哈啰大家好!我是大Z。好久没见,甚是想念。
在刚刚过去的8-9月份,有一个电子信息类专业最大的竞赛--全国大学生电子设计大赛。这个比赛被誉为是全国电子信息类、自动化等类别的最高水平的电子竞技大赛。电赛作为全国电子类竞赛的一哥,也基本上是我们这个专业参赛人数最多,竞争最激烈,含金量最高的比赛了。建议在校的各位学生朋友们,在大学期间尽可能的去参加一次。一是用来检验自己的专业技能水平,二是了解自己的不足和缺陷,从而能够在剩余的大学生涯中,进一步优化自己。
言归正传,今天我们一起来研究一下STM32常用的延时函数。
对于学过51单片机的同学来说,一定都知道延时函数在单片机程序中的重要性。从入门阶段写的流水灯、呼吸灯,到IIC和SPI协议,以及通过时序图写某些模块的驱动程序等。里面都比不可少的要用到各种延时函数。一个延时函数的精确度与否,很可能直接决定了这个代码能否正确驱动对应的传感器或其他电子设备(模块),因此下面的篇幅中,我给大家分享几个较常用的延时函数的写法。
话不多说先贴程序:
/*---------------------------------
函数名:延时调整形式的delaynus函数,
描 述:参数1即为1us,1000即为1ms;
-----------------------------------*/
void delay_nus(unsigned long n)
{
unsigned long j;
while(n--)
{
j=12;
while(j--);
}
}
/*---------------------------------
函数名:延时调整形式的delaynms函数,
描 述:参数1即为1ms,1000即为1s;
-----------------------------------*/
void delay_nms(unsigned long n)
{
while(n--)
delay_nus(1030);
}
这两段程序分别是微秒级别的延时函数(delay_nus)和毫秒级别的延时函数(delay_nms),这两段函数是前人通过调试确定的us或ms单位延时函数。我们只需要拿过来自己用就好了。但是需要注意的是,这种延时函数没有用到STM32的定时计数器或M3内核中的SysTick定时器,因此这两个延时函数相对来说还存在一定的误差,但是对于一般的粗略延时的场合,甚至包括完成时序图,已经足够精确了。因此在一般情况下,这两个延时函数足够应付大部分工作场合。
现在我们通过Keil MDk来对这两个延时函数进行一下调试,看一下它们的精确度分别如何。写一个简单的程序,在程序中加上断点,然后一步步进行调试。调试现象分别如下图所示:
由上图四个断点处的运行时间数据(每幅图的左下方红色方框区域),可以看出,执行delay_nus(1000);这句话总共用时 0.00097052s (由第三断点的0.00101560s减去第二断点的0.00004508s计算得来),即970.5us约为1000us,也就是说us级别的函数,执行1000次,累计误差仅有3%,可以看来delay_nus这个us级别的延时函数还是比较精确的。
接下来执行delay_nms(100);这句话总共用时0.10016604s(由第4断点的0.10118164s减去第3断点的0.00101560s计算得来),即100.1ms约为100ms,也就是说ms级别的延时函数,执行100次的累积误差仅仅是0.1%,已经是非常精确的了。
因此使用这两个函数,足矣应对大部分需要延时的场合了。
然鹅,对于某些小伙伴们来说,非得要精益求精。他们会嫌弃我这个延时函数还是“大老粗”,还想要追求更高更快更强的身体素质更精确的延时函数,那么就只能通过更高级的玩法来实现咯~
对于STM32来说,在它的内核中,有一个非常善良又精确的定时器,它的名字叫做SysTick定时器,用这个定时器,能够实现相对来讲更加精确地延时。在下一讲中,我们会集中精力重点讲一讲这个SysTick定时器究竟该如何使用。
尽情期待下一节:大Z带你重玩STM32系列(十一)------SysTick定时器