首页 > 代码库 > [WinAPI] 串口读写

[WinAPI] 串口读写

  1 #include <stdio.h>
  2 #include <stdlib.h>
  3 #include <windows.h>
  4 
  5 HANDLE hComm;
  6 OVERLAPPED m_ov;
  7 COMSTAT comstat;
  8 DWORD    m_dwCommEvents;
  9 
 10 //如果在调用CreateFile创建句柄时指
 11 //定了FILE_FLAG_OVERLAPPED标志,那么调用ReadFile和WriteFile对该句柄进
 12 //行的操作就应该是重叠的;如果未指定
 13 //重叠标志,则读写操作应该是同步的
 14 //在同步执行时,函数直到操作完成后才返回。这意味着同步执行时线程会被阻塞,从
 15 //而导致效率下降。在重叠执行时,即使操作还未完成,这两个函数也会立即返回,费
 16 //时的I/O操作在后台进行
 17 bool openport(char *portname)//打开一个串口
 18 {
 19     hComm = CreateFile(portname,
 20         GENERIC_READ | GENERIC_WRITE,
 21         0,
 22         0,
 23         OPEN_EXISTING,
 24         FILE_FLAG_OVERLAPPED,    
 25         0);
 26     if (hComm == INVALID_HANDLE_VALUE)
 27         return FALSE;
 28     else
 29         return true;
 30 }
 31 
 32 
 33 bool setupdcb(int rate_arg)
 34 {
 35     DCB  dcb;
 36     int rate= rate_arg;
 37     memset(&dcb,0,sizeof(dcb)); //在一段内存块中填充某个给定的值,是对较大的结构//体或数组进行清零操作的一种最快方法
 38     if(!GetCommState(hComm,&dcb))//获取当前DCB配置
 39     {
 40         return FALSE;
 41     }
 42     /* -------------------------------------------------------------------- */
 43     // set DCB to configure the serial port
 44     dcb.DCBlength       = sizeof(dcb);
 45     /* ---------- Serial Port Config ------- */
 46     dcb.BaudRate        = rate;
 47     dcb.Parity      = NOPARITY;
 48     dcb.fParity     = 0;
 49     dcb.StopBits        = ONESTOPBIT;
 50     dcb.ByteSize        = 8;
 51     dcb.fOutxCtsFlow    = 0;
 52     dcb.fOutxDsrFlow    = 0;
 53     dcb.fDtrControl     = DTR_CONTROL_DISABLE;
 54     dcb.fDsrSensitivity = 0;
 55     dcb.fRtsControl     = RTS_CONTROL_DISABLE;
 56     dcb.fOutX           = 0;
 57     dcb.fInX            = 0;
 58     /* ----------------- misc parameters ----- */
 59     dcb.fErrorChar      = 0;
 60     dcb.fBinary         = 1;
 61     dcb.fNull           = 0;
 62     dcb.fAbortOnError   = 0;
 63     dcb.wReserved       = 0;
 64     dcb.XonLim          = 2;
 65     dcb.XoffLim         = 4;
 66     dcb.XonChar         = 0x13;
 67     dcb.XoffChar        = 0x19;
 68     dcb.EvtChar         = 0;
 69     /* -------------------------------------------------------------------- */
 70     // set DCB
 71     if(!SetCommState(hComm,&dcb))
 72     {
 73         return false;
 74     }
 75     else
 76         return true;
 77 }
 78 //在用readfile和writefile读写串行口时,需要考虑超时问题, 读写串口的超时有两
 79 //种:间隔超时和总超时, 写操作只支持总超时,而读操作两种超时均支持, 如果所有
 80 //写超时参数均为0,那么就不使用写超时。
 81 bool setuptimeout(DWORD ReadInterval,DWORD ReadTotalMultiplier,DWORD ReadTotalconstant,DWORD WriteTotalMultiplier,DWORD WriteTotalconstant)               
 82 {
 83     COMMTIMEOUTS timeouts;
 84     timeouts.ReadIntervalTimeout=ReadInterval; //读间隔超时
 85     timeouts.ReadTotalTimeoutConstant=ReadTotalconstant; //读时间系数
 86     timeouts.ReadTotalTimeoutMultiplier=ReadTotalMultiplier; //读时间常量
 87     timeouts.WriteTotalTimeoutConstant=WriteTotalconstant; // 写时间系数
 88     timeouts.WriteTotalTimeoutMultiplier=WriteTotalMultiplier; //写时间常//量, 总超时的计算公式是:总超时=时间系数×要求读/写的字符数+时间常量
 89     if(!SetCommTimeouts(hComm, &timeouts))
 90     {
 91         return false;
 92     }
 93     else
 94         return true;
 95 }
 96 void ReceiveChar(){
 97     BOOL  bRead = TRUE;
 98     BOOL  bResult = TRUE;
 99     DWORD dwError = 0;
100     DWORD BytesRead = 0;
101     char RXBuff;
102     while(true){
103         bResult = ClearCommError(hComm, &dwError, &comstat);
104         // 在使用ReadFile 函数进行读操作前,应先使用ClearCommError函数清除错误
105         if(comstat.cbInQue==0)// COMSTAT结构返回串口状态信息
106             //本文只用到了cbInQue成员变量,该成员变量的值代表输入缓冲区的字节数
107             continue;
108         if(bRead){
109             bResult = ReadFile(hComm, // Handle to COMM port串口的句柄
110                 &RXBuff,// RX Buffer Pointer// 读入的数据存储的地址,即读入的数据将存//储在以该指针的值为首地址的一片内存区
111                 1,// Read one byte要读入的数据的字节数,
112                 &BytesRead, // Stores number of bytes read, 指向一个DWORD//数值,该数值返回读操作实际读入的字节数
113                 &m_ov);           // pointer to the m_ov structure// 重叠操作时,该参数指向一个OVERLAPPED结构,同步操作时,该参数为NULL
114             printf("%c",RXBuff);
115             if (!bResult){// 当ReadFile和WriteFile返回FALSE时,不一定就是操作失//败,线程应该调用GetLastError函数分析返回的结果
116                 switch (dwError = GetLastError()){
117                 case ERROR_IO_PENDING:
118                         bRead = FALSE;
119                         break;
120                 default:break;
121                 }
122             }else{
123                 bRead = TRUE;
124             }
125         }  // close if (bRead)
126         if (!bRead){
127             bRead = TRUE;
128             bResult = GetOverlappedResult(hComm,    // Handle to COMM port
129                 &m_ov,    // Overlapped structure
130                 &BytesRead,        // Stores number of bytes read
131                 TRUE);             // Wait flag
132         }
133     }
134 }
135 BOOL WriteChar(BYTE* m_szWriteBuffer,DWORD m_nToSend){
136     BOOL bWrite = TRUE;
137     BOOL bResult = TRUE;
138     DWORD BytesSent = 0;
139     HANDLE    m_hWriteEvent;
140     ResetEvent(m_hWriteEvent);
141     if (bWrite){
142         m_ov.Offset = 0;
143         m_ov.OffsetHigh = 0;
144         // Clear buffer
145         bResult = WriteFile(hComm,    // Handle to COMM Port, 串口的句柄
146             m_szWriteBuffer,        // Pointer to message buffer in calling finction
147                                     // 即以该指针的值为首地址的nNumberOfBytesToWrite
148                                     // 个字节的数据将要写入串口的发送数据缓冲区
149             m_nToSend,                // Length of message to send, 要写入的数据的字节数
150             &BytesSent,                // Where to store the number of bytes sent
151                                     // 指向指向一个DWORD数值,该数值返回实际写入的字节数
152             &m_ov );                // Overlapped structure
153                                     // 重叠操作时,该参数指向一个OVERLAPPED结构,
154                                     // 同步操作时,该参数为NULL
155         if (!bResult){                // 当ReadFile和WriteFile返回FALSE时,不一定就是操作失
156             //败,线程应该调用GetLastError函数分析返回的结果
157             DWORD dwError = GetLastError();
158             switch (dwError){
159             case ERROR_IO_PENDING: //GetLastError函数返回//ERROR_IO_PENDING。这说明重叠操作还未完成
160                     // continue to GetOverlappedResults()
161                     BytesSent = 0;
162                     bWrite = FALSE;
163                     break;
164             default:break;
165             }
166         }
167     } // end if(bWrite)
168     if (!bWrite){
169         bWrite = TRUE;
170         bResult = GetOverlappedResult(hComm,    // Handle to COMM port
171             &m_ov,        // Overlapped structure
172             &BytesSent,        // Stores number of bytes sent
173             TRUE);             // Wait flag
174         
175         // deal with the error code
176         if (!bResult){
177             printf("GetOverlappedResults() in WriteFile()");
178         }
179     } // end if (!bWrite)
180     
181     // Verify that the data size send equals what we tried to send
182     if (BytesSent != m_nToSend){
183         printf("WARNING: WriteFile() error.. Bytes Sent: %d; Message Length: %d\n", BytesSent, strlen((char*)m_szWriteBuffer));
184     }
185     return true;
186 }
187 
188 
189 void   main(){
190     if(openport("com4"))
191         printf("open comport success\n");
192     if(setupdcb(115200))
193         printf("setupDCB success\n");
194     if(setuptimeout(0,0,0,0,0)) //如果所有写超时参数均为0,那么就不使用写超时
195         printf("setuptimeout success\n");
196     PurgeComm(hComm, PURGE_RXCLEAR | PURGE_TXCLEAR | PURGE_RXABORT | PURGE_TXABORT); // 在读写串口之前,还要用PurgeComm()函数清空缓冲区
197     //PURGE_TXABORT      中断所有写操作并立即返回,即使写操作还没有完成。
198     //PURGE_RXABORT      中断所有读操作并立即返回,即使读操作还没有完成。
199     //PURGE_TXCLEAR      清除输出缓冲区
200     //PURGE_RXCLEAR      清除输入缓冲区
201     //WriteChar("please send data now",20);
202     printf("received data:\n");
203     ReceiveChar( );
204     system("pause");
205 }