STM32HAL库微秒延时(μs)
单片机:STM32F407ZET6
软件版本:STM32CubeMX 4.20.1
单片机固件包:STM32Cube FW_F4 V1.15.0
本代码是我于2019年8月参加全国大学生电子设计竞赛前做赛前准备时参考网络上博客的程序代码编写,仅用于学习和交流。希望能给各位读者些许帮助。
本博客对于STM32单片机实现微秒(μs)延时采用的是定时器计数的方法。以STM32F407ZET6型号单片机的TIM4为例来进行代码展示。
先设置TIM4的时钟源:
STM32F407ZET6的TIM4的时钟为APB1的两倍即84MHz。
设置TIM4参数:
因为是微秒延时,所以计数频率应为f=1/1μs=1MHz。所以预分频Prescaler应为(84/f)-1=83,理论上来说计数周期Counter Period的设置将影响中断时长,而微秒延时只是计数并不需要开启定时器的中断。但是在实际开发过程中我将Counter Period设置为0结果延时时间变成随机时长,因此建议Counter Period不要设置为0。
微秒延时函数:
void Delay_us(uint16_t myus)//基于TIM4定时器的μs延时函数
{
uint16_t differ = 0xffff-myus-5;
HAL_TIM_Base_Start(&htim4);
__HAL_TIM_SetCounter(&htim4,differ);
while(differ < 0xffff-5)
{
differ = __HAL_TIM_GetCounter(&htim4);
}
HAL_TIM_Base_Stop(&htim4);
}
因为我是使用STMCubeMX搭建的工程,因此需要将这段延时函数加进tim.c中的 /* USER CODE BEGIN 1 / 和 / USER CODE END 1 / 中,并在tim.h中的 / USER CODE BEGIN Prototypes / 和 / USER CODE END Prototypes */ 中加上 void Delay_us(uint16_t ); 做函数声明。
接下来,我对这个微秒延时函数做一些解释说明:
- 函数功能解释:
HAL_StatusTypeDef HAL_TIM_Base_Start(TIM_HandleTypeDef *htim) 启动定时器;
HAL_StatusTypeDef HAL_TIM_Base_Stop(TIM_HandleTypeDef *htim) 关闭定时器;
__HAL_TIM_SetCounter和__HAL_TIM_GetCounter可在头文件stm32_hal_legacy.h中找到定义:
__HAL_TIM_SET_COUNTER 设定计数初值,默认是0;
__HAL_TIM_GET_COUNTER 获取当前计数值。 - STM32单片机的定时器基本都是16位计数器每次记到0xffff就会重载arr值。因此给定时器应至少赋予初值为0xffff-myus。
- 为什么我在定时器基本初值的基础上还要再“-5”呢?
这是为了防止因中断打断延时,造成计数错误。
以延时1μs为例:延时1us因而应从0xfffe开始计数,但假设在这过程产生中断。由于被中断打断(此时计数器仍在计数),本因计数至0xffff便停止计数,但由于错过计数值,并重载arr值,将会导致实际延时(0xffff+1)us。