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 }