前言
延迟函数是一项常用的编程技术,用于控制程序的执行速度和时间间隔。通过合理使用延迟函数,可以使程序在需要的时候暂停一段时间,从而实现更加灵活和精确的控制。然而,在使用延迟函数时需要注意合理选择延迟时间,并避免可能存在的问题。
一、为什么用delay来延时?
1. 实现简单
delay函数的实现相对直接,通常基于循环计数器或者定时器中断来完成。例如,在STM32系列微控制器上,可以通过配置SysTick定时器来创建精确的毫秒级延时。这种方式不需要引入额外的库或依赖项,降低了系统的复杂度。
2. 不阻塞线程(适用于协程)
当提到delay时,特别是在现代编程语言如Kotlin中,delay是一个非阻塞的挂起函数,这意味着它可以暂停当前协程的执行而不阻塞整个线程。这使得应用程序能够更高效地利用系统资源,特别是在并发任务处理方面。然而,需要注意的是,这里的delay特指协程环境下的异步延迟,而不仅仅是简单的忙等待循环。
3. 精确度与灵活性
通过调整参数值,delay函数可以提供从微秒到分钟甚至更长时间的不同级别的延时精度。对于某些应用场景来说,比如需要精确控制灯光闪烁频率或是传感器采样周期的情况,这一点尤为重要。
4. 内存占用低
相比于使用操作系统提供的睡眠功能(如Linux中的sleep),delay函数往往占用较少的内存空间,因为它们不涉及复杂的上下文切换机制。这对于资源受限的嵌入式平台而言是一个显著的优势。
5. 适应性强
尽管delay函数本身是非阻塞的(在协程环境中),但在传统的单线程环境下,如果确实需要一个简单的阻塞式延时,那么也可以很容易地实现。例如,在裸机编程中,可以直接编写一个忙等待循环来达到目的。不过,这种方**持续消耗CPU周期直到延时期满,因此并不总是最优的选择。
6. 缺点:影响实时性能
虽然delay函数易于使用且效率较高,但它可能会对系统的实时响应能力产生负面影响。特别是在多任务系统中,长时间的延时可能导致其他任务得不到及时处理,从而引发优先级倒置等问题。此外,如果使用不当,还可能造成电源管理方面的挑战,比如无法进入低功耗模式。
二、使用步骤
1.delay.c
代码如下(示例):
#include "stm32f10x.h" // 包含STM32F1系列的标准库头文件
#include "delay.h"
// 定义用于微秒级延时的函数,使用NOP指令实现短时间延迟
void Delay_usnop(uint32_t time) // 更改类型为uint32_t以符合标准
{
for (volatile uint32_t i = 0; i < time * 72; ++i) // 每个循环大约等于1微秒
{
__NOP(); // 使用单个NOP指令代替多个NOP指令
}
}
// 实现微秒级延时,通过调用Delay_usnop()函数完成
void Delay_us(uint32_t time) // 改为uint32_t,避免过大数值溢出
{
while (time--) // 对于每个需要延时的微秒调用一次Delay_usnop()
{
Delay_usnop(1); // 每次调用大约等于1微秒
}
}
// 实现毫秒级延时,通过软件循环等待完成
void Delay_ms(uint32_t time)
{
uint32_t start = SysTick->VAL;
while ((SysTick->VAL - start) <= (SystemCoreClock / 1000 * time)) {}
}
// 初始化SysTick定时器,配置为每1ms触发一次中断
void Delay_Init(void)
{
if (SysTick_Config(SystemCoreClock / 1000)) // 根据系统核心时钟频率计算正确的重装载值
{
while (1); // 如果SysTick配置失败,则在此处等待
}
}
// 全局变量用于跟踪不同事件的时间计数
volatile uint32_t timeled[2] = { 0, 2000 }; // LED控制的时间间隔
volatile uint32_t timekey[2] = { 0, 10 }; // 按键扫描的时间间隔
volatile uint32_t timedc[2] = { 0, 10 }; // 直流电机控制的时间间隔
volatile uint32_t timedi[2] = { 0, 2000 }; // 数字输入检测的时间间隔
// SysTick定时器的中断服务例程(ISR),每1ms被调用一次
void SysTick_Handler(void)
{
timeled[0]++; // 每隔1ms增加一次
timekey[0]++;
timedc[0]++;
timedi[0]++;
}
2.delay.h
代码如下(示例):
#ifndef DELAY_H_
#define DELAY_H_
#include "stm32f10x.h" // 包含STM32F1系列的标准库头文件
// 宏定义
#define NOP() __NOP() // 定义一个宏来简化NOP指令的调用 [ty-reference](26)
// 延时函数声明
/**
* @brief 实现微秒级延时,通过调用Delay_usnop()函数完成。
* @param time 要延时的时间,单位为微秒。
*/
void Delay_us(uint32_t time);
/**
* @brief 使用NOP指令实现短时间延迟,每个循环大约等于1微秒。
* @param time 循环次数,通常与微秒数成正比。
*/
void Delay_usnop(uint32_t time);
/**
* @brief 实现毫秒级延时,通过软件循环等待完成。
* @param time 要延时的时间,单位为毫秒。
*/
void Delay_ms(uint32_t time);
/**
* @brief 初始化SysTick定时器,配置为每1ms触发一次中断。
*/
void Delay_Init(void);
// 全局变量声明
extern volatile uint32_t timeled[2]; // LED控制的时间间隔
extern volatile uint32_t timekey[2]; // 按键扫描的时间间隔
extern volatile uint32_t timedc[2]; // 直流电机控制的时间间隔
extern volatile uint32_t timedi[2]; // 数字输入检测的时间间隔
#endif /* DELAY_H_ */
当您在不同的.c文件中需要使用上述延时函数时,只需简单地添加如下行即可:
#include "delay.h"
这样做的好处是,所有的延时相关功能都被集中管理在一个单独的头文件中,便于未来的修改和扩展。此外,这种方法也遵循了C语言中“分离编译”的原则,即每个源文件只关心自己的实现细节,而公共接口则由头文件提供。
总结
delay函数是一种在编程中常见的函数,用于暂停程序的执行一段时间。它通常用于制造一个时间延迟,使程序可以按照特定的时间间隔执行。
delay函数是一种常见的用于延迟程序执行的函数。它可以用于控制程序的执行速度、行为和流程。然而,在使用delay函数时需要注意程序的实时性要求,避免影响程序的响应和性能。
————————————————
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/m0_63037616/article/details/144836352
|