昨天分享了整個程序的架構,今天重點分析一下串口接收數據這塊的機制
我們知道,通過串口接收數據一般有3中方式,輪詢、中斷以及DMA。輪詢模式為堵塞模式,必須要定時去查詢收到的數據;中斷模式為非堵塞模式,也是平時用的比較多的,但每次只能接收一個字節;還有一個比較好的方法那就是用串口的空閑中斷+DMA實現串口數據的接收,在接收一幀數據只需要中斷一次,這樣就可以接收不定長數據了。機智云這里采用的方式2,即常規的中斷方式。
數據通訊采用的串口2,引腳為GPIO2和GPIO3,在gizwitsInit()中進行初始化
我們進去看看
上圖主要初始化了一些硬件接口,并開啟中斷,這也是我們一般的寫法,再往下看,看到一個pRb的結構體,這是個什么呢,我們追蹤下,下面是pRb的定義
我們先來解釋下環形緩沖區的原理:
環形緩沖區通常有一個讀指針和一個寫指針。讀指針指向環形緩沖區中可讀的數據,寫指針指向環形緩沖區中可寫的緩沖區。通過移動讀指針和寫指針就可以實現緩沖區的數據讀取和寫入。在通常情況下,環形緩沖區的讀用戶僅僅會影響讀指針,而寫用戶僅僅會影響寫指針。
這里的rbCapacity代表緩沖區的容量,head指向了讀區域,tail指向了寫區域,rbBuff指向緩沖區的入口地址,示意圖入下
明白了結構體的定義,我們接著往下看
rbCreate(),顧名思義,此函數的作用用于創建緩沖區,將緩沖區的head/Tail都指向緩沖區的首地址,那么rbCapacity和rbBuff在哪里賦值的呢?我們返回去看gizwitsInit();
看到這里我們就明白了,繼續往下看
這個函數為刪除緩沖區函數,將結構體里面的數據全部清零
這個函數為獲取緩沖區的總容量,很好理解
接下來這個函數為緩沖區有多少數據可以讀,有三種情況:
1、Head和Tail都指向同一個地址,可讀大小為0,返回0,這種情況只會出現在緩沖區還沒有數據的時候,使用之后就不會出現頭尾重合的現象;
2、Head
3、Head>Tail,如下圖所示,緩沖區已經寫滿,并且從開頭處重新寫了數據,可讀部分為藍灰色區域(rb_capacity(rb) - (rb->rb_head - rb->rb_tail));
接下來的函數為可寫區域大小,直接用總容量rb_capacity(rb)減去可讀區域大小就好了。
然后是讀數據函數,從Head處開始讀,讀取count個數據,放到data地址開始的數據區域,如下圖所示,也是分為三種情況
1、Head
2、Head>Tail,且count中的數據小于從Head到緩沖區尾部的個數,即小于下圖中的藍灰色,與第一種情況一樣,直接復制相應內存,之后修改Head指針即可。
3、Head>Tail,且count中的數據大于從Head到緩沖區尾部的個數,即大于下圖中的看灰色,這種情況我們就先把Head到緩沖區尾部的數據復制到data處,再把綠色區域的復制過去,這里綠色部分并不會超過Tail,寫操作中做了限制。
最后是寫數據函數,把從data指向的地址,寫到Tail指向的地址,寫count個數據,返回成功寫入的個數,在這里判斷了要寫入的數據大小要小于可寫區域大小,防止數據覆蓋,如下圖所示,也是分為三種情況
1、Head
2、Head
3、Head>Tail,這個因為已經做了數據合法判斷,所以直接復制數據就行。如下圖所示
那么明白了串口環形buff的機制,數據是從哪里進入的呢,我們找到串口中斷的入口,
可以看到中斷程序非常簡單,中斷之后直接往緩沖區丟一個數據就行了,采用這種數據結構,大大提高了程序的穩定性,同時操作起數據來也很方便,需要的時候直接去讀緩沖區數據就好了。今天就先分享這么多,下期分享機智云的協議與結構體的定義,謝謝大家!
-
串口
+關注
關注
14文章
1543瀏覽量
76190 -
源代碼
+關注
關注
96文章
2944瀏覽量
66668 -
機智云
+關注
關注
2文章
581瀏覽量
26368
原文標題:Gokit3.0 STM32源代碼分析之二
文章出處:【微信號:IoTMaker,微信公眾號:機智云開發者】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
相關推薦
評論