热门标签 | HotTags
当前位置:  开发笔记 > 后端 > 正文

基于API函数的串口通信编程(转载)

基于API函数的串口通信编程用到的串口通信编程方法有:使用通信控件、在高级语言中嵌入汇编以及使用API函数。在这几种方法中&

基于API函数的串口通信编程

 

 

 

用到的串口通信编程方法有:使用通信控件、在高级语言中嵌入汇编以及使用API函数。在这几种方法中,使用API函数编写的串口通信程序最为高效、灵活。串口通信编程将用到三种API函数——串口通信相关API函数、多线程API函数和实现消息机制的API函数,下面将分别介绍这几种API函数。

1 与串口通信有关的API函数

  Windows系统通信一般都以WOSA(Windows Open Services Architecture,即Windows开放式服务体系)模型为基础,在此模型中位于上层的应用程序通过调用各种通信API与位于下层的设备驱动程序进行数据交换。下面将按一般串口通信程序的流程顺序介绍这些API函数。

  1.1 打开串口

  Win32操作系统把串口看作一个文件,因此打开串口我们将要用到CreateFile函数。该函数第一个参数指明要打开的文件名称,对串口操作来说,就是COM1、COM2等。第二个参数为读写模式设置,因为要对串口进行读写,所以该参数应设为GENERIC_READ|GENERIC_WRITE。第三个参数值必须为0,表示不将串口与其他应用程序共享。第四个参数指向一个Security Attribute结构,通常设为NULL。第五个参数指定如何打开文件,在打开设备(串口是一种设备)时,此参数必须指定为OPEN_EXISTING。第六个参数指定文件属性及相关标  志,但是对于串行口,唯一有意义的设置是FILE_FLAG_OVERLAPPED或0;最后一个参数必须为NULL。若该函数打开串口成功,则返回创建的句柄,该句柄供随后对串行口的设置、读写等操作用;否则返回INVALID_HANDLE_VALUE。

  1.2 设置串口

  串口打开后,即可进行一系列初始化设置。最基本的初始化设置将通过GetCommState和SetCommState函数来实现。先调用GetCommState函数获取当前串口配置填充设备控制块(DCB),然后将DCB结构中几个重要参数如波特率、数据位、停止位、校验位改成符合实际设计要求的值,最后用SetCommState将刚刚所做的改动重新设置串口。串口I/O缓冲区的大小用SetupComm函数设置。通信速率越高,缓冲区应设置得越大,但不能超出设备驱动程序所能 处理的范围。另一个很重要的设置是串口超时设置。通信中因未知原因将出现不可预测的事件,譬如:接收数据过程中突然被中断,或者发送数据突然停止等。如果不认真对待,这些情况可能会引起I/O线程挂起或者线程被无限阻塞。Windows对于这类问题提供了安全措施,它可通过超时设置来决定通信是否异常并作相应处理,因此超时设置在串行通信中显得尤为重要。超时设置过程分为两步,首先设置Commtimeouts结构中的五个成员,然后调用SetCommTimeouts函数设置超时值。Commtimeouts结构的五个成员分别是:读串口间隔超时、读串口总超时乘数、读串口总超时常数(ms)、写串口总超时乘数、写串口总超时常数(ms)。

  1.3 读写串口

  设置工作完成后,即可用ReadFile和WriteFile对串口进行读写操作。在调用读写操作函数之前,应先用ClearCommError函数清除错误标志和获取当前串口状态。读写操作分为同步和重叠I/O(异步)。同步执行时,函数直到操作完成后才返回;重叠I/O操作时,即使操作尚未完成,调用的函数也会立即返回,费时的I/O操作在后台进行。可见,同步操作线程被阻塞,效率低,只能用在对通信要求比较低的场合,我们一般用到的都是效率较高的重叠I/O操作。前面提到的CreateFile函数第六个参数设置为FILE_FLAG_OVERLAPPED即可指定Read File和WriteFile函数为重叠I/O执行。使用重叠I/O还需为读写函数指定一个Overlapped结构,该结构有五个数据成员,对串口通信来说,其中的Offset和hEvent成员是很重要的。Offset指示文件指针偏移量,在重叠I/O操作时系统不能自动维护文件指针,所以要靠Offset在程序中手动调整文件指针。而hEvent标志读写操作是否完成。若操作完成,

 

  则将hEvent置为信号态;否则即置为非信号态。最后要说明的是,在重叠I/O操作时,读写函数返回值是FALSE并不能说明操作失败,应该调用GetLastError函数分析返回结果。如果 此时GetLastError函数返回值是ERROR_IO_PENDING,则说明操作未完成(并不是操作失败)。我们将用等待函数来等待操作的完成。典型的两个等待函数有WaitForSingleObject和GetOverlappedResult。函数的相同之处为都是等待读写操作指定的Overlapped结构hEvent成员置为信号态(即代表操作完成);不同之处是WaitForSingleObject是可设置超时,但无法得到重叠I/O操作的结果,GetOverlappedResult用来得到重叠I/O操作的结果,但无法设置超时。因此,我们经常两者结合起来使用,在用WaitForSingleObject等待操作结束后,用GetOverlap-pedResult得到操作结果。

  1.4 关闭串口

  串行口是非共享资源,某应用程序打开串行口后,即独占该资源,使其它应用程序无法再访问,直到该应用程序释放串口。所以对串口操作完成后,一定要关闭串口。关闭串口使用CloseHandle函数,该函数唯一参数即为用CreateFile打开串口时所创建的句柄。

  2 多线程API函数

  Windows是多线程(multi-threaded)、抢先多任务的(preemptible )。Windows中,一个可执行程序的运行时刻实例称为进程(process)。一个进程可以有多个线程(thread),Windows是按照线程分配CPU时间片的,而分配的机制就是抢先多任务方式。

  对于读写串口这种耗时的工作,使用多线程技术,创建辅助线程来管理串口是一个常用的方案。这样在进行串口读写的同时,能对读入的数据进行处理。如果使用单线程,就需要等待串口读写操作完成,整个进程都被阻塞。而使用多线程就可以避免这种情况。

  多线程也会带来一些新的问题,其中的一个问题就是线程的同步,如果同步问题解决不好,程序的稳定性会受到很大的影响。通常用到的几种线程同步的方法有互斥体对象(Mutex)、利用信号(Semaphore)、利用事件对象(Event)和设置临界区(Critical Section)。笔者在实际应用中使用的是事件对象结合Windows消息机制使线程同步,收到了很好的效果。

  创建线程函数为CreateThread,用SuspendThread和ResumeThread函数来挂起和唤醒线程。创建事件函数为CreateEvent,用SetEvent和ResetEvent函数来将事件置为信号态和非信号态,以此来同步线程。串口通信的辅助线程管理经常还要用到SetCommMask和WaitCommEvent函数。SetCommMask用来指定一系

 

  列事件监视串口,比如监视串口是否有数据收到;WaitCommEvent则用来等待指定的事件发生。笔者在实际应用中,就是在辅助线程中用SetCommMask指定串口监视接收数据事件,然后用WaitCommEvent等到串口真的接收到数据时,用PostMessage发出消息通知主线程,由主线程处理接收到的数据。

  3 实现消息机制的API函数

  Windows是一个消息驱动操作系统,简单的说消息就是指通过输入设备向程序发出的指令以要求

 

  其执行某个操作。具体的操作由消息处理函数实现。用户可以自定义消息在线程之间传递。把WM_USER(它的值等于0×0400)当作基数,然后顺序地去加序号,譬如:

  WM_COMMNOTIFY equ WM_USER+100h(小于WM_USER的值是Windows系统的保留值,大于该值留给用户来使用)。

  前一节已经提到在串口通信编程中对消息机制的利用,这里将继续说明怎样实现消息机制。由于笔者使用的编程工具是Borland公司的C++ Builder(BCB),因此对于消息机制的实现有其特殊之处。在BCB中实现消息的方法有三种:使用消息映射Message Map重载TObject的Dispatch虚成员函数;重载TControl的WndProc方法;重载Appli

 

  cation的OnMessage方法。其中以第三种方法最快,因为一般情况下,BCB会为每个程序自动生成一个TApplication类的实例,消息到达BCB程序时,最先得到它们的就是TApplication对象。经由TApplication之后,才传递给Form的。前两种方法都是重载TForm的方法,显然比直接重载Application的OnMessage方法要晚一些收到消息。我们要做的只是定义好自己的消息处理函数:

  void __fastcall TForm1MyOnMessagetagMSG &Msg

bool &Handled

  

  TMessage Message

  switch(Msg.message)

  

  case WM_COMMNOTIFY

  Message.Msg=Msg.message;

  Message.WParam=Msg.wParam;

  Message.LParam=Msg.lParam;

  //此处添加处理该消息的代码

  Handled=true;

  break;

    

  

  然后在窗口创建时用自定义的消息处理函数重载Application的OnMessage方法:

  void __fastcall TForm1FormCreate(TObject Sender)

  

  Application->OnMessage = MyOnMessage;

  

  这样就可以在程序中收到自定义的消息并作出相应处理。

值得注意的是,使用Application->OnMessage并不能捕获非队列消息,它无法捕获使用SendMessage直接发送给窗口的消息,这是因为其不通过消息队列。但可以使用另一个发送消息的API函数——PostMessage,该函数发出的消息是队列消息。

 

  4 结束语

  利用多线程、消息机制和重叠I/O的API函数进行串口编程的方法,可实现串口通信的实时高效,为开发Windows系统下串口驱动程序提供了有益参考。&

  参考文献

  1 范逸之.江文贤.陈立元.C++ Builder与RS-232串行通信控制[M].清华大学出版社,2002

  2 黄军等.Delphi串口通信编程[M].人民邮电出版社,2001

3   张志明.李蓉艳.王磊.WIN32环境下串行通信编程技术研究[J].《计算机应用研究》 2002;9

 

转:https://www.cnblogs.com/enterBeijingThreetimes/archive/2008/12/18/1357550.html



推荐阅读
  • 面试题总结_2019年全网最热门的123个Java并发面试题总结
    面试题总结_2019年全网最热门的123个Java并发面试题总结 ... [详细]
  • 本文详细介绍了 Java 网站开发的相关资源和步骤,包括常用网站、开发环境和框架选择。 ... [详细]
  • IOS Run loop详解
    为什么80%的码农都做不了架构师?转自http:blog.csdn.netztp800201articledetails9240913感谢作者分享Objecti ... [详细]
  • Java EE 平台集成了多种服务、API 和协议,旨在支持基于 Web 的多层应用程序开发。本文将详细介绍 Java EE 中的 13 种关键技术规范,帮助开发者更好地理解和应用这些技术。 ... [详细]
  • 阿里云 Aliplayer高级功能介绍(八):安全播放
    如何保障视频内容的安全,不被盗链、非法下载和传播,阿里云视频点播已经有一套完善的机 ... [详细]
  • 小程序的授权和登陆
    小程序的授权和登陆 ... [详细]
  • Cookie学习小结
    Cookie学习小结 ... [详细]
  • 本文将深入探讨 iOS 中的 Grand Central Dispatch (GCD),并介绍如何利用 GCD 进行高效多线程编程。如果你对线程的基本概念还不熟悉,建议先阅读相关基础资料。 ... [详细]
  • 2020年9月15日,Oracle正式发布了最新的JDK 15版本。本次更新带来了许多新特性,包括隐藏类、EdDSA签名算法、模式匹配、记录类、封闭类和文本块等。 ... [详细]
  • JUC(三):深入解析AQS
    本文详细介绍了Java并发工具包中的核心类AQS(AbstractQueuedSynchronizer),包括其基本概念、数据结构、源码分析及核心方法的实现。 ... [详细]
  • Python 数据可视化实战指南
    本文详细介绍如何使用 Python 进行数据可视化,涵盖从环境搭建到具体实例的全过程。 ... [详细]
  • 在多线程并发环境中,普通变量的操作往往是线程不安全的。本文通过一个简单的例子,展示了如何使用 AtomicInteger 类及其核心的 CAS 无锁算法来保证线程安全。 ... [详细]
  • C语言是计算机科学和编程领域的基石,许多初学者在学习过程中会感到困惑。本文将详细介绍C语言的基本概念、关键语法和实用示例,帮助你快速上手C语言。 ... [详细]
  • 本文总结了Java初学者需要掌握的六大核心知识点,帮助你更好地理解和应用Java编程。无论你是刚刚入门还是希望巩固基础,这些知识点都是必不可少的。 ... [详细]
  • 双指针法在链表问题中应用广泛,能够高效解决多种经典问题,如合并两个有序链表、合并多个有序链表、查找倒数第k个节点等。本文将详细介绍这些应用场景及其解决方案。 ... [详细]
author-avatar
嘻嘻2502891803
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有