接著以前的文章(uart學習筆記一),繼續聊聊這個話題。上次的文章分析了如果去
接收資料,這章分析下如果去check一幀資料。如果想要check一幀資料,就要考慮兩種情況:
1)資料幀接收完畢,意思就是說buffer裡面有一幀完整的資料;
2)資料幀暫時沒有接收完畢,比如:幀頭、校驗、幀尾,目前只收到了幀頭;
上面兩種情況和底層驅動實現方式直接相關:
1)timer_out方式;
2)邊接收邊解析,佇列快取方式;
首先來說第一種情況:
底層驅動利用timer_out方式,這個是時候,check_function(...)可以認為已經收到一幀
「完整」資料。然後就去按著常規的方式去解析:
1)找幀頭,如果成功則執行步驟2,否則丟棄;
2)找幀尾,如果成功則執行步驟三,否則丟棄;
3)檢查校驗,如果成功則通知協議解析,否則丟棄;
如果成功,丟給協議解析函式,否則直接丟棄,並清空快取;
這種方式很簡單,基本沒什麼難度,按著幀格式校驗就可以。
再來看看另外一種:
底層驅動負責入隊操作,check_function負責出隊操作,同時負責檢查,其編寫邏輯就不能
按著上面的步驟直接操作了。要利用狀態機的思維,首先定義出幾個狀態,然後根據狀態去
做相應的事情。
enum{
fsm_start = 0,
fsm_wait_head,
fsm_wait_tail,
fsm_wait_user_read
fsm_start:做一些初始化工作,必須保留。
fsm_wait_head:查詢幀頭,其邏輯如下:
如果接收資料 < 幀頭資料個數,把資料儲存到快取,直接返回;
如果沒有找到幀頭,則保留快取區最後的幀頭資料個數-1個資料,其它丟棄,返回;
如果找到幀頭,則直接丟棄幀頭前面資料,同時把幀頭以後資料複製到快取頭開始處
(這是為了處理方便,當然也可以用環形的處理方式),狀態機跳到fsm_wait_tail。
fsm_wait_tail:等待幀尾,其邏輯如下:
如果快取資料《計算出的幀長總個數儲存資料,直接返回;
檢驗幀尾,如果錯誤,則丟棄快取第乙個位元組,goto到fsm_wait_head;
校驗幀校驗位,如果錯誤,則丟棄快取第乙個位元組,goto到fsm_wait_head;
跳轉到fsm_wait_user_read:什麼都不幹,不能出隊,也不能對快取進行操作,
就是直接返回 true;(為了做同步)
使用者檢查到true,就會呼叫read_data(。。。)把檢查到一幀資料,拷貝到使用者快取區,
同時自動復位狀態機;
注意點:
1、丟棄快取第乙個位元組,goto到fsm_wait_head,是為了防止由於上幀資料接收到
一部分(後面的資料丟失),引起下幀資料錯誤問題;
2、最好有個接收超時,然後整幀校驗,復位狀態機;
3、用goto是為了更好的解決邏輯問題,使邏輯更清晰;
有時間再去說說如果去做協議分析。以上觀點都是本人愚見,還請大神們不吝指教。
uart串列埠學習筆記
uart是universal asynchronous receiver and transmitter簡稱,中文為通用非同步接收和傳送器,是常用的序列通訊介面。uart的作用是列印串列埠輸出資訊和連線各種外用裝置 優點是硬體簡單,而且傳輸資訊穩定 但是缺點也很明顯,傳輸資訊非常慢,因為uart是以...
ZigBee學習二 UART通訊
在使用串列埠時,只需掌握zigbee協議棧提供的串列埠操作相關的三個函式即可。uint8 haluartopen uint8 port,haluartcfg t config uint16 haluartread uint8 port,uint8 buf,uint16 len uint16 halu...
msp430學習筆記之uart
msp430系列,usart模組的波特率值設定是通過以下三個引數決定的 uxbr0,uxbr1,uxmctl 波特率 brclk n brclk 時鐘源,可以通過暫存器設定何為時鐘源 n 波特率產生的分頻因子。n uxbr1 uxbr0 uxmctl,其中uxbr1 uxbr0為整數部分,uxmct...