掌握串行通信API函数的用法是掌握串行通信编程技术的关键。

在Win32中,系统将串行口与文件统一了起来, 对它们的打开、读写、关闭等操作都使用相同的API函数,但是它们之间又有差别,这些差别主要体现在API函数中部分参数的设置上。有关通信的API主要包括打开串口、关闭串口、配置串口、设置缓冲区、设置超时、 事件驱动、读串口、写串口等。下面结合GPS的具体情况对串口操作函数的使用方法进行详细的介绍和分析。

一:串口的打开和关闭

1:串口的打开。由于在Windows环境中,串口作为一种文件来使用,打开串口用打开文件同样的API函数 CreateFile()。

函数原型为:  HANDLE CreateFile( LPCTSTR lpFileName,

DWORD dwDesiredAccess,

DWORD dwShareMode,

LPSECURITY_ATTRIBUTES lpSecurityAttributes,

DWORD dwCreationDisposition,

DWORD dwFlagsAndAttributes,

HANDLE hTemplateFile

);

其中几个参数的含义分别为: lpFileName 指定文件名或设备名,串口通讯时,它必须是“COMx”,其中的“x”为串口编号,如第一个串口则为“COM1”;

dwDesiredAccess 为串口读写属性; dwShareMode指定该端口的共享属性,串行口不能作为共 享设备,故参数值必须为0;lpSecurityAttributes为安全属性,对于串口应该为0 ; dwCreationDisposition指文件的创建模式,对于串口必须为OPEN—EXISTING; dwFlagsAndAttributes描述了创建文件的其它属性,对于串行口,有效的设置只能是FILE-FLAG-OVERLAPPED 或者0,分别表示异步或同步读写; 参数hTemplateFile必须为NULL。
          返回值:若成功,返回创建的句柄;否则返回INVALID—HANDLE—VALUE。

2:串口的关闭。 关闭串口相对简单,通过关闭句柄BOOL CloseHandle(HANDLE hObject )函数进行, hObject为打开串口时所得到的句柄。句柄关闭后,串口资源即释放,其它程序可以使用。

二:配置串口

串行口在打开后,将保持上一次使用的配置,要使之和外设进行通信,必须对串口进行配置,使之和外设保持相同的串口配置,这样才能有效地配置外设并接收数据。

在WIN32中,串口的配置主要通过一个称之为 COMMCONFIG的结构来实现,此结构包含了一个DCB结构,在DCB中,有波特率、数据位数、停止位、校验位等串
行口通信参数,对串口的配置主要即是对这些参数的配置。

对COMMCONFIG进行配置的WIN32 API 主要有一下几 个:

1:获取默认配置函数。其原型为: BOOL GetDefaultCommConfig( LPCSTR lpszName,

LPCOMMCONFIG lpCC,

LPDWORD lpdwSize)

其参数如下: LpszName为设备名,如“COM1”; lpCC为COMMCONFIG结构体的指针。 LpdwSize是lpCC的大小。

通过使用此函数可以得到某串口的默认配置,此函数与机器硬件相关,在不同的机器上会有不同的结果,因而容易出错,所以建议用户自己重写此函数,分别对COMMCONFIG的成员进行赋值,这样才稳定可靠。

2:得到串口的当前配置,原形如下: BOOL GetCommConfig( HANDLE hCommDev, LPCOMMCONFIG lpCC, LPDWORD lpdwSize )

其参数同GetDefaultCommConfig();

3:配置串口 BOOL SetCommConfig( HANDLE hCommDev,LPCOMMCONFIG lpCC, DWORD dwSize);

此函数将由hCommDev指定的串口按lpCC结构体中的内容进行配置。LPCOMMCONFIG结构体中的主要成员是设备控制块结构DCB,在DCB中指定了设备的波特率,奇偶校验位,流控,停止位等参数。

4:配置串口的对话框 BOOL CommConfigDialog(LPCSTR lpszName,HWND hWnd,LPCOMMCONFIG lpCC )

此函数提供了一个用户熟悉的串口配置对话框,其句柄为hWnd。用户可在此对话框中进行对lpszName指示的串口配置,配置结果存放在lpCC所指向的COMMCONFIG结构体中。

5:设置缓冲区 WIN32环境下读写串口已经不是传统方式下针对串口的UART进行,而是提供一缓冲区,串口的读写都是针对于此缓冲区进行。

确定缓冲区的大小比较重要,太大浪费资源,太小又会使有效数据丢失。用户必须在串口读写前计算出外设流量的大小,按照宁大勿小、有所冗余的原则确定合适大小的缓冲区,再使用SetupComm()函数对串口进行设置。

其原型如下: BOOL SetupComm(HANDLE hFile,DWORD dwInQueue,DWORD dwOutQueue);

hFile为打开串口时所得到的句柄; dwInQueue为输入缓冲区的大小,以字节为单位; dwOutQueue为输出缓冲区的大小。

6:设置超时

数据通信过程中可能会发生的不可预测的事件,如数据传输电缆损坏、外设意外失效中断,或者发送数据突然停止等等。通信应用程序的一个关键问题就是如何处理通信中的不可预测的事件,处理错误事件的能力是一个通信应用程序优劣的重要标志。这些问题处理的不好可能会引起I/O线程挂起或者线程被无限阻塞。

Windows对于这类问题提供了安全措施,用户可以通过超时设置来决定通信是否异常并作相应处理。因此超时设置在串行通信中显得尤为重要。

在Win32中提供了SetCommTimeouts()函数设置串口的超时值。

BOOL SetCommTimeouts(HANDLE hFile, LPCOMMTIMEOUTS lpCommTimeouts);

hFile为打开串口时所得到的句柄; lpCommTimeouts为指向超时结构体的指针。

三:读写串口

在打开串口并对其进行正确地和必要的配置后就可以用它进行通信即读写数据。读数据就是接收输入,写数据就是向外设发送数据。读写数据通过两个API函数完成。

1:读数据函数     BOOL ReadFile ( HANDLE hFile,

LPVOID lpBuffer,

DWORD nNumberOfBytesToRead,

LPDWORD lpNumberOfBytesRead,

LPOVERLAPPED lpOverlapped);

hFile是由CreateFile()返回的句柄; lpBuffer是读取的数据缓冲区指针; nNumberOfBytesToRead是要读取的字节数; lpNumberOfBytesRead是实际读取的字节数的首地址; lpOverlapped 是指向一个可重叠I/O(异步)的数据结构指针。如果lpOverlapped设置为NULL,则ReadFile()工作在同步方式;如果lpOverlapped指向一个重叠结构,则工作在异步方式。不管是同步还是异步, ReadFile()函数执行后将立刻返回。

2:写串口函数     BOOL WriteFile( HANDLE hFile,

LPVOID lpBuffer,

DWORD nNumberOfBytesToRead,

LPDWORD lpNumberOfBytesRead,

LPOVERLAPPED lpOverlapped);

其参数的意义与读串口相似。

四:工作模式

在串口读写操作时,存在多种操作模式,从同步控制角度讲,有同步和异步方式,从编程角度讲,有查询方式和事件驱动方式。

在同步读串口时,如果串口缓冲区中内容没有读完,系统将处于等待状态,直至读完才返回;如果是异步读,即使缓冲区中没有读完,系统也将下行,执行下一句代码。如果串口的交互频繁,则宜使用异步读写,但对于一般采集而言,主要是读数据,写命令不多,一次读取的数据量又不会太大,所以使用同步较好,更易于控制。

查询方式是指在一个无穷循环中直接读写串口数据,对于从串口读取数据来说,查询是最为直接、最简单的方法,但是这种方法效率较低,要花费大量的CPU时间。

事件驱动方式是指线程通过监视通信资源中的一组事件来进行读写操作,这种方式类似于DOS下的中断工作方式,效率高。监视事件的工作是通过SetCommMask()和WaitCommEvent()函数进行的。在读或写操作中可以通过SetCommMask()函数设置事件屏蔽来监视指定通信资源上的事件,指定一组事件后,线程可以使用WaitCommEvent()函数等待其中一个事件发生,在等待过程中线程将挂起,这样将花费极少的CPU时间,一旦有相应事件发生,WaitCommEvent()将返回, 告诉系统发生的事件,用户可以根据事件的内容确定相应的处理方式。在等待事件时,WaitCommEvent()函数将独占串口,此时串口既不能读也不能写,读写工作必须等WaitCommEvent()函数返回后进行。

设置同步控制模式在打开串口时进行,由其第三个参数指定。 而在编程时采用事件驱动模式的函数有以下几个。

1:设置事件掩码   BOOL SetCommMask(HANDLE hFile,DWORD dwEvtMask);

其中hFile为打开串口的文件句柄。 DwEvtMask是设置的掩码,其形式和意义如下表所示

掩码                               事件

EV_BREAK                   在输入中检测到断点

EV_CTS                        CTS (clear-to-send) 信号改变状态

EV_DSR                        DSR (data-set-ready) 信号改变状态

EV_ERR                        出现线路状态错误

EV_RING                       检测到振铃指示

EV_RLSD                      RLSD (receive-line-signal-detect) 信号改变状态

EV_RXCHAR                 一个字符到达并存放于接收缓冲区

EV_RXFLAG                  一个事件字符到达并存放于接收缓冲区,事件字符包含在设备的DCB中,由SetCommState 函数应用到串口

EV_TXEMPTY                发送缓冲区中的最后一个字符被送出

2:等待事件到来

BOOL WaitCommEvent(HANDLE hFile,DWORD dwEvtMask,LPOVERLAPPED lpOverlapped);

其参数意义与设置掩码相似。这个函数表示等待由SetCommMask()函数设置的事件的到来,在此函数工作时,串口处于阻塞模式独占串口。 如果定义的事件到来,我们就可以采取相应的措施来处理。在数据采集时,通常设置的事件为: EV_RXCHAR,在此事件到来时就可以读出接收缓冲区中的数据并交给后台线程处理。 如果使用的串口不止一个,则需要利用Win32的多任务特性。

COMMCONFIG进行配置的WIN32 API相关推荐

  1. java 调用win32 api 学习总结

    java使用JInvoke调用windows API 使用jinvoke调用windowsAPI.jna使用比较麻烦,需要写c代码和参数转换,jinvoke的使用就像jdk中的包一样. 官网使用参考: ...

  2. 深入浅出VC++串口编程之基于Win32 API

    1.API描述 在WIN32 API中,串口使用文件方式进行访问,其操作的API基本上与文件操作的API一致. 打开串口 Win32 中用于打开串口的API 函数为CreateFile,其原型为: H ...

  3. VC++中忽略所有默认库纯Win32 API编译及链接 - 计算机软件编程 - Wangye's Space

    原始链接: VC++中忽略所有默认库纯Win32 API编译及链接 - 计算机软件编程 - Wangye's Space 我们在用VC++编写Windows程序的时候可能会发现一般可执行体(.EXE) ...

  4. 深入浅出VC++串口编程--基于Win32 API

    1.API描述 在WIN32 API中,串口使用文件方式进行访问,其操作的API基本上与文件操作的API一致. 打开串口 Win32 中用于打开串口的API 函数为CreateFile,其原型为: H ...

  5. Win32 API 概论

    1.1为什么使用 Win32 API 在Windows程序设计领域处于发展初期时,Windows程序员可使用的编程工具唯有API函数.这些函数在程序员手中犹如"积木块"一样,可搭建 ...

  6. Win32 API概论

    1.1为什么使用 Win32 API 在Windows程序设计领域处于发展初期时,Windows程序员可使用的编程工具唯有API函数.这些函数在程序员手中犹如"积木块"一样,可搭建 ...

  7. WIN32 API串口通信编程

    WIN32 API串口通讯实例教程 第一节实现串口通讯的函数及串口编程简介 API函数不仅提供了打开和读写通讯端口的操作方法,还提供了名目繁多的函数以支持对串行通讯的各种操作.常用函数及作用下: 函数 ...

  8. C++ 纯WIN32 API编程 悦读器实战示例

    /* 最后修改:2020-09-21 14:04 <C++编程示例大全> 作者:张国鹏 本例功能:C++ 纯WIN32 API编程 悦读器实战示例 软件下载:http://lovegp.c ...

  9. Win32 API 打印

    重温 Win32 API ----- 截屏指定窗口并打印 http://blog.csdn.net/smstong/article/details/42082039 朋友说在一个VC++6.0开发的项 ...

最新文章

  1. JSP实现医院住院管理系统
  2. iOS 9应用开发教程之使用开关滑块控件以及滚动部署视图
  3. 八、H.264中的熵编码基本方法、指数哥伦布编码
  4. volley框架下发送和读取cookie
  5. 【学习】Android开入门教程
  6. 怎样远程连接服务器后上传文件,远程登录服务器后怎样上传文件
  7. 手把手教你使用C#操作SQLite数据库,新建数据库,创建表,插入,查询,删除,运算符,like...
  8. 给某社区技术写作大赛当评委,我的个人资料
  9. r语言 分类变量 虚拟变量_R语言中的变量
  10. Codeforces Round #371 (Div. 2) C. Sonya and Queries —— 二进制压缩
  11. Netty工作笔记0027---NIO 网络编程应用--群聊系统2--服务器编写2
  12. 【Codeforces】Gym 101173B Bipartite Blanket 霍尔定理+状压DP
  13. 高中电子技术——电弧抑制电路
  14. Windows Phone SDK 7.1 简体中文版离线安装包地址
  15. 2021-06-27 对象类型详解.
  16. 大学生心理健康管理系统
  17. 非极大值抑制法(NMS,non-maximum suppression)
  18. 小爱同学指令大全_小爱同学有趣的命令分享给大家
  19. windows自带备份驱动
  20. 文件及代码代码命名规则

热门文章

  1. java中上传文件_Java中文件上传下载 --使用Minio
  2. kafka 启动_「首席看Event Hub」如何在您的Spring启动应用程序中使用Kafka
  3. php调取 zabbix实时数据_Linux运维必知的Zabbix故障排错实战
  4. hashmap remove 没释放内存_面试题:来,问你几个关于HashMap的问题?
  5. 第四十二篇 面对对象进阶
  6. 基于ISE的设计实现基础
  7. HOJ 2278 IP Filtering (二分)
  8. 解释一下python中的//,%和**运算符
  9. Unix/Linux操作系统中如何在sqlplus/rman中使用方向键
  10. 现在的人工智能逆天到什么地步了?