单片机延时函数是嵌入式系统中常用的一种功能,用于控制程序执行的时间间隔。延时函数的实现方法有很多种,包括软件延时和硬件延时。下面详细介绍几种常见的延时函数实现方法,并揭示一些精准延时的技巧。
最简单的延时方法是通过空循环实现。这种方法简单但不够精确,因为延时的长度会受到单片机执行其他任务的影响。
void delay_ms(uint16_t ms) {
uint16_t i, j;
for (i = 0; i < ms; i++) {
for (j = 0; j < 123; j++) {
__NOP(); // 插入空操作
}
}
}
查表延时是通过预先计算好延时时间的表格来实现延时,这种方法比空循环延时更精确。
uint16_t delay_table[1000];
void init_delay_table() {
for (uint16_t i = 0; i < 1000; i++) {
delay_table[i] = i * 123; // 预先计算延时值
}
}
void delay_ms(uint16_t ms) {
if (ms < 1000) {
while (__get与时计数器() - delay_table[ms] > 0);
}
}
定时器是实现精准延时的常用方法。大多数单片机都内置了定时器,可以通过设置定时器的重载值来实现延时。
void delay_ms(uint16_t ms) {
TIM_SetCounter(0); // 将定时器计数器清零
TIM_SetPeriod(ms * TIM_GetClockFrequency() / 1000 - 1); // 设置定时器重载值
while (!TIM_GetFlagStatus(TIM_FLAG_UPDATE)); // 等待定时器溢出
TIM_ClearFlag(TIM_FLAG_UPDATE); // 清除定时器溢出标志
}
在执行延时函数时关闭中断可以减少其他任务对延时精度的影响。
void delay_ms(uint16_t ms) {
__disable_irq(); // 关闭中断
TIM_SetCounter(0); // 将定时器计数器清零
TIM_SetPeriod(ms * TIM_GetClockFrequency() / 1000 - 1); // 设置定时器重载值
while (!TIM_GetFlagStatus(TIM_FLAG_UPDATE)); // 等待定时器溢出
TIM_ClearFlag(TIM_FLAG_UPDATE); // 清除定时器溢出标志
__enable_irq(); // 开启中断
}
一些单片机支持高精度定时器,可以选择更高频率的时钟源来提高延时的精度。
在延时函数中执行复杂的操作会降低延时的精度,尽量保持延时函数的简单性。