運行環境
Windows10
STM32CubeMX
Version 5.4.0
Keil5(MDK5)
Version 5.28.0.0
硬件開發板
F103RB-NUCLEO
簡介
本例程主要講解如何使用STM32在不用定時器的情況下使用微秒延時函數.
STM32CubeMx基本配置
基礎配置過程請參考 STM32CubeMx開發之路—配置第一個項目
使用printf
功能
重定向printf
的過程請參考 STM32CubeMx開發之路—3發送USART數據和printf重定向
CubeMX配置
查看時鐘樹
- CubeMX不需要什麼特別的配置, 只需要查看一下時鐘樹就行了, 而且在代碼中也有專門的接口調用, 這兒大家瞭解一下, 由下圖可知, 系統的時鐘爲
72M HZ
.
代碼修改
- 本節的微秒延時主要是通過不斷獲取系統時間來實現的
- 在
main.c
文件中添加如下函數代碼
/**
* @bieaf 微秒延時函數
* @detail 注意:由於指令執行需要時間, 實際的延時精度約爲1微秒
*
* @param unsigned int Delay 延時的微秒
*/
void delay_us(unsigned int Delay)
{
uint32_t tickstart = SysTick->VAL; ///<獲取當前tick
uint32_t tickNum = 0;
uint32_t tickMax = SysTick->LOAD + 1;
uint32_t delay_usvalue = (tickMax / 1000) * Delay; ///<計算一共需要延時的tick
while(1)
{
uint32_t cur_tick = SysTick->VAL;
if (cur_tick > tickstart) ///<進行了一次重載
{
tickNum = tickstart + (tickMax - cur_tick);
}
else ///<未進行過重載
{
tickNum = tickstart - cur_tick;
}
if (tickNum > delay_usvalue) ///<達到延時的tick數
{
return;
}
}
}
- 在主函數
main()
中添加如下測試函數
while (1)
{
static unsigned int start_time = 0;
static unsigned int end_time = 0;
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
start_time = SysTick->VAL; ///<延時前獲取tick
delay_us(10); ///<延時
end_time = SysTick->VAL; ///<延時後獲取tick
printf("delay time tick is %d\r\n", start_time - end_time); ///打印輸出
HAL_Delay(1000);
}
/* USER CODE END 3 */
- 結果分析, 如下圖所示:
- 我們延時的時間爲10us, 會發現tick相差的是756,是不是我們的延時函數錯了呢?
- 進一步分析, 系統時鐘是
72M HZ
的, 也就是說1s系統時鐘走72M次, 也就是說1us走72次 - 10us的時間應該走
72 * 10 = 720
次,而我們測試的結果爲756次, 多了36次約爲0.5us - 這些時間是哪兒多出來的呢?
- 如果你使用過彙編, 你可能就知道, 進出函數的跳轉指令, 取指令, 讀指令, …等各種指令需要時間的,多出來的時間就是那些時間造成的誤差.
- 有沒有辦法消除這些誤差?
- 辦法是有的, 不過這和系統相關, 可以經過多次測試, 在延時函數裏面減去多的這些時間誤差, 這兒不詳細說明, 一般對於要用的微秒延時的像軟件IIC這樣的功能, 這些誤差是沒有影響的,大可放心使用.
源碼
備註:提供一下個人微信號 Hleafleafleaf,歡迎加好友,共同學習!共同進步!