UART學習筆記二:如何去check資料幀
接著以前的文章(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是為了更好的解決邏輯問題,使邏輯更清晰;
有時間再去說說如果去做協議分析。以上觀點都是本人愚見,還請大神們不吝指教。