串口编程步骤
基于win32API
写在前面:
关于串口通信,网上的文章代码很多,之所以还要写这篇文章主要是因为本人在写串口通信时还是遇到了一些挫折,想借写此文章进一步加深对串口通信的理解,同时也是对这两天的一个总结吧。
这几天项目要求用C++写串口通信,于是果断上网搜关于C++串口通信的代码,还真是一搜一箩筐。由于本人编程能力有限,刚开始看到那些代码时,感觉好麻烦,于是看了两行后不想看了,然后又开始找其他代码。这样烦躁的忙碌了一天后,感觉不对劲。在这样下去这串口通信是没法整明白了,自己估计也得疯掉。醒悟后,开始慢慢平静心情,我先找了一篇关于介绍串口通信一般步骤的文章,认真读完一遍后,感觉收获挺大。鉴于本人较懒,于是我直接又从网上找了几份c++串口通信的代码研究,研究发现,代码主要分两类,一类是利用串口控件,另一类是直接利用Win32API。本文主要讲第二类,主要原因是我的VC++6.0貌似找不到串口控件,郁闷呀。不过利用API编程还是挺有趣的嘛。废话不说了,先来说说串口通信的一些基本函数吧。
1.打开串口。
所用函数:
HANDLE CreateFIle(LPCTSTR lpFileName,
DWORD dwAccess,
DWORD dwShareMode, LPSECURITY_ATTRIBUTES lpsa,
DWORD dwCreate,
DWORD dwAttrsAndFlags,
HANDLE hTemplateFile)
参数介绍:
LPCTSTR lpFileName:将要打开的串口逻辑名,如COM1 或COM2。
DWORD dwAccess:指定串口访问的类型,可以是读取、写入或两者 并列
DWORD dwShareMode:指定共享属性,由于串口不能共享,该参数 必须置为0 LPSECURITY_ATTRIBUTES lpsa:引用安全性属性结构,缺省值NULL
DWORD dwCreate:创建标志,对串口操作该参数必须置为OPEN EXISTING
DWORD dwAttrsAndFlags:属性描述,用于指定该串口是否可进行 异步操作
HANDLE hTemplateFile:指向模板文件的句柄,对串口而言该参数 必须置为NULL
例如,以下程序用于以同步读写方式打开串口COM1:
HANDLE hCom;
DWORD dwError;
hCon = CreateFile("COM1", GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
if (hCom == (HANDLE)0xFFFFFFFF)
{
dwError = GetLastError();
MessageBox(dwError);
}
2.配置串口
配置串口是通过改变设备控制块DCB(Device Control Block) 的成员变量值来实现的,接收缓冲区和发送缓冲区的大小可通过SetupComm函数来设置。
DCB的结构体定义如下:
typedef struct _DCB { // dcb
DWORD DCBlength; // sizeof(DCB)
DWORD BaudRate; // current baud rate
DWORD fBinary: 1; // binary mode, no EOF check
DWORD fParity: 1; // enable parity checking
DWORD fOutxCtsFlow:1; // CTS output flow control
DWORD fOutxDsrFlow:1; // DSR output flow control
DWORD fDtrControl:2; // DTR flow control type
DWORD fDsrSensitivity:1; // DSR sensitivity
DWORD fTXContinueOnXoff:1; // XOFF continues Tx
DWORD fOutX: 1; // XON/XOFF out flow control
DWORD fInX: 1; // XON/XOFF in flow control
DWORD fErrorChar: 1; // enable error replacement
DWORD fNull: 1; // enable null stripping
DWORD fRtsControl:2; // RTS flow control
DWORD fAbortOnError:1; // abort reads/writes on error
DWORD fDummy2:17; // reserved
WORD wReserved; // not currently used
WORD XonLim; // transmit XON threshold
WORD XoffLim; // transmit XOFF threshold
BYTE ByteSize; // number of bits/byte, 4-8
BYTE Parity; // 0-4=no,odd,even,mark,space
BYTE StopBits; // 0,1,2 = 1, 1.5, 2
char XonChar; // Tx and Rx XON character
char XoffChar; // Tx and Rx XOFF character
char ErrorChar; // error replacement character
char EofChar; // end of input character
char EvtChar; // received event character
WORD wReserved1; // reserved; do not use
} DCB;
而SetupComm函数的原型则为:
BOOL SetupComm(
HANDLE hFile, // handle to communications device
DWORD dwInQueue, // size of input buffer
DWORD dwOutQueue // size of output buffer
);
那么长一大串,看都不想看,想要记住谈何容易。其实关于DCB的属性我们一般只需设置下面程序中的几个。
以下程序将串口设置为:波特率为9600,数据位数为7位,停止位为2 位,偶校验,接收缓冲区和发送缓冲区大小均为1024个字节,最后用PurgeComm函数终止所有的后台读写操作并清空接收缓冲区和发送缓冲区:
DCB dcb;
dcb.BaudRate = 9600; //波特率为9600
dcb.ByteSize = 7; //数据位数为7位
dcb.Parity = EVENPARITY; //偶校验
dcb.StopBits = 2; //两个停止位
dcb.fBinary = TRUE;
dcb.fParity = TRUE;
if (!SetCommState(hCom, &dcb))
{
MessageBox("串口设置出错!");
}
SetupComm(hCom, 1024, 1024);
PurgeComm(hCom, PURCE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR);
3读写串口
读串口
对串口进行读取所用的函数和对文件进行读取所用的函数相同,读函数原型如下:
BOOL ReadFile(
HANDLE hFile, // handle of file to read
LPVOID lpBuffer, // pointer to buffer that receives data
DWORD nNumberOfBytesToRead, // number of bytes to read
LPDWORD lpNumberOfBytesRead, // pointer to number of bytes read
LPOVERLAPPED lpOverlapped // pointer to structure for overlapped I/O
);
写串口
对串口进行写入所用的函数和对文件进行写入所用的函数相同,写函数原型如下:
BOOL WriteFile(
HANDLE hFile, // handle to file to write to
LPCVOID lpBuffer, // pointer to data to write to file
DWORD nNumberOfBytesToWrite, // number of bytes to write
LPDWORD lpNumberOfBytesWritten, // pointer to number of bytes written
LPOVERLAPPED lpOverlapped // pointer to structure for overlapped I/O
);
4关闭串口
利用API 函数实现串口通信时关闭串口非常简单,只需使用CreateFile 函数返回的句柄作为参数调用CloseHandle 即可:
BOOL CloseHandle(
HANDLE hObject // handle to object to close
);
完了,关于串口通信的一般步骤就是这几步了,现在想起来其实还是挺简单的。当然想要深入还是有很东西要学的,不过对于我这个初学者来说,明白这些就已经够用了,更深的东西今后慢慢学吧。