你點擊藍字關注,回復“入門資料”獲取單片機入門到高級開掛教程
?開發板帶你入門,我們帶你飛
文 |?無際(微信:2777492857)
全文約1661字,閱讀大約需要?5?分鐘
我做過挺多串口通訊類的產品,有用485通訊的pdu,有wifi/4G/藍牙通訊類的網關...
做串口的應用,把串口外設調通只是第一步,串口只是數據傳輸的媒介,在此基礎上,兩個設備/器件要進行通信,傳遞更有意義的信息,還需要一個通訊協議。
如果沒有協議設計經驗,可以用標準協議,比如Modbus。

也可以自己設計通信協議,比如我們無際項目特訓營的物聯網串口通訊協議。

該協議負責網關和云平臺/APP的數據交互。

串口通訊的難點和重點,不在于串口外設本身,而是基于串口的增值功能,比如協議設計和解析,其穩定性的考量。
早期做pdu的時候,用485通訊,Modbus協議,我是做從機,當時沒什么經驗,總是做不穩定,如果是碰上那種對成本要求很苛刻的產品,比如連一個電容錢都要省的,調起來極其惡心,想把公司電腦都砸了。
解析協議數據時,寫程序也非常頭疼,最常見的就是定義數組作為緩存,去接收數據,不過用這種方式程序寫起來比較麻煩,全局變量滿天飛。
如果一邊接收,一邊解析,然后再發送數據,難免會有多個程序同時訪問和修改數組的情況,這樣管理數據的插入和刪除,就會大大增加了程序的復雜性。
如果沒有足夠的經驗,很容易引起數據錯亂,丟包,就是一幀協議數據,丟了其中1個或者幾個字節。
所以,這篇文章,是解決如何用應對高頻數據流的問題,這種方法,不僅僅能用于串口,也適用其它大數據流處理的場景。
這個時候,需要用到一種數據結構,叫隊列。
隊列可以更好地保證數據的完整性和順序,因為隊列是先進先出(FIFO)的數據結構,而數組可能會因為覆蓋或重新分配而導致數據順序混亂。
其實隊列,也沒想象中這么玄乎,就是在數組/內存里面,寫一些入列/出列的小算法,去管理這些數組/內存。
如果想學寫隊列這種數據結構,我知道的兩個渠道。
第一,可以看我2018年錄制的那套程序架構教程,里面有手把手教寫隊列代碼的章節。


通過這些結構體,可以根據應用場景,定義不同大小的隊列。
然后通過4個函數,去管理定義好的隊列,比如清空、入列、出列、判斷隊列有效數據長度。



這個隊列相對簡單,缺點是只能入列單個字節的數據類型,不過大多數單片機項目也夠用。
第二,RTOS也有隊列代碼,不過是用鏈表這種數據結構,更加復雜一點,優點是支持任意數據類型入列。
我一般是用自己寫的那個,因為能100%掌控,使用也簡單,而且經過了大批量產品驗證,穩得一批。
下圖是我們用無際單片機特訓營項目3做的實驗,單片機型號為STM32F103,以10ms的頻率發送和接收串口數據,測試了32.5W個字節數據,0丟包。

這個代碼,我并沒有用DMA,如果用DMA,效率更高。
下面講下我是怎么做的,其實賊簡單。

DebugTxMsg是全局隊列,大小為256個字節,這個可以根據單片機資源、實際應用的數據量大小、頻率去調節。

當串口收到一個字節數據,我就直接丟進隊列里。什么數組下標++,判斷數組是否滿之類的操作,其實是在隊列入列函數里完成的,一次寫好后,無限復用。
然后,有專門的函數,用來處理隊列的數據,如果判斷隊列里有數據,就通過串口1再發送出去。

QueueDataOut是一個隊列數據出列函數,函數內部實現了先進先出的算法,所以我們完全不用管什么數組下標,數組還有多少數據之類的,也是一次寫好,無限復用,大大簡化了程序。
hal_debugProc這個函數,是一直main函數里輪詢執行的,所以只要隊列有數據,就會被發送出去。
這個階段,能夠測試數據接收是否完整,穩定,測試通過以后,再去實現協議解析的代碼。
寫程序有點像下棋,走一步看百步,前期搭好程序架構,后期做細節功能會很高效穩定。
end

下面是更多無際原創的個人成長經歷、行業經驗、技術干貨。
1.電子工程師是怎樣的成長之路?10年5000字總結
2.如何快速看懂別人的代碼和思維
3.單片機開發項目全局變量太多怎么管理?
4.C語言開發單片機為什么大多數都采用全局變量的形式?
5.單片機怎么實現模塊化編程?實用程度讓人發指!
6.c語言回調函數的使用及實際作用詳解
7.手把手教你c語言隊列實現代碼,通俗易懂超詳細!
8.c語言指針用法詳解,通俗易懂超詳細!