本帖最后由 jinglixixi 于 2021-2-18 11:48 编辑
#申请原创#
在常规的例程中,都少不了测试I/O控制作用的点亮LED的程序。而伴随该例程出现的往往少不了延时函数,利用此类延时函数则可以达到相对精准的时基性的延时效果,如毫秒级及微秒级的函数。缺少了此类延时函数,则只能通过定时器来编程解决了。在LPC54114的官方例程中,也有点亮LED的程序,但该例程却没有提供此类的时基性的延时函数。那它是如何来获得延时效果的呢? 其例程的主程序如下: int main(void) { int loop = 1; /* Used to fix the unreachable statementwarning */ SystemCoreClockUpdate(); Board_Init(); Board_IO_Init(); Board_LED_RGB_Off(); /* EnableSysTick Timer */ SysTick_Config(SystemCoreClock/ TICKRATE_HZ); while (loop){ __WFI(); } return 0; } 由此可以推断,它是提供嘀嗒计时器来控制延时效果的。 那嘀嗒计时器又是如何来控制LED的呢? 从下面的中断处理函数即可看出结果: void SysTick_Handler(void) { tick_ct += 1; /* bump tickcount */ if ((tick_ct% 10) == 0) { /* if one second has elapsed (10 ticks) */ tick_ct =0; LED_ct+= 1; /* bumpthe LED count */ Board_LED_RGB_Set(LED_ct& 0x07); /* display the new LED value */ } } 原来它是依靠嘀嗒计时器来产生标准的时基信号,然后再通过程序设计了一个软件计时器来控制延时长短,并以此来切换RGB_LED的显示状态。 在了解了这些之后,我们能否据此来为LPC54114的例程来添加毫秒级及微秒级的延时函数呢? 答案自然是可以的,那又该这样实现呢? 为了便于理解我们先看一下如下的程序: voidSysTick_Handler(void) { tick_ct += 1; if ((tick_ct % M) == 0) { tick_ct = 0; LED_ct += 1; F=(F+1)%2; } } 通过增添延时标识变量F,即可判别延时是否完成,然后在主程序中即可实现延时控制的作用,而修改M的数值即可到达改变延时长短的作用。 while (1) { if(F) LED_R_Set(); else LED_R_Clr(); __WFI(); } 为了符合我们调用延时函数的习惯,可以将其变换为如下的形式: voidSysTick_Handler(void) { tick_ct += 1; if ((tick_ct % M) == 0) { tick_ct = 0; LED_ct += 1; F=1; } }
void delay_ns(uint16_t n) { M=n; F=0; while(!F) { __WFI(); } }
这样我们就可以在主程序中,自由地使用延时函数了。 while (1) { delay_ns(2); LED_R_Set(); delay_ns(2); LED_R_Clr(); }
图1 上电状态(点亮电源指示灯)
图2 嘀嗒计时器控制LED闪烁
图3 延时函数用于RGB_LED控制
以此为基础,若将中断处理函数改为: void SysTick_Handler(void) { tick_ct += 1; if ((tick_ct % TICKRATE) == 0) { tick_ct = 0; LED_ct++; if(LED_ct>=M) { LED_ct=0; F=1; } } } 则可以达到3个等级的延时函数: void delay_ns(uint16_t n) { // 秒级延时 M=n; TICKRATE=1000000; TICKRATE_HZ=1000000; F=0; while(!F) { __WFI(); }
}
void delay_nms(uint16_t n) { // 毫秒级延时 M=n; TICKRATE=1000;s TICKRATE_HZ=1000000; F=0; while(!F) { __WFI(); } }
void delay_nus(uint32_t n) { // 微秒级延时 M=n; TICKRATE=1; TICKRATE_HZ=1000000; F=0; while(!F) { __WFI(); } } 有了这些延时函数后,除了解决延时问题,我们还能做些什么呢? 在数字式的传感器驱动中,对顺序的要求比较高,因此就需要有比较基准的延时函数来配合,如单总线的DS18B20、DHT11/DHT22等,以及I2C和SPI接口的外设也需要延时函数的配合来驱动,故延时函数的作用还是非常重要的。 例如在驱动OLED屏的辅助函数中,是通过调用延时函数来保持信号作用时间的。 void IIC_Start() { OLED_SCLK_Set(); delay_nus(2); OLED_SDIN_Set(); delay_nus(2); OLED_SDIN_Clr(); delay_nus(2); OLED_SCLK_Clr(); delay_nus(2); }图4 延时函数用于OLED屏显示
此外,该延时函数还适用于LPC54110等开发板。当然,也可将它移植到具有嘀嗒计时器又缺少基准延时函数的地方。
|