Windows串口编程
1.串行接口是采用串行通信方式的扩展接口,将数据一位一位地顺序传送。
2.基本概念
(1) RS232电平和TTL电平
电平信号是用信号线电平减去参考线电平得到的电压差,这个电压差决定了传输值是1还是0。在电平信号中多少V代表1,多少V代表0是不固定的,取决于点评标准。例如:RS232电平中-15V ~ -3V表示1,+3V ~ +15V代表0;TTL电平中+5V表示1,0V表示0。
不管哪种电平都是为了在传输线上表示1和0,区别在于适用的环境和条件不同。RS232电平适合干扰大、距离远的情况,一般传输距离小于15米,用于工业上;TTL电平适合距离近且干扰小的情况,一般用在电路板内部的两个芯片之间。对于编程来说,RS232电平传输和TTL电平传输是没有差异的。TTL电平和RS232电平混接是不可以的。
(2) 波特率指的是串口通信的速率,也就是串口通信时每秒钟可以传输多少个二进制位。串口通信的波特率不能随意设定,而应该是在一些值中去选择。一般最常见的波特率是9600或115300(低端单片机如51常用9600,高端单片机和嵌入式SOC常用115200)。
波特率不能随意指定,主要是因为:通信双方必须事先设定相同的波特率才能成功通信,如果发送方和接收方按照不同的波特率通信根本收不到,因此波特率最好是常用的9600或者115200。
(3) 串口通信时,收发是一个周期一个周期进行的,每个周期传输n个二进制位。这一个周期就叫做一个通信单元,一个通信单元由:起始位 + 数据位 + 奇偶校验位 + 停止位组成。
串口通信时因为是异步通信,所以通信双方必须事先约定好通信参数,这些通信参数包括:波特率、数据位、校验位、停止位。
3.在Win32位的windows系统中,有两种编程方式实现串口通信:
(1) 使用ActiveX控件,这种方法程序简单,但欠灵活。
(2) 调用Win32API函数,这种方法可以清楚的掌握串口通信机制,并且自由灵活。
4.串口的操作可以有两种操作方式:
(1) 同步操作方式
同步操作时,API函数会阻塞直到操作完成以后才能返回(在多线程方式中,虽然不会阻塞主线程,但是仍然会阻塞监听线程)。
(2) 重叠操作方式 (又称为异步操作方式)
重叠操作方式,API函数会立即返回,操作在后台进行,避免线程的阻塞。
5.操作步骤
(1) 打开串口
Win32系统把文件的概念进行了扩展。无论是文件、通信设备、命名管道、邮件槽、磁盘还是控制台,都是用API函数CreateFile来打开或创建的。
HANDLE CreateFile (LPCTSTR lpFileName, // 串口逻辑名,如"COM1"或"\\\\.\\COM10"
DWORD dwDesiredAccess, // 串口访问类型,可以是读取、写入或者两者并列
DWORD dwShareMode, // 共享属性,由于串口不能共享,该参数必须为0
LPSECURITY_ATTRIBUTES lpSecurityAttributes, // 引用安全性树形结构,缺省值为NULL
DWORD dwCreationDistribution, // 创建标志,该参数必须设置为OPEN_EXISTING
DWORD dwFlagsAndAttributes, // 属性描述,指定串口是否进行异步操作: FILE_FLAG_OVERLAPPED,异步的I/O;0,同步I/O操作
HANDLE hTemplateFile // 对于串口而言该参数必须为NULL
);
HANDLE hCom = CreateFile("COM3", GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
(2) 配置串口
1> DCB结构:
在打开通讯设备句柄后,需要对串口进行一些初始化配置工作。通过DCB结构来进行,DCB结构包含了波特率、数据位数、奇偶校验和停止位数等信息。在查询或配置串口的属性时,都要用DCB结构来作为缓冲区。在调用CreateFile打开串口后,可以调用GetCommState函数来获取串口的初始配置,若修改串口的配置,应该先修改DCB结构,然后再调用SetCommState函数设置串口。
BOOL GetCommState(
HANDLE hFile, // 通信设备句柄
LPDCB lpDCB // 指向一个设备控制块(DCB结构)的指针
);
BOOL SetCommState(
HANDLE hFile, // 通信设备句柄
LPDCB lpDCB // 指向一个设备控制块(DCB结构)的指针
);
2> I/O缓冲区
Windows用I/O缓冲区来暂存串口输入和输出的数据。如果通信的速率较高,则应该设置较大的缓冲区。调用SetupComm函数可以设置串行口的输入和输出缓冲区的大小
BOOL SetupComm(
HANDLE hFile, // 通信设备句柄
DWORD dwInQueue, // 输入缓冲区的大小 (字节数)
DWORD dwOutQueue // 输出缓冲区的大小 (字节数)
);
3> 超时问题
在使用ReadFile和WriteFile读写串行口时,需要考虑超时问题。超时的作用是在指定的时间内没有读入或发送指定数量的字符,ReadFile或WriteFile的操作仍然会结束。要查询当前的超时设置应调用GetCommTimeouts函数,该函数会填充一个COMMTIMEOUT结构。调用SetCommTimeouts可以用某一个COMMTIMEOUTS结构的内容来设置超时。
BOOL GetCommTimeouts(
HANDLE hFile,
LPCOMMTIMEOUTS lpCommTimeouts
);
BOOL SetCommTimeouts(
HANDLE hFIle,
LPCOMMTIMEOUTS lpCommTimeouts
);
读写串口的超时有两种:
间隔超时:在接收时两个字符之间的最大时延。
总超时:指读写操作总共花费的最大时间。
写操作只支持总超时,而读操作两种超时均支持。
typedef struct _COMMTIMEOUTS{
DWORD ReadIntervalTimeout; // 读间隔超时
DWORD ReadTotalTimeoutMultiplier; // 读时间系数
DWORD ReadTotalTimeoutConstant; // 读时间常量
DWORD WriteTotalTimeoutMultiplier; // 写时间系数
DWORD WriteTotalTimeoutConstant; // 写时间常量
}COMTIMEOUTS, *LPCOMMTIMEOUTS;
COMMTIMEOUTS结构的成员都以毫秒为单位。
总超时计算公式:总超时 = 时间系数 X 要求读/写的字符数 + 时间常量
如果所有写超时参数均为0,那么就不使用写超时。如果ReadIntervalTimeout为0,那么就不适用读间隔超时。如果ReadTotalTimeoutMultiplier和ReadTotalConstant都为0,则不适用读总超时。如果读间隔超时被设置成MAXDWORD并且读时间系数和读时间常量都为0,那么在读一次输入缓冲区的内容后读操作就立即返回,而不管是否读入了要求的字符。
在用重叠方式读写串口时,虽然ReadFile和WriteFile在完成操作以前就可能返回,但超时仍然是起作用的。在这种情况下,超时规定的是操作的完成时间,而不是ReadFile和WriteFile的返回时间。
在读写串口之前,还要用PurgeComm()函数情况缓冲区
BOOL PurgeComm(
HANDLE hFile, // 通信设备句柄
DWORD dwFlags // 需要完成的操作
);
参数dwFlags指定要完成的操作,可以是下列值的组合:
PURGE_TXABORT 中断所有写操作并立即返回,即使写操作还没有完成
PURGE_RXABORT 中断所有读操作并立即返回,即使读操作还没有完成
PURGE_TXCLEAR 清除输出缓冲区
PURGE_RXCLEAR 清除输入缓冲区
(3) 读写串口
BOOL ReadFile(
HANDLE hFIle, // 通信设备句柄
LPVOID lpBuffer, // 读入的数据存储的地址,即读入的数据将存储在以该指针的值为首地址的一片内存区
DWORD nNumberOfBytesToRead, // 要读入的数据的字节数
LPDWORD lpNumberOfBytesRead, // 指向一个DWORD数值,该数值返回读操作实际读入的字节数
LPOVERLAPPED lpOverlapped // 重叠操作时,该参数指向一个OVERLAPPED结构,同步操作时,该参数为NULL
);
BOOL WriteFile(
HANDLE hFile, // 通信设备句柄
LPCVOID lpBuffer, // 写入的数据存储的地址,即以该指针的值为首地址的nNumberOfBytesToWrite个字节的数据将要写入串口的发送数据缓冲区
DWORD nNumberOfBytesToWrite, // 要写入的数据的字节数
LPDWORD lpNumberOfBytesWritten, // 指向一个DWORD数值,该数值返回实际写入的字节数
LPOVERLAPPED lpOverlapped // 重叠操作时,该参数指向一个OVERLAPPED结构,同步操作时,该参数为NULL
);
在用ReadFile和WriteFile读写串口时,既可以同步执行,也可以重叠执行。在同步执行时,函数直到操作完成后才返回。这意味着同步执行时线程会被阻塞,从而导致效率下降。在重叠执行时,即使操作还未完成,这两个函数也会立即返回,费时的I/O操作在后台进行。
ReadFile和WriteFile函数是同步还是异步由CreateFile函数决定,如果在调用CreateFile创建句柄时指定了FILE_FLAG_OVERLAPPED标志,那么调用ReadFile和WriteFile对该句柄进行的操作就应该是重叠的;如果未指定重叠标志,则读写操作应该是同步的。ReadFile和WriteFile函数的同步或者异步应该和CreateFile函数相一致。
ReadFile函数只要在串口输入缓冲区中读入指定数量的字符,就算完成操作。而WriteFile函数不但要把指定数量的字符拷入到输出缓冲区,而且要等这些字符从串行口送出去后才算完成操作。如果操作成功,这两个函数都返回TRUE。需要注意的是,当ReadFile和WriteFile返回FALSE时,不一定就是操作失败,线程应该调用GetLastError函数分析返回的结果。例如,在重叠操作时如果操作还未完成函数就返回,那么函数就返回FALSE,而且GetLastError函数返回ERROR_IO_PENDING。这说明重叠操作还未完成。
(4) 关闭串口
void CloseHandle(HANDLE hFIle); // 关闭通信设备句柄
Windows串口编程相关推荐
- Windows串口编程:使用非标准波特率
文章目录 前言 1. 创建一个对话框 2. Windows下使用非标准波特率 2.1获取串口号 2.2 获取设置的非标波特率 2.3 打开串口 前言 我们在使用USB转串口设备进行通讯时候,常用的标准 ...
- windows 串口编程 c语言,windows下C语言版串口发送程序(基于VS2017)
#include "tchar.h" #include int main() { /*****************************打开串口*************** ...
- windows API 串口编程参考
*************************************************** 更多精彩,欢迎进入:http://shop115376623.taobao.com ****** ...
- 串口编程 - windows如何枚举串口|获取活跃串口号
串口编程 - windows如何枚举串口|获取活跃串口号 如需转载请标明出处:http://blog.csdn.net/itas109 QQ技术交流群:129518033 文章目录 串口编程 - wi ...
- windows中Python串口编程(一)
在windows中,使用python进行串口编程需要安装一个Serial模块 pyserial: 下载地址:https://pypi.python.org/pypi/pyserial 下载完成后得到一 ...
- Wince C++串口编程
C# 串口操作系列:http://blog.csdn.net/wuyazhe/article/category/695097 在windows程序设计与开发过程中,特别是涉及到开发嵌入式软硬件系统时, ...
- VirtualBox Ubuntu虚拟机串口编程
VirtualBox Ubuntu虚拟机串口编程 此文适用于Ubuntu虚拟机实现串口通信,可以在虚拟机上运行程序,直接将windows下的串口映射到虚拟机上即可.在网上找了半天,没有找到合适的教程, ...
- 用户方式中线程的同步——Windows核心编程学习手札之八
用户方式中线程的同步 --Windows核心编程学习手札之八 系统中所有线程都必须拥有对各种系统资源的访问权,这些资源包括内存堆栈.串口.文件.窗口和许多其他资源.如果一个线程需要独占对资源的访问权, ...
- CSerialPort多线程串口编程工具详解
1.前言 既然有了MSComm这种简单粗暴的控件,为什么还需要CSerialPort类?这是因为与前者相比,这个类在程序的发布上不需要加入其他的文件,而且CSerialPort提供给我们的函数都是开放 ...
最新文章
- 万万没想到,我居然在机器人大会遇到了这些奇葩物种
- zabbix聚合图形创建脚本
- webpack 入口文件 php,webpack,jsx_webpack jsx 找不到入口文件,webpack,jsx - phpStudy
- 指针学习笔记(更新中)
- Nmap Windows 版本时区显示乱码
- 「服务端」node服务的监控预警系统架构
- transpose公式_EXCEL转置你是用公式还是选择性粘贴?
- Exception in thread main java.lang.NoClassDefFoundError
- Linux学习总结(28)——Linux主机加固
- linux查看图片的拍摄时间,ImageMagick 的一些高级图片查看技巧 | Linux 中国
- 声智科技陈孝良:没有好的语音数据收集,语音识别和交互不可能做好
- 【渝粤教育】电大中专建筑力学 (2)作业 题库
- ARMA 模型的参数估计 —— 增广最小二乘法
- 2009年考研数学一解析pdf
- Cadence PSpice 补充1:脉冲信号源的详细介绍与使用方法图文演示
- 海外网红营销是战略还是战术?从“PDCA循环”层面规划营销
- 餐厅点菜c语言程序代码,餐馆点菜系统C语言源代码.pdf
- 鬼故事之中学异事(01)
- MSDN无法打开的解决办法
- 我不想安于当前的限度,以达到所谓的幸福,回顾下2020年的我