STM32的HAL库开发系列 - 延时
延时有几种实现的方法。
1是循环延时/NOP空语句延时。就是利用执行每行代码的时间进行延时。每个单片机都不同需要调试。
2是定时器中断延时。需要额外占用一个定时器。
3是用系统滴答计时器
/**
* @brief us延时
* @param[in] us
*/
#define TimebaseSource_is_SysTick 0
#if (!TimebaseSource_is_SysTick)
extern TIM_HandleTypeDef htim9; // 当使用FreeRTOS, TimebaseSource为其他定时器时
#define Timebase_htim htim9
#define Delay_GetCurrentValueReg() __HAL_TIM_GetCounter(&Timebase_htim)
#define Delay_GetReloadReg() __HAL_TIM_GetAutoreload(&Timebase_htim)
#else
#define Delay_GetCurrentValueReg() (SysTick->VAL)
#define Delay_GetReloadReg() (SysTick->LOAD)
#endif
static uint32_t fac_us = 0;
static uint32_t fac_ms = 0;
void Delay_us_init(void)
{
#if (!TimebaseSource_is_SysTick)
fac_ms = 1000; // 作为时基的计数器时钟频率在HAL_InitTick()中被设为了1KHz
fac_us = fac_ms / 1000;
#else
fac_ms = SystemCoreClock / 1000;
fac_us = fac_ms / 1000;
#endif
}
void Delay_us(uint16_t us)
{
/*** 定时器功能实现 ***/
uint32_t ticks = us * fac_us;
uint32_t reload = Delay_GetReloadReg();
uint32_t told = Delay_GetCurrentValueReg();
uint32_t tnow = 0;
uint32_t tcnt = 0;
while (1) {
tnow = Delay_GetCurrentValueReg();
if (tnow != told) {
if (tnow < told) {
tcnt += told - tnow;
} else {
tcnt += reload - tnow + told;
}
told = tnow;
if (tcnt >= ticks) {
break;
}
}
}
#ifdef Delay_Use_NOP
/*** NOP空语句实现 ***/
uint32_t delay = us * fac_us / 4;
do {
__NOP();
}
while (delay --);
#endif
}