针对stm32f103 MCU的延时方法及函数深入探讨
1 概述
在嵌入式开发过程中延时是很常见的操作。总体上延时方法有两种主要思路,本文分析两种种常见的延时方法,分析利弊,在项目开发中可以参考使用。
结论是:针对ms级别的延时使用操作系统的延时函数osDelay或者HAL_Delay,针对100us级别以下的延时,采用__NOP()函数调节,针对100us到1000us可以采用delay_us。测试还发现,针对72MHz主频的stm32f103 采用位段方式,IO翻转频率可以高达2.8797MHz,(也就是IO模拟clk时钟频率到达的最高频率)这应该是stm32f103 MCU IO翻转频率的极限了。采用HAL_GPIO_TogglePin翻转IO的最高的翻转速度大概562kHz。测试工程下载地址文末第3章节结论。
1.1 CPU空跑消耗时间
针对stm32f103 有几种常用的延时套路,部分参考代码如下
void Delay_1us(void)
{uint32_t i = 0;for(i = 0; i < 2; i++){__NOP();}
}
void Delay_xus(uint32_t xus)
{uint32_t i = 0;for(i = 0; i < xus; i++){Delay_1us();}
}
1.2 在有操作的系统,CPU切换任务消耗长延时+CPU空跑消耗时间短延时
这种方式,参考正点原子给出的方案,ms级别延时,调用操作系统的延时函数,us级别的延时,采用等待定时器计数的方式。实测发现us级别的延时不是太准确。部分参考代码如下:
void delay_us(uint32_t nus)
{uint32_t ticks;uint32_t told,tnow,tcnt=0;uint32_t reload=SysTick->LOAD; ticks=nus*fac_us; told=SysTick->VAL; while(1){tnow=SysTick->VAL;if(tnow!=told){if(tnow<told)tcnt+=told-tnow; //else tcnt+=reload-tnow+told;told=tnow;if(tcnt>=ticks)break; //}};
}
void delay_ms(uint32_t nms)
{if(xTaskGetSchedulerState()!=taskSCHEDULER_NOT_STARTED)//ϵͳÒѾÔËÐÐ{if(nms>=fac_ms) //{vTaskDelay(nms/fac_ms); //FreeRTOS}nms%=fac_ms; //}//delay_us((u32)(nms*1000)); //
}
2 实测
针对STM32F103的测试如下
主频配置在72MHz
2.1 测试delay_us(1)
//测试delay_us短延时
delay_us(1);
HAL_GPIO_TogglePin(LED_GPIO_Port, LED_Pin);
从上图看delay_us(1)的延时,最短也是3.5us,理论和实际还是又区别的,这里其实是那个函数的开销大了。使用时候要主要这个问题了。delay_us延时函数,延时100us从测试结果来看,还比较准确,小于100us偏差个人认为有点大了,谨慎点,还是要根据自己的需求,实测延时,能不能满足应用需求。
2.2 测试delay_us(1000000)
//测试delay_us长延时
delay_us(1000000);
HAL_GPIO_TogglePin(LED_GPIO_Port, LED_Pin);
从上图看,delay_us(1000000)比较准确
2.3 测试不延时STM32F103管脚翻转速度
不延时
HAL_GPIO_TogglePin(LED_GPIO_Port, LED_Pin);
从上图看,红框的高电平时间大约0.88us,这里也可以看出,最高的IO翻转速度大概562kHz
2.4 测试位段方式翻转IO
上述换一个写法,用位段来操作,看看能不能提升IO翻转频率,毕竟有些场景下外设期间的clk频率都要1MHz,甚至更大
PAout(8) = 0;
PAout(8) = 1;
从上图测试结果发现,还是位带操作快啊,红框的时间大概173ns,整个频率可以高达2.8797MHz,这应该是MCU IO翻转的极限了。
2.5 测试Delay_xus函数
采用Delay_xus该函数核心是使用CPU空跑带来延时效果,不推荐,但是在IO翻转要求高速的情况还是要推荐,__NOP();函数加位段操作,来做100us以下的精确延时。
Delay_xus(100);
HAL_GPIO_TogglePin(LED_GPIO_Port, LED_Pin);
这个就不再贴图了,这个再100us以下数据就不准确了。实际使用按需调试。
3 结论
在IO翻转要求高速的情况还是要推荐:位段方式操作IO,使用__NOP()来做100us以下的精确延时,针对ms级别的延时建议采用操作系统延时函数。
本文使用测试工程下载地址:
针对stm32f103MCU的延时方法及函数深入探讨,测试使用工程,具体测试结论参考参考博客内容资源-CSDN下载