本篇文章主要介紹stm32串列埠接收不定長資料,採用比較通用的超時分包的方法,不依賴於空閒中斷(因為有些微控制器是沒有空閒中斷的),而是使用定時器判斷超時,希望能給人以收穫。
使用mdk5.25版本,晶元包為stm32f4系列。
開發板:stm32f407vgt6開發板,是一款大容量晶元,最高能跑168mhz。
燒錄器:stlink或者jlink。
其實用滴答定時器就可以完成本實驗的,不過為了介紹一下其他定時器及其中斷,所以就選了通用定時器來完成本實驗。因為系統初始化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進入一次中斷服務程式,並把列印替換成串列埠超時分包函式
在主函式中加入串列埠接收處理函式
因為多開中斷會影響系統實時性,所以大可不必開乙個硬體timer,可以直接把串列埠超時分包函式放到滴答定時器中斷裡面,對於stm32高波特率通訊,最好選擇dma+串列埠空閒中斷完成,不然會遇到例如串列埠溢位中斷,或者中間丟位元組錯位元組等各種各樣的問題。
這個方法使用各種型別的微控制器,是一種通用的串列埠接收不定長資料的方法,希望大家能有所收穫。
stm32關定時器 STM32定時器TIM3程式
include led.h include delay.h include key.h include sys.h include usart.h include timer.h stm32開發板實驗8 定時器中斷實驗 int main void delay init 延時函式初始化 nvic co...
stm32通用定時器
stm32的定時器是個強大的模組,定時器使用的頻率也是很高的,定時器可以做一些基本的定時,還可以做pwm輸出或者輸入捕獲功能。時鐘源問題 名為timx的有八個,其中tim1和tim8掛在apb2匯流排上,而tim2 tim7則掛在 apb1匯流排上。其中tim1 tim8稱為高階控制定時器 adva...
stm32的定時器
stm32一共有8個都為16位的定時器。其中tim6 tim7是基本定時器 tim2 tim3 tim4 tim5是通用定時器 tim1和tim8是高階定時器。1.基本定時器 基本定時器tim6和tim7只具備最基本的定時功能,就是累加的時鐘脈衝數超過預定值時,能觸發中斷或觸發dma請求。由於在晶元...