【STM32】STM32定时器延时/粗略延时1us的对比以及结论

写在前面

最近毕设中用到了DS18B20,就重新调试了一下,发现一直工作不正常。检查驱动没有问题之后,最终发现是delay_us的问题。自己延时微秒一直用的是之前封装好的循环x个时钟周期来实现,但用逻辑分析仪采样(条件有限)后发现跟实际相差甚远。
经过实践之后就把自己两种延时的方法贴出来分享。
下文均以STM32F1为例,时钟频率为72MHz

粗略延时1us

时钟频率为72MHz,1个时钟周期为1/72us,理论上延时1us就需要72个时钟周期。
实际中需要再除一个调整的数Adjust ,才能达到想要大的微秒。有兴趣的可以自行实践下,我测试的Adjust为12时1-10us相对比较准。
Adjust为12时,1us、5us、10us、15us、20us、25us、50us、100us、200us、300us、500us、1000us的实际时间为1.75us、4.75us、9.25us、13.5us、17.5us、21.5us、42.75us、84us、167.75us、253、417.5us、836.5us
可以看到,粗略延时在延时数不高的时候(比如15us以内)相差不大,但延时数变高之后就相差甚远了
代码如下:

#define Adjust 12
void HAL_Delay_us(uint32_t us, uint16_t CLK_MHz )
{
    uint32_t Delay = us * CLK_MHz / Adjust;
    do
    {
        __NOP();
    } while (Delay --);
}

//调用
HAL_Delay_u(1, 72);//延时1us, 时钟为72MHz

定时器延时1us

配置定时器1,tim1的时钟频率为72MHz,
设置PSC=72-1,则定时器的计数频率为1MHz,即1us计数一次
设置ARR为任意数,之后在程序中设置。
【STM32】STM32定时器延时/粗略延时1us的对比以及结论_第1张图片
代码如下

void HAL_Delay_us(uint16_t us)
{
	uint16_t counter = 0;
	__HAL_TIM_SetAutoreload(&htim1, us);		//设置定时器自动加载值
	__HAL_TIM_SetCounter(&htim1, counter); 		//设置定时器初始值
	HAL_TIM_Base_Start(&htim1); 				//启动定时器

	while(counter != us) //直到定时器计数从0计数到us结束循环,刚好是所需要的时间
	{
		counter = __HAL_TIM_GetCounter(&htim1); // 获取定时器当前计数
	}
	HAL_TIM_Base_Stop(&htim1); // 停止定时器
}

经过测试,第二种方法延时1us、5us、10us、15us、20us、25us、50us、100us、200us、300us、500us、1000us的实际时间为4.5us、8.25us、13.25us、18us、23.25us、28.5us、53.25us、103.25us、203.25us、303.25us、503.5us、1003us
可以看到,用定时器延时,函数执行时间大约稳定在3.25us左右,无论延时时间长短,均表现稳定

小结

延时精度要求不高、延时微秒数比较小,可以用粗略延时。否则就必须开定时器进行了。

你可能感兴趣的:(STM32,stm32,单片机,嵌入式硬件)