Win-API-03 串口读写
- 简 介
- 下 载
- 留 言
- 说 明
串行接口简称串口,也称串行通信接口或串行通讯接口(通常指COM接口),是采用串行通信方式的扩展接口。串行接口 (Serial Interface) 是指数据一位一位地顺序传送,其特点是通信线路简单,只要一对传输线就可以实现双向通信(可以直接利用电话线作为传输线),从而大大降低了成本,特别适用于远距离通信,但传送速度较慢。
Code
#include <stdio.h> #include <stdlib.h> #include <windows.h> HANDLE hComm; OVERLAPPED m_ov; COMSTAT comstat; DWORD m_dwCommEvents; //如果在调用CreateFile创建句柄时指 //定了FILE_FLAG_OVERLAPPED标志,那么调用ReadFile和WriteFile对该句柄进 //行的操作就应该是重叠的;如果未指定 //重叠标志,则读写操作应该是同步的 //在同步执行时,函数直到操作完成后才返回。这意味着同步执行时线程会被阻塞,从 //而导致效率下降。在重叠执行时,即使操作还未完成,这两个函数也会立即返回,费 //时的I/O操作在后台进行 bool openport(char *portname)//打开一个串口 { hComm = CreateFile(portname, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0); if (hComm == INVALID_HANDLE_VALUE) return FALSE; else return true; } bool setupdcb(int rate_arg) { DCB dcb; int rate= rate_arg; memset(&dcb,0,sizeof(dcb)); //在一段内存块中填充某个给定的值,是对较大的结构//体或数组进行清零操作的一种最快方法 if(!GetCommState(hComm,&dcb))//获取当前DCB配置 { return FALSE; } /* -------------------------------------------------------------------- */ // set DCB to configure the serial port dcb.DCBlength = sizeof(dcb); /* ---------- Serial Port Config ------- */ dcb.BaudRate = rate; dcb.Parity = NOPARITY; dcb.fParity = 0; dcb.StopBits = ONESTOPBIT; dcb.ByteSize = 8; dcb.fOutxCtsFlow = 0; dcb.fOutxDsrFlow = 0; dcb.fDtrControl = DTR_CONTROL_DISABLE; dcb.fDsrSensitivity = 0; dcb.fRtsControl = RTS_CONTROL_DISABLE; dcb.fOutX = 0; dcb.fInX = 0; /* ----------------- misc parameters ----- */ dcb.fErrorChar = 0; dcb.fBinary = 1; dcb.fNull = 0; dcb.fAbortOnError = 0; dcb.wReserved = 0; dcb.XonLim = 2; dcb.XoffLim = 4; dcb.XonChar = 0x13; dcb.XoffChar = 0x19; dcb.EvtChar = 0; /* -------------------------------------------------------------------- */ // set DCB if(!SetCommState(hComm,&dcb)) { return false; } else return true; } //在用readfile和writefile读写串行口时,需要考虑超时问题, 读写串口的超时有两 //种:间隔超时和总超时, 写操作只支持总超时,而读操作两种超时均支持, 如果所有 //写超时参数均为0,那么就不使用写超时。 bool setuptimeout(DWORD ReadInterval,DWORD ReadTotalMultiplier,DWORD ReadTotalconstant,DWORD WriteTotalMultiplier,DWORD WriteTotalconstant) { COMMTIMEOUTS timeouts; timeouts.ReadIntervalTimeout=ReadInterval; //读间隔超时 timeouts.ReadTotalTimeoutConstant=ReadTotalconstant; //读时间系数 timeouts.ReadTotalTimeoutMultiplier=ReadTotalMultiplier; //读时间常量 timeouts.WriteTotalTimeoutConstant=WriteTotalconstant; // 写时间系数 timeouts.WriteTotalTimeoutMultiplier=WriteTotalMultiplier; //写时间常//量, 总超时的计算公式是:总超时=时间系数×要求读/写的字符数+时间常量 if(!SetCommTimeouts(hComm, &timeouts)) { return false; } else return true; } void ReceiveChar(){ BOOL bRead = TRUE; BOOL bResult = TRUE; DWORD dwError = 0; DWORD BytesRead = 0; char RXBuff; while(true){ bResult = ClearCommError(hComm, &dwError, &comstat); // 在使用ReadFile 函数进行读操作前,应先使用ClearCommError函数清除错误 if(comstat.cbInQue==0)// COMSTAT结构返回串口状态信息 //本文只用到了cbInQue成员变量,该成员变量的值代表输入缓冲区的字节数 continue; if(bRead){ bResult = ReadFile(hComm, // Handle to COMM port串口的句柄 &RXBuff,// RX Buffer Pointer// 读入的数据存储的地址,即读入的数据将存//储在以该指针的值为首地址的一片内存区 1,// Read one byte要读入的数据的字节数, &BytesRead, // Stores number of bytes read, 指向一个DWORD//数值,该数值返回读操作实际读入的字节数 &m_ov); // pointer to the m_ov structure// 重叠操作时,该参数指向一个OVERLAPPED结构,同步操作时,该参数为NULL printf("%c",RXBuff); if (!bResult){// 当ReadFile和WriteFile返回FALSE时,不一定就是操作失//败,线程应该调用GetLastError函数分析返回的结果 switch (dwError = GetLastError()){ case ERROR_IO_PENDING: bRead = FALSE; break; default:break; } }else{ bRead = TRUE; } } // close if (bRead) if (!bRead){ bRead = TRUE; bResult = GetOverlappedResult(hComm, // Handle to COMM port &m_ov, // Overlapped structure &BytesRead, // Stores number of bytes read TRUE); // Wait flag } } } BOOL WriteChar(BYTE* m_szWriteBuffer,DWORD m_nToSend){ BOOL bWrite = TRUE; BOOL bResult = TRUE; DWORD BytesSent = 0; HANDLE m_hWriteEvent; ResetEvent(m_hWriteEvent); if (bWrite){ m_ov.Offset = 0; m_ov.OffsetHigh = 0; // Clear buffer bResult = WriteFile(hComm, // Handle to COMM Port, 串口的句柄 m_szWriteBuffer, // Pointer to message buffer in calling finction // 即以该指针的值为首地址的nNumberOfBytesToWrite // 个字节的数据将要写入串口的发送数据缓冲区 m_nToSend, // Length of message to send, 要写入的数据的字节数 &BytesSent, // Where to store the number of bytes sent // 指向指向一个DWORD数值,该数值返回实际写入的字节数 &m_ov ); // Overlapped structure // 重叠操作时,该参数指向一个OVERLAPPED结构, // 同步操作时,该参数为NULL if (!bResult){ // 当ReadFile和WriteFile返回FALSE时,不一定就是操作失 //败,线程应该调用GetLastError函数分析返回的结果 DWORD dwError = GetLastError(); switch (dwError){ case ERROR_IO_PENDING: //GetLastError函数返回//ERROR_IO_PENDING。这说明重叠操作还未完成 // continue to GetOverlappedResults() BytesSent = 0; bWrite = FALSE; break; default:break; } } } // end if(bWrite) if (!bWrite){ bWrite = TRUE; bResult = GetOverlappedResult(hComm, // Handle to COMM port &m_ov, // Overlapped structure &BytesSent, // Stores number of bytes sent TRUE); // Wait flag // deal with the error code if (!bResult){ printf("GetOverlappedResults() in WriteFile()"); } } // end if (!bWrite) // Verify that the data size send equals what we tried to send if (BytesSent != m_nToSend){ printf("WARNING: WriteFile() error.. Bytes Sent: %d; Message Length: %d\n", BytesSent, strlen((char*)m_szWriteBuffer)); } return true; } void main(){ if(openport("com4")) printf("open comport success\n"); if(setupdcb(115200)) printf("setupDCB success\n"); if(setuptimeout(0,0,0,0,0)) //如果所有写超时参数均为0,那么就不使用写超时 printf("setuptimeout success\n"); PurgeComm(hComm, PURGE_RXCLEAR | PURGE_TXCLEAR | PURGE_RXABORT | PURGE_TXABORT); // 在读写串口之前,还要用PurgeComm()函数清空缓冲区 //PURGE_TXABORT 中断所有写操作并立即返回,即使写操作还没有完成。 //PURGE_RXABORT 中断所有读操作并立即返回,即使读操作还没有完成。 //PURGE_TXCLEAR 清除输出缓冲区 //PURGE_RXCLEAR 清除输入缓冲区 //WriteChar("please send data now",20); printf("received data:\n"); ReceiveChar( ); system("pause"); }