关于单片机串口接收不固定字节长度的解决方案
之前老是有個問題困惑著小編,串口這種一字節一字節的接收和發送的機制,而在實際應用中如果收發雙方不制定一個協議,沒有幀頭,幀尾做一幀數據接收開始和結束的標準。或者收發數據長度不固定,怎么去確定每一幀長度不同的幀呢?
面對這種每次發送長度不固定的情況,我最開始采用的是定時器中斷加串口中斷的方式。
? ? 如現在來了一幀長度為86字節的數據,我在串口接收中斷中將這86個字節一一入循環隊列,假設循環隊列的長度是256個字節,現在86個字節已經接收完畢,那么,我在哪里出隊來確保這86個字節能一次性出完呢,很多人可能考慮的是主函數輪詢出隊,但是你可想過,如果主函數里面處理的任務不多,導致輪詢過快,如果此時出隊列就會導致86個字節出隊時不能出完,從而會被多次拆分形成多幀數據,處理數據無效。
? ? 所以可以采用定時器中斷,每80ms中斷一次,每次中斷,數據出隊列,80ms已經可以實現一次性接收256個字節都會完整的出隊了。而且80ms肉眼基本看不出,只能看到這邊發送,那邊就已經把完整的數據打印出來了,而且256個字節以內任意發多少,都沒有數據被拆分,丟失的問題。這樣顯然是初步解決了任意長度發送,接收的問題,但是在實際應用使用中,如果要求串口高速度,發不定長的數據,就會出現一系列的問題,如現在客戶要求任意長度的一幀數據,我連續發送多幀,而且每幀的時間間隔要小于10ms,并且我們之間收發沒有通信協議,我想給你發什么就發什么,你要解析數據。面對這種客戶要求這種定時器中斷加串口中斷肯定是不行了的。那么采用什么會有效解決這個問題呢。
? ? 仔細看單片機的數據手冊關于串口中斷的描述,會發現,其實串口中斷中,存在一個空閑中斷,這個空閑中斷幫了我大忙,空閑中斷并不是說串口空閑就觸發,這樣的話豈不是串口如果沒有數據過來,空閑中斷一直觸發,那么整個程序不就一直處于中斷之中嘛??臻e中斷是指,當最后一個字節接收完畢后,硬件接收中斷接收完數據后使得IDLE寄存器中的標志位置高,于是,我們便可以采用此空閑中斷標志置高來提醒主程序可以出隊,因為一幀數據已經發送完畢了。
1、下圖為初始化時使能串口接收中斷和空閑中斷,及重寫串口中斷函數方法:
?注意:USART5_IRQHandler函數里面,用關于先讀SR,再讀DR是為了清除空閑中斷標志,以至于下一幀數據還能觸發此中斷,而下面那個變量置1,提醒主程序一幀數據接收完畢,你該去處理了。
2、下圖為在主程序里輪詢檢測數據結束標志,如果標志被置1則進行相應處理。
?注意:uart5_handle函數里面據實際情況而實現,如果你只想單純的轉發數據,那么直接判斷隊列里數據長度,根據長度出隊所有數據,然后進行轉發就行,如果需要解析處理數據的話,也可以先出隊再解析處理。
以上就是關于單片機接收不定長數據的解決方案的全部處理過程,其中如果收發雙方如果制定了協議,則可以根據協議收發不定長數據。如果沒有串口通信協議則可以使用,串口接收中斷加串口空閑中斷的方式處理!!小編也是剛剛入坑不久,歡迎各位大佬對不對的地方評論。謝謝!!
?
總結
以上是生活随笔為你收集整理的关于单片机串口接收不固定字节长度的解决方案的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: ios swift5 弹出原生的提示框(
- 下一篇: ios swift 5 UIView切圆