Win32下,可以使用两种编程方式实现串口通信。
一、使用ActiveX控件,优点是简单,缺点是欠灵活
二、使用windows的API函数,优点是可以清楚的掌握串口通信的机制、灵活
确定是比较复杂
串口操作可以有两种方式:同步、异步。用编程语言说就是阻塞、非阻塞。
它们都有四个步骤:
1、打开串口
2、配置串口
3、读写串口
4、关闭串口
1、打开串口
Win32系统把文件的概念进行了扩展。无论是文件、通信设备、命名管道、邮件槽、磁盘、控制台,都是用API函数CreateFile打开/创建
HANDLE CreateFileA(
LPCTSTR lpFileName, //文件名
DWORD dwDesiredAccess, //访问方式(read,write,r/w)
DWORD dwShareMode, //文件共享方式
LPSECURITY_ATTRIBUTES lpSecurityAttributes,
//安全模式
DWORD dwCreationDisposition, //文件存在时的创建方式
DWORD dwFlagsAndAttributes, //文件属性
HANDLE hTemplateFile //文件模板句柄
}
CreateFileA和CreateFileW参数相同,区别是字符编码
lpFileName: 将要打开的串口逻辑名,如“COM1”
dwDesiredAccess: 串口访问类型,读取、写入或读写
dwShareMode : 共享属性,串口不可共享,该参数必须为0
lpSecurityAttributes: 引用安全性属性结构,缺省为NULL
dwCreationDistribution: 创建标识,这里必须为OPEN_EXISTING
dwFlagsAndAttributes: 属性描述,用于指定该串口是否进行异步
FILE_FLAG_OVERLAPPED 异步,0 同步
hTemplateFile:这里该参数必须为NULL
HANDLE hCom; //全局变量,串口句柄
hCom =CreateFile("COM1", //COM1口
GENERIC_READ|GENERIC_WRITE, //允许读和写
0, //独占方式
NULL,
OPEN_EXISTING, //打开而不是创建
FILE_ATTRIBUTE_NORMAL|FILE_FLAG_OVERLAPPED, //重叠方式
NULL);
if(hCom == INVALID_HANDLE_VALUE)
{
AfxMessageBox("打开COM失败");
return FALSE;
}
2、配置串口 winbase.h
(1) 设置DCB结构
打开串口句柄后,需要一个DCB结构来进行初始化配置工作。DCB结构包含了诸如波特率、数据位数、奇偶检验和停止位数等信息。另外在查询时也需要使用到DCB结构。
GetCommState(HANDLE hFile,LPDCB lpDCB)--->获取串口的配置信息
设置串口信息可以先修改DCB结构的内容,然后调用
SetCommState(HANDLE hFile,LPDCB lpDCB)
typedef struct _DCB{
………
//波特率,指定通信设备的传输速率。这个成员可以是实际波特率值或者下面的常量值之一:
DWORD BaudRate;
CBR_110,CBR_300,CBR_600,CBR_1200,CBR_2400,CBR_4800,CBR_9600,CBR_19200, CBR_38400,
CBR_56000, CBR_57600, CBR_115200, CBR_128000, CBR_256000, CBR_14400
DWORD fParity; // 指定奇偶校验使能。若此成员为1,允许奇偶校验检查
…
BYTE ByteSize; // 通信字节位数,4—8
BYTE Parity; //指定奇偶校验方法。此成员可以有下列值:
EVENPARITY 偶校验 NOPARITY 无校验
MARKPARITY 标记校验 ODDPARITY 奇校验
BYTE StopBits; //指定停止位的位数。此成员可以有下列值:
ONESTOPBIT 1位停止位 TWOSTOPBITS 2位停止位
ONE5STOPBITS 1.5位停止位
………
} DCB;
BOOL GetCommState(
HANDLE hFile, //标识通讯端口的句柄
LPDCB lpDCB //指向一个设备控制块(DCB结构)的指针
); -->获取COM口的设备控制块,从而获得相关参数
BOOL SetCommState(
HANDLE hFile,
LPDCB lpDCB
); -->函数设置COM口的设备控制块
(2) 设置I/O缓冲区的大小和超时
Windows用I/O缓冲区来暂存串口输入和输出的数据。如果需要设置缓冲区,调用SetupComm函数
SetupComm(
HANDLE hFile,
DWORD dwInQueue
DWORD dwOutQueue
);
查询当前的超时设置应调用GetCommTimeouts函数,该函数会填充一个COMMTIMEOUTS结构。调用SetCommTimeouts设置超时
typedef struct _COMMTIMEOUTS {
DWORD ReadIntervalTimeout; //读间隔超时
DWORD ReadTotalTimeoutMultiplier; //读时间系数
DWORD ReadTotalTimeoutConstant; //读时间常量
DWORD WriteTotalTimeoutMultiplier; // 写时间系数
DWORD WriteTotalTimeoutConstant; //写时间常量
} COMMTIMEOUTS,*LPCOMMTIMEOUTS;
总超时的计算公式是:
总超时=时间系数×要求读/写的字符数+时间常量
在读写串口前,还要用PurgeComm()函数清空缓冲区,
BOOL PurgeComm(
HANDLE hFile, //串口
DWORD dwFlags //需要完成的操作
);
参数dwFlags指定要完成的操作,可以是下列值得组合
DCB dcb;
GetCommState(hComm,&dcb);
dcb.BaudRate=9600;//波特率为9600
dcb.ByteSize=8;//每个字节有8位
dcb.Parity=NOPARITY;//无奇偶位
dcb.StopBits=TWOSTOPBITS;//两个停止位
SetCommState(hCom,&dcb);
PurgeComm(hCom,PURGE_TXCLEAR|PURGE_RXCLEAR);
在读写串口之前,还要PurgeComm()函数清空缓冲区,该函数原型:
BOOL PurgeComm(
HANDLE hFile,
DWORD dwFlags
);
PURGE_TXABORT 中断所有写操作并立即返回,即使写操作还没有完成。
PURGE_RXABORT 中断所有读操作并立即返回,即使读操作还没有完成。
PURGE_TXCLEAR 清除输出缓冲区
PURGE_RXCLEAR 清除输入缓冲区
3、读写串口
BOOL ReadFile(
HANDLE hFile,//串口句柄
LPVOID lpBuffer, //内存块
DWORD nNumberOfBytesToRead,//要读入的数据的字节数
LPDWORD lpNumberOfBytesRead,//返回实际读入的字节数
LPOVERLAPPED lpOverlapped 同步/异步
);
BOOL WriteFile(
HANDLE hFile,
LPCVOID lpBuffer,
DWORD nNumberOfBytesToWrite,
LPDWORD lpNumberOfBytesWritten,
LPOVERLAPPED lpOverlapped 同步/异步
);
ReadFile/WriteFile成功返回TRUE,返回FALSE后调用GetLastError函数分析结果。如果返回ERROR_IO_PENDING,则操作失败。
OVERLAPPED结构
typedef struct _OVERLAPPED { // o
DWORD Internal;
DWORD InternalHigh;
DWORD Offset;
DWORD OffsetHigh;
HANDLE hEvent;
} OVERLAPPED;
在使用ReadFile 函数进行读操作前,应先使用ClearCommError函数清除错误.
BOOL ClearCommError(
HANDLE hFile, // 串口句柄
LPDWORD lpErrors, // 指向接收错误码的变量
LPCOMSTAT lpStat // 指向通讯状态缓冲区
);
参数lpStat指向一个COMSTAT结构,该结构返回串口状态信息。
4、关闭串口
BOOL CloseHandle(
handle hObject,//串口句柄
)window串口编程
原文:http://blog.csdn.net/u010640235/article/details/18261725