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