|
有人使用STM32G4系列的USART,并開啟DMA方式的定長接收,DMA工作在Normal模式,但是偶爾會出現(xiàn)接收出錯問題。令人頭疼的是一旦出錯了后面的接收總是錯的,出錯的位置往往體現(xiàn)在一幀的第一個數(shù)據(jù)。除非重啟系統(tǒng)才能消除接收連續(xù)出錯問題。下面兩幅圖是UART接收出錯的情形!緸榱吮阌诮涣鳎竺娴亩ㄩL接收都是指8個字符的接收。】
anwvvbetrot6405507120.png (91.54 KB, 下載次數(shù): 3)
下載附件
保存到相冊
anwvvbetrot6405507120.png
2024-8-21 13:20 上傳
11dayj3dn036405507220.png (83.16 KB, 下載次數(shù): 1)
下載附件
保存到相冊
11dayj3dn036405507220.png
2024-8-21 13:20 上傳
使用場景大致是這樣的。某工程師使用STM32G474開發(fā)產(chǎn)品,用到某USART的DMA收發(fā)。MCU通過USART跟外部傳感器進(jìn)行通信,USART的收發(fā)都使用DMA方式,Normal模式。兩端的收發(fā)都是定長方式,即收發(fā)都是基于確定長度的傳輸。
實際調(diào)試過程中,他發(fā)現(xiàn)STM32G4芯片的USART的DMA發(fā)送倒沒啥問題,就是接收偶爾會出錯。一旦出錯,后面就一直錯。通信兩端明明使用的定長數(shù)據(jù)的收發(fā),數(shù)據(jù)怎么會錯亂?即使偶爾出差了要怎樣才能及時恢復(fù)正常呢?
后來經(jīng)反復(fù)檢查確認(rèn),他說的定長收發(fā)只是理論上的或者說預(yù)期的。實際上,在通信過程中偶爾會有額外的噪聲竄出來,即傳感器端實際發(fā)送過來的數(shù)據(jù)可能多于指定長度。多發(fā)的數(shù)據(jù)雖然沒有被當(dāng)次接收,但留在USART接收FIFO了。下次基于DMA接收時,F(xiàn)IFO數(shù)據(jù)若沒被清掉就會當(dāng)作下一次的接收數(shù)據(jù)了。
因為接收這邊是DMA定長接收,發(fā)送端也是定長發(fā)送,但由于FIFO里噪聲數(shù)據(jù)的存在,接收端沒法全部接收新的數(shù)據(jù),使得FIFO里始終有殘留數(shù)據(jù),進(jìn)而導(dǎo)致后續(xù)的接收發(fā)生錯位。
下面截圖是STMG4的USART的功能框圖,看看有助于理解。
h3ejrvmjbpb6405507320.png (90.65 KB, 下載次數(shù): 2)
下載附件
保存到相冊
h3ejrvmjbpb6405507320.png
2024-8-21 13:20 上傳
既然這樣,我們可以在每次的USART的定長接收完成之后、開啟下一次DMA接收前,將USART的FIFO清理干凈。當(dāng)然這個過程中,要注意溢出問題,發(fā)生溢出后會妨礙DMA請求的產(chǎn)生,我們需及時處理溢出標(biāo)志。
下面簡單演示解決上面問題的做法。使用STM32G474的USART2的DMA收發(fā)功能,STM32G474的USART每次從PC的串口終端做8個字符的定長接收,多余的將被丟棄并不可以影響下次接收,同時,STM32G474將每次收到的8個字符回顯到PC串口終端。開啟USART DMA接收的完成中斷,每次收到8字符時設(shè)置相應(yīng)的標(biāo)志【Flag_Rxcpt】,并稍作延時,保證一次性發(fā)送過來的字符發(fā)送完畢。注意,是保障對方的發(fā)送完畢,接收的話每次只接收8個字符。
下面的測試使用STM32G474的USART2的配置如下:
jnjkjova5se6405507421.png (124.1 KB, 下載次數(shù): 4)
下載附件
保存到相冊
jnjkjova5se6405507421.png
2024-8-21 13:20 上傳
zt3pus2tjkw6405507521.png (134.38 KB, 下載次數(shù): 3)
下載附件
保存到相冊
zt3pus2tjkw6405507521.png
2024-8-21 13:20 上傳
USART收發(fā)的FIFO可開可關(guān),下面做法都適用。另外,這里沒有使能USART2的中斷響應(yīng),使用庫函數(shù)組織代碼的話最好使能它,可以省些事。
解決上面問題的第一種做法就是每次在開啟下次DMA接收前將USART重新初始化一下,這個肯定是有效的。沒理由重新初始化USART了,其FIFO數(shù)據(jù)還不失效吧。見下圖紅框中的代碼。
k1fuxz3u3cw6405507621.png (213.27 KB, 下載次數(shù): 4)
下載附件
保存到相冊
k1fuxz3u3cw6405507621.png
2024-8-21 13:20 上傳
下面是USART DMA接收完成中斷的回調(diào)處理函數(shù)。接收到8個字符后設(shè)置接收標(biāo)志,并設(shè)置延時參數(shù),讓對方或線路上可能多發(fā)或多產(chǎn)生的數(shù)據(jù)發(fā)送完畢。
30epaz4nzh36405507721.png (80.99 KB, 下載次數(shù): 1)
下載附件
保存到相冊
30epaz4nzh36405507721.png
2024-8-21 13:20 上傳
不過這個操作動作有點大,有時可能不太合適。我們可以換個做法,像下面這樣,通過查詢RXNE標(biāo)志來讀取接收數(shù)據(jù)寄存器。其實就是將FIFO里的殘留清掉,同時預(yù)防性地對溢出標(biāo)志清零。
j2345knkftr6405507821.png (228.68 KB, 下載次數(shù): 4)
下載附件
保存到相冊
j2345knkftr6405507821.png
2024-8-21 13:20 上傳
如果前面使能了USART的中斷響應(yīng),基于庫函數(shù)組織代碼時,此處對溢出標(biāo)志清零就不必要了,可以到中斷服務(wù)程序里處理。顯然第二種做法更有針對性,動作不波及其它。
當(dāng)然,還有另外一種做法,通過操作特定寄存器清空USART接收FIFO。具體就是對USART_RQR寄存器的RXFRQ位寫1,發(fā)起對接收FIFO清空的請求。操作代碼如下:
oqophsn2ofc6405507921.png (18.93 KB, 下載次數(shù): 1)
下載附件
保存到相冊
oqophsn2ofc6405507921.png
2024-8-21 13:20 上傳
下面是基于上面幾種做法的驗證結(jié)果。USART接收時DMA每次只搬8個數(shù)據(jù),多發(fā)過來的數(shù)據(jù)不予理睬,也不影響后續(xù)的再次接收。
qo5jmejbmxn6405508022.png (64.94 KB, 下載次數(shù): 3)
下載附件
保存到相冊
qo5jmejbmxn6405508022.png
2024-8-21 13:20 上傳
不管哪種做法,最終目的都一樣,即在開啟下次的USART接收前先清空接收FIFO。OK,今天的分享就到這里,下次再聊~!
猜你喜歡:
WiFi6+藍(lán)牙+星閃,三合一開發(fā)板,真香!
Github上熱門 C 語言項目匯總!
嵌入式,可測試性軟件設(shè)計!
一些低功耗軟件設(shè)計的要點!
嵌入式 C 保護(hù)結(jié)構(gòu)體的方式
實用 | 10分鐘教你通過網(wǎng)頁點燈
談?wù)勄度胧杰浖募嫒菪裕?/strong> |
|