新聞中心

        EEPW首頁 > 嵌入式系統 > 設計應用 > 單片機之串口數據處理

        單片機之串口數據處理

        作者: 時間:2016-11-10 來源:網絡 收藏
        隨著硬件系統的模塊化發展,很多電子產品都做出模塊并采用串口進行數據通信。例如:GPRS模塊、GPS模塊、語音模塊、熱敏微型打印機、串口攝像頭等等。在與這些模塊進行數據通信都離不開串口,而對于串口的操作,由于串口本身沒有標準的通信協議,所以很難做到非常統一的操作過程。一般來說,不同的模塊其有著特殊的通信協議,我們只能根據其協議進行數據解碼。

        雖然說串口沒有標準協議,但是我們卻可以把它們的相似部分提取出來,做成模塊化的程序,方便代碼的移植和理解。下面我們簡單談到串口數據的處理方法。。。。。
        串口數據處理流程:


        一般來說,串口數據的接收都是采用中斷方式,中斷中只復制把串口發送的數據放入數據緩沖區中。而發送一般都是采用查詢方式比較方便。不管是與什么設備通信,這一點完全是一致的。所以,我們完全可以把這部分代碼獨立起來。

        定義數據結構如下:
        1. typedef struct
        2. {
        3. u16 WtCnt; // 寫指針
        4. u16 RdCnt;// 讀指針
        5. u16 BufLen;緩沖尺寸
        6. u8*RwBuf;// 讀寫緩沖
        7. } DF_RCV;
        復制代碼
        對于這個結構來說非常簡單,參數1是用于結束數據計數,參數2為處理數據計數,參數3為緩沖的大小,參數4為緩沖區指針,這里用指針是為了保證這個結構的獨立,否則無法滿足各種需求。
        實現函數:

        1. 初始化函數

        本函數用于對串口結構體中的各種數據進行初始化。
        1. /**************************************************************************************
        2. * FunctionName : DFInit()
        3. * Description : 初始化
        4. * EntryParameter : None
        5. * ReturnValue : None
        6. **************************************************************************************/
        7. void DFInit(DF_RCV *pRcv)
        8. {
        9. u16 i;
        10. pRcv->WtCnt = 0x0000;
        11. pRcv->RdCnt = 0x0000;
        12. for (i=0; iBufLen; i++)
        13. {
        14. pRcv->RwBuf[i] = 0x00;
        15. }
        16. }
        復制代碼
        2. 接收一字節數據

        本函數用于把串口中斷接收的數據放入數據緩沖區中,并且接收計數器加1.
        1. /**************************************************************************************
        2. * FunctionName : DFWriteByte()
        3. * Description : 數據接收(接收中斷調用)
        4. * EntryParameter : None
        5. * ReturnValue : None
        6. **************************************************************************************/
        7. void DFWriteByte(u8 dat, DF_RCV *pRcv)
        8. {
        9. pRcv->RwBuf[pRcv->WtCnt] = dat; // 數據存入
        10. if (++(pRcv->WtCnt) >= pRcv->BufLen) // 緩沖判斷
        11. {
        12. pRcv->WtCnt = 0;
        13. }
        14. }
        復制代碼
        3. 讀取一字節數據

        本函數用于從接收緩沖區中讀取未處理的一字節數據,讀計數器加1.
        1. /**************************************************************************************
        2. * FunctionName : DFReadByte()
        3. * Description : 從接受緩沖中讀取一字節數據
        4. * EntryParameter : None
        5. * ReturnValue : 返回讀取數據
        6. **************************************************************************************/
        7. u8 DFReadByte(DF_RCV *pRcv)
        8. {
        9. u8 val = 0x00;
        10. val = pRcv->RwBuf[pRcv->RdCnt]; // 讀取一字節
        11. if (++(pRcv->RdCnt) >= pRcv->BufLen)
        12. {
        13. pRcv->RdCnt = 0; // 清零
        14. }
        15. return val; // 返回數據
        16. }
        復制代碼
        4. 獲取緩沖區中未處理數據的長度

        本函數用于讀取串口緩沖區中還未處理的數據的大小。
        1. /**************************************************************************************
        2. * FunctionName : DFGetLen()
        3. * Description : 獲取緩沖區中未讀數據長度
        4. * EntryParameter : None
        5. * ReturnValue : 返回數據長度
        6. **************************************************************************************/
        7. u16 DFGetLen(DF_RCV *pRcv)
        8. {
        9. return ((pRcv->WtCnt >= pRcv->RdCnt) ? ((pRcv->WtCnt - pRcv->RdCnt)) :
        10. ((pRcv->WtCnt + pRcv->BufLen) - pRcv->RdCnt));
        11. }
        復制代碼
        有了以上幾個函數,串口的處理就非常簡單了。這幾個函數可以應用到任何串口中,也可以應用到任務微處理器上,一致非常簡單,應用也非常方便。下面我們說說實際的應用。
        這部分代碼為應用代碼

        為了保證數據的相對獨立和模塊化,下面代碼將寫入應用代碼中,和上面的程序不能放在相同的文件中。

        1. 數據定義

        首先需要定義一個緩沖區,這個緩沖區的大小根據實際應用定義,其大小一般為數據幀的最大值的2倍。之后需要定義一個DF_RCV數據,在這個數據中需要初始化這個結構圖的參數。特別需要注意,緩沖的大小,和緩沖區指針賦值。
        1. u8 AU_Buf[AU_BUF_ZISE] = {0};
        2. DF_RCV AU_Rvc = {0, 0,AU_BUF_ZISE,AU_Buf};
        復制代碼
        2. 編寫數據接收函數

        本函數把串口數據放入緩沖區中,此函數必須在串口中斷中調用。
        1. /**************************************************************************************
        2. * FunctionName : AURcvDat()
        3. * Description : 串口數據接收(串口中斷服務調用)
        4. * EntryParameter : None
        5. * ReturnValue : None
        6. **************************************************************************************/
        7. void AURcvDat(u8 dat)
        8. {
        9. DFWriteByte(dat, &AU_Rvc);
        10. }
        復制代碼
        3. 數據處理函數

        本函數判斷緩沖區中是否有數據,如果有,逐個讀取并處理。
        1. /**************************************************************************************
        2. * FunctionName : AUTaskCtrl()
        3. * Description : 通信數據處理
        4. * EntryParameter : None
        5. * ReturnValue : None
        6. **************************************************************************************/
        7. void AUTaskCtrl(void)
        8. {
        9. u8tmpDat;
        10. u16 i, len = 0;
        11. static u8 sendMark = 0;
        12. len = DFGetLen(&AU_Rvc); // 獲取未讀數據長度
        13. for (i=0; i < len; i++)
        14. {
        15. tmpDat = DFReadByte(&AU_Rvc); // 讀一字節數據
        16. AU_PrcRcvDat(tmpDat);
        17. }
        18. }
        復制代碼
        函數AU_PrcRcvDat(tmpDat)是數據處理函數,首先是數據幀判斷,如果是一幀數據,就進行相應操作,并把操作結果返回。了解了這個過程,串口的編程就變得非常簡單。而且我們在讀程序時,只要看懂一個串口處理過程,其他串口的程序就自然懂了,非常方便吧。


        評論


        技術專區

        關閉
        主站蜘蛛池模板: 阿拉善盟| 启东市| 城市| 伊宁市| 察哈| 德化县| 晋宁县| 海门市| 万宁市| 湟中县| 广西| 顺义区| 峨边| 福海县| 雅安市| 高雄市| 开远市| 泸溪县| 会同县| 缙云县| 新昌县| 太保市| 巴中市| 利津县| 酒泉市| 武穴市| 卢龙县| 柳州市| 沙湾县| 枣阳市| 顺义区| 仪征市| 班玛县| 安国市| 治多县| 察哈| 绥化市| 平阳县| 益阳市| 资阳市| 静宁县|