C\C++串口通信編程的一點技術記錄


新工作接的第一個活,要寫一個配合設備調試的上位機程序。

除了MFC界面的部分,就是要處理幾條命令。

 

串口通信部分代碼借鑒的是這一篇文章:http://blog.sina.com.cn/s/blog_afb1793101016mq2.html

                                                                 https://blog.csdn.net/qq_41480046/article/details/82220155

里面代碼很好理解,對於串口的連接設置,有那么幾個固定的函數,之后串口的打開和讀寫,就是用CreateFileA、ReadFile、WriteFile這樣的幾個函數,將串口當做文件來操作

另外就是用了臨界區來實現同步操作,

比較精妙的是串口的讀線程,在循環里首先判斷串口緩沖區里是否有內容,如果有再去真正讀串口

 

我這里記錄在這篇文章代碼之外,自己實踐之后新獲得的一些心得:

 

1,DCB的EVEN方式的初始化寫法

DCB是一個結構體,在調用SetCommState函數時作為參數傳入,這是串口初始化的通用寫法,不贅述

關鍵是初始化時的一些設置

如果設備端用了校驗位,上位機這邊沒有用,那么設備可以連接,但收發信息是出錯的

所以,初始化時候要設置校驗位的使用

 

校驗方式有以下幾種:

無校驗 (no parity)

奇校驗 (odd parity):如果字符數據位中"1"的數目是偶數,校驗位為"1",如果"1"的數目是奇數,校驗位應為"0"。(校驗位調整個數)

偶校驗 (even parity):如果字符數據位中"1"的數目是偶數,則校驗位應為"0",如果是奇數則為"1"。(校驗位調整個數)

mark parity:校驗位始終為1

space parity:校驗位始終為0

 

在VS有以下宏定義對應:

#define NOPARITY 0
#define ODDPARITY 1
#define EVENPARITY 2
#define MARKPARITY 3
#define SPACEPARITY 4

 

問題是我一開始初始化DCB時候,傳入的參數是EVENPARITY,結構出錯

搞了半天,各種嘗試都沒用,網上也沒資料,微軟的官方文檔也看不太懂

后來才明白使用BuildCommDCB函數構造DCB結構的時候,傳入的參數應該是'E',而不是EVENPARITY,同理如果是NOPARITY的話,就傳'N',其余同理

感覺很扯淡

 

2,判斷串口是否斷開的寫法

那篇文章的代碼里沒有這樣的函數,網上也找不到,但實際這樣的功能非常重要!

經過實踐我用下面方法解決了這個問題:

開個線程,線程里循環,每次循環Sleep一秒,線程里寫: bResult = ReadFile(m_hComm, &cRecved, 0, &BytesRead, NULL);

注意第三個參數為0,表示讀取長度為0,如果該參數大於1,會一直等待讀數據而卡死

然后通過返回值bResult即可判斷串口連接狀態

經實驗證明,此判斷方法,不會影響其余的實際串口讀寫功能

 

3,把串口通信類封裝成DLL

在公司里可能會反復遇到些串口通信的需求,如果每次都復制一遍代碼重復度太高,必須封裝成庫,費勁一點以后就省事了

大體思路如下:

一般需求只需要設備連接、設備斷開、判斷設備連接狀態、發送命令或數據、接收命令和數據   這五種接口

串口接收的處理肯定要寫在線程里

對外接口的話,提供的是發送后接收 的 整個過程 的方法

邏輯如下:

//發送命令
........
// 等待時間5秒
int iWaitTime=10; while(i--) {
//通過全局變量和接收線程通訊
//設備返回成功
if (g_iFlag == SUCCESS) return true; // 設備返回失敗 if (g_iFlag == FAIL) return false; Sleep(500); } // 超時 return false;

這樣提供的接口,

就是先發命令,然后等待設備返回結果(在線程里接收,全局變量通信),結果有三種:成功、失敗、超時

以這樣的思路,很容易就可以把串口通信的代碼封裝成dll了,這也是上面那篇文章沒做到的事情 


免責聲明!

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



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