STM32標准庫_05 | 用定時器寫通用串口接收


本篇文章主要介紹STM32串口接收不定長數據,采用比較通用的超時分包的方法,不依賴於空閑中斷(因為有些單片機是沒有空閑中斷的),而是使用定時器判斷超時,希望能給人以收獲。

1.開發環境

軟件環境

使用MDK5.25版本,芯片包為STM32F4系列。

硬件環境

開發板:STM32F407VGT6開發板,是一款大容量芯片,最高能跑168MHz。

燒錄器:STlink或者Jlink。

2.工程搭建

注釋掉串口空閑中斷相關代碼

直接復制上一篇代碼,然后先把串口空閑中斷給去掉,在uart1_Init和串口1中斷服務函數中把串口空閑中斷的部分注釋掉(當然用#if代碼會更規范)。

添加定時器相關代碼

其實用滴答定時器就可以完成本實驗的,不過為了介紹一下其他定時器及其中斷,所以就選了通用定時器來完成本實驗。因為系統初始化SystemInit函數里初始化APB1總線時鍾為4分頻即42M,APB2總線時鍾為2分頻即84M(可以查看F407的時鍾樹),TIM1、TIM8 ~ TIM11的時鍾為APB2時鍾的兩倍即168M,TIM2 ~ TIM7、TIM12 ~ TIM14的時鍾為APB1時鍾的兩倍即84M。

本實驗我們選擇定時器3(TIM3)來完成,定時器時鍾為84M。然后添加定時器初始函數和定時器3中斷服務函數。

定時器測試

先定時500ms,用於打印測試,記得把定時器3的初始化放在串口初始化后面,因為我們在定時器中斷服務函數里面打印了數據,所以要防止printf打印時串口沒有初始化而導致死機。

通過上圖也可以發現一個問題,那就是定時器初始化完之后馬上就進入了一次中斷,所以我們改進一下代碼,把

TIM_ClearFlag(TIM3,TIM_FLAG_Update);     //清除定時器3中斷標志

加入定時器3的初始化函數中

發現達到了預期效果,其實我測試使用TIM_ClearITPendingBit(TIM3,TIM_IT_Update)也能達到這樣的效果(有些帖子說不行,但一切以實際為准)。

定時器使用小結

可能很多人會問,自動重裝載值和預分頻系數怎么去選擇,其實我們可以根據定時的時間結合定時器的位數共同去決定。重裝載值是不能超過定時器位數所能容納的值的,舉個例子如果定時器是8位的,那么能計數的值也就是0~255,所以我們不能超過它的范圍。

串口超時時間的判斷

首先我們來看看串口通信的時序圖。

從上圖可以看出,空閑的時候串口電平為高電平,起始信號是低電平,然后傳輸8個數據位,如果有奇偶校驗就在數據位后面加上一位奇偶校驗位(默認無奇偶校驗),還有一位停止位,總共10位數據,代表傳輸了一個字節的數據。波特率為9600的時候,通信率 I = 9600 * log22 = 9600bit/s。

所以一個字節的傳輸時間為:1/960Byte(單位秒) 約等於 1.04ms(干脆算作1ms),同理115200波特率快了10倍,所以一個字節的傳輸時間為:100us。因此我們定時器定時為100us(串口超時分包設為10個字節的時間)。

編寫串口接收代碼

定義串口結構體

編寫串口接收終端函數與串口超時分包函數

編寫串口接收處理函數

修改定時器初始化為100us進入一次中斷服務程序,並把打印替換成串口超時分包函數

在主函數中加入串口接收處理函數

3.收發測試

4.后記

因為多開中斷會影響系統實時性,所以大可不必開一個硬件Timer,可以直接把串口超時分包函數放到滴答定時器中斷里面,對於STM32高波特率通信,最好選擇DMA+串口空閑中斷完成,不然會遇到例如串口溢出中斷,或者中間丟字節錯字節等各種各樣的問題。

這個方法使用各種類型的單片機,是一種通用的串口接收不定長數據的方法,希望大家能有所收獲。

代碼已全部上傳到gitee,希望各位小伙伴們在下載的同時不忘點擊Star,地址:https://gitee.com/Notmi/stm32-standard-peripheral-libraries


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM