13.5.3 读写串口(1)
串口的读写操作同文件的读写操作一样,也是通过ReadFile()及WriteFile()函数来实现的。这两个函数的原型如下。
(1)写文件函数原型及说明如下:
- BOOL WriteFile(
- HANDLE hFile,
- LPCVOID lpBuffer,
- DWORD nNumberOfBytesToWrite,
- LPDWORD lpNumberOfBytesWritten,
- LPOVERLAPPED lpOverlapped
- );
函数有5个参数,说明如下。
hFile:打开串口时返回的句柄。
lpBuffer:写入的数据存储的地址,即以该指针的值为首地址的nNumberOfBytesToWrite个字节的数据,将要写入串口的发送数据缓冲区。
nNumberOfBytesToWrite:要写入的数据的字节数。
lpNumberOfBytesWritten:指向一个DWORD数值,该数值返回实际写入的字节数。
lpOverlapped:重叠操作时,该参数指向一个OVERLAPPED结构,同步操作时,该参数为NULL。
(2)读文件函数原型及说明如下:
- BOOL ReadFile(
- HANDLE hFile,
- LPVOID lpBuffer,
- DWORD nNumberOfBytesToRead,
- LPDWORD lpNumberOfBytesRead,
- LPOVERLAPPED lpOverlapped
- );
函数有5个参数,说明如下。
hFile:串口的句柄。
lpBuffer:读入的数据存储地址,即读入的数据将存储在以该指针的值为首地址的一片内存区。
nNumberOfBytesToRead:要读入数据的字节数。
lpNumberOfBytesRead:指向一个DWORD数值,该数值返回读操作实际读入的字节数。
lpOverlapped:重叠操作时,该参数指向一个OVERLAPPED结构,同步操作时,该参数为NULL。
在用ReadFile()及WriteFile()函数读写串口时,既可以同步执行,也可以重叠执行。在同步执行时,函数直到操作完成后才返回。这意味着同步执行时线程会被阻塞,从而导致效率下降。在重叠执行时,即使操作还未完成,这两个函数也会立即返回,费时的I/O操作在后台进行。
而在调用CreateFile()函数打开串口时,就已经决定了ReadFile()及WriteFile()函数对串口的操作是同步还是异步。如果在调用CreateFile()函数创建打开串口时指定了FILE_FLAG_OVERLAPPED标志,那么调用ReadFile()及WriteFile()函数对该打开串口时返回的句柄进行的操作就应该是重叠的。如果未指定重叠标志,则读写操作应该是同步的,即ReadFile()和WriteFile()函数的同步或者异步应该和CreateFile()函数相一致。
说明:ReadFile()函数只要在串口输入缓冲区中读入指定数量的字符,就算完成操作。而WriteFile()函数不但要把指定数量的字符复制到输出缓冲区,而且要等这些字符从串行口送出去后才算完成操作。如果操作成功,这两个函数都返回true。需要注意的是,当ReadFile()和WriteFile()函数返回false时,不一定就是操作失败,线程应该调用GetLastError()函数分析返回的结果。例如,在重叠操作时如果操作还未完成函数就返回,那么函数就返回false,而且GetLastError()函数返回ERROR_IO_PENDING,这说明重叠操作还未完成。
由于同步读写串口的实现比较简单,所以首先给出同步读写串口的示例代码:
(1)同步读串口示例代码如下:
- 01 bool ReadCom(char * str , int len)
- 02 {
- 03 DWORD wCount; //读取的字节数
- 04 BOOL bReadStat;
- 05 bReadStat = ReadFile( hCom, str, len, &wCount, NULL );
- 06 if( !bReadStat )
- 07 {
- 08 AfxMessageBox( "读串口失败! ");
- 09 return FALSE;
- 10 }
- 11 return TRUE;
- 12 }