在這個實驗中,我們基於滴答定時器實現精確延時功能,當然想要實現精確的延時功能也不一定非得使用滴答定時器,使用其它定時器一樣可以實現,其實現的原理是一樣的。這里我們雖然借用了滴答定時器,但是不占用滴答定時器的中斷,只是不斷的去讀取滴答定時器的寄存器,從而實現延時功能。如果想要在項目中移植實時操作系統,下面的延時功能代碼也無需做什么改變,同時也不會對系統內核產生影響(注:這里的不會影響是基於大部分系統的時鍾節拍為1ms)。
代碼如下:
#include "stm32f4xx.h"
#include "delay.h"
#include "delay.h"
/********************************************************
* 函數功能:初始化滴答定時器
* 形 參:無
* 返 回 值:無
********************************************************/
void systick_init(void)
{
// Reload為24位寄存器,最大值:16777216,在168M下,約合0.0998s左右
SysTick->LOAD = SystemCoreClock / 1000UL; // 配置中斷時間為1ms
SysTick->CTRL |= SysTick_CLKSource_HCLK; // 內部時鍾配置為168MHz
SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk; // 開啟SYSTICK
SysTick->CTRL |= SysTick_CTRL_TICKINT_Msk; // 開啟SYSTICK中斷
}
* 函數功能:初始化滴答定時器
* 形 參:無
* 返 回 值:無
********************************************************/
void systick_init(void)
{
// Reload為24位寄存器,最大值:16777216,在168M下,約合0.0998s左右
SysTick->LOAD = SystemCoreClock / 1000UL; // 配置中斷時間為1ms
SysTick->CTRL |= SysTick_CLKSource_HCLK; // 內部時鍾配置為168MHz
SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk; // 開啟SYSTICK
SysTick->CTRL |= SysTick_CTRL_TICKINT_Msk; // 開啟SYSTICK中斷
}
/********************************************************
* 函數功能:使用滴答定時器做的微秒級延時函數(強阻塞)
* 形 參:nus:延時時間,單位:微秒
* 返 回 值:無
********************************************************/
void delay_us(unsigned short nus)
{
unsigned int wait_time = 0UL;
unsigned int check_time = 0UL;
unsigned int start_time = SysTick->VAL; // 計數器值
unsigned int total_time = (SystemCoreClock / 1000000UL) * nus;
// 注:SysTick是一個遞減的計數器
while(wait_time < total_time)
{
start_time = check_time;
check_time = SysTick->VAL;
if(check_time < start_time)
{
wait_time += start_time - check_time;
}
else if(check_time > start_time)
{
wait_time += SysTick->LOAD - check_time + start_time;
}
}
}
while(wait_time < total_time)
{
start_time = check_time;
check_time = SysTick->VAL;
if(check_time < start_time)
{
wait_time += start_time - check_time;
}
else if(check_time > start_time)
{
wait_time += SysTick->LOAD - check_time + start_time;
}
}
}
/********************************************************
* 函數功能:使用滴答定時器做的毫秒級延時函數(強阻塞)
* 形 參:nms:延時時間,單位:毫秒
* 返 回 值:無
********************************************************/
void delay_ms(unsigned short nms)
{
delay_us((unsigned int)(nms * 1000UL));
}