ARM精密延时子程序设计
时间:10-02
整理:3721RD
点击:
大家好!今天分享一个有趣儿的实用程序。
我的MCU的时钟频率是12MHz,时钟周期是1/12=0.083333us。
这种12MHz时钟情况下,要实现一个1us为单位的延时子程序,又要求比较准确,不是一件容易事儿。 您如果是使用几十~100MHz以上的高速MCU,就不要往下看了。
首先测试了for循环,不成功,最小时延1.8us,做不到1us,而且2,3,4,5us的误差都比较大。
后用inline __asm volatile ("nop")测试,可以实现,重复一次加多50ns。
最后,搞成了这个样子:
__attribute__( ( always_inline ) ) __STATIC_INLINE void __NOP(void)
{
__asm volatile ("nop");
}
//-----uS delay ( >=1us)---------------
void vDelayUS(uint32_t u32DelayUS)
{
volatile uint32_t i;
if (u32DelayUS <= 15)
{
switch(u32DelayUS)
{
case 1:
__NOP();
__NOP();
__NOP();
return;
case 2:
i = 3;
__NOP();
break;
case 3:
i = 6;
__NOP();
__NOP();
__NOP();
break;
case 4:
i = 10;
__NOP();
__NOP();
break;
default:
i = (u32DelayUS - 2) << 2;
i++;
i++;
}
loop: if (--i > 0) goto loop;
return;
}
// >=16us
u32DelayUS = (13260 * u32DelayUS) >> 12;
for (i = 0; i < u32DelayUS; i++) {}
}
注意,
1. ARM编译器的优化处理会对定时产生极大的影响,使用时必须用示波器测试调整。
2. 微秒级别的延时,运行时不允许有中断事件发生,要关闭所有中断。
3. 上面这个程序,适合1000uS以下使用。mS延时程序,有太多选择了。
4. 调整测试,1,2,3,4,5,15,16us, 1000us都需要单独调整,或者兼顾调整。
下面这个是测试用的,也可以单独使用:
//-----delay 1us-----------------------
void vDelay1us(void)
{
volatile uint32_t i=0;
__NOP();
__NOP();
__NOP();
__NOP();
__NOP();
__NOP();
}
请大家多提宝贵意见。
简单了解一下 毕竟不会
顶一个~~~~~~~~~~~~~~