[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 }

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM