1. 程式人生 > 實用技巧 >STM32標準庫_05用定時器寫通用串列埠接收

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+串列埠空閒中斷完成,不然會遇到例如串列埠溢位中斷,或者中間丟位元組錯位元組等各種各樣的問題。

這個方法使用各種型別的微控制器,是一種通用的串列埠接收不定長資料的方法,希望大家能有所收穫。