4. 延时
延时功能在计算机编程中十分常见,它可以暂停程序的执行一段时间,以实现各种应用需求。
4.1 延时的作用
在Arduino或其他微控制器的编程中,延时被广泛使用,主要有以下一些原因:
处理硬件
许多硬件都需要一些时间来响应某个命令。例如,如果在一个程序中你启动一个电动机然后立即检查其状态,你可能会得到一个错误的读数,因为电动机可能还没有足够的时间开始旋转。此时你需要使用 delay() 函数让系统等待一段时间,使得电动机有足够的时间响应。
用户交互
我们常常需要在用户交互中实现延迟效果。例如,在蜂鸣器播放音乐时,音符之间需要一段沉默的时间。或者,在闪烁LED灯的情况下,"开"和"关"状态之间需要延时以控制闪烁的速度。
节省能源
在一些应用中,比如电池供电的系统,如果不在需要的时候长期保持系统的高速运转,那么电池的寿命会大大缩短。在此情况下,我们可以让系统在一段时间后进入待机或低功耗模式,直到下一个处理周期到来。
定时操作
在许多项目中,我们常常需要实现一些特定时间点的操作。例如,在自动灌溉系统中,我们可能需要在每天的特定时间点进行灌溉。在间隔测量中,我们可能每隔一段时间采集一次数据。
尽管延时函数在很多情况下非常有用,但也需要注意其阻塞性质。过度依赖阻塞延时可能会导致程序对其他事件的响应不及时。为了更好的在Arduino上进行多任务编程,我们还可以学习一些非阻塞延时的编程技术。
❓什么是阻塞延时?
阻塞延时是在程序执行过程中,当某个操作或函数需要一定时间才能完成时,程序会暂停执行直至该操作完成,这段时间程序被阻塞了。阻塞延时可能会导致程序运行速度变慢或出现假死现象。 举个例子,假设你想要煮开水来泡茶。通常情况下,你会将水壶放在炉灶上加热,等待水烧开后才能使用。在这个过程中,存在阻塞延时。 当你将水壶放在炉灶上加热时,程序可以看作是“等待”水烧开的操作。在这个等待过程中,你不能立即得到热水来泡茶,需要耐心等待水煮沸。期间,你无法做其他与烧水无关的事情,因为你需要留意水壶,并等待时机。即便家里着火了,你也还是在等待烧水。
4.2 延时的实现
在 Arduino 中,延时操作可以通过使用 delay()
函数实现。delay()
函数只接收一个参数,表示要延迟的毫秒数。这个函数会阻塞代码执行,导致程序在指定的时间内暂停,然后继续执行。
例如,要在 Arduino 中实现 1 秒的延时,可以编写以下代码:
delay(1000); // 延时1000毫秒,等于1秒
注意,由于 delay()
函数是阻塞性的,程序在等待延时期间无法执行其他任务。对于需要同时处理多个任务或使用非阻塞延时的程序,可以使用 millis()
函数来获取自程序启动以来的毫秒数并进行计时。
以下是一个使用 millis()
实现非阻塞延时的示例:
const int ledPin = 48; //定义LED引脚
unsigned long previousMillis = 0;//定义一个变量,记录时间
unsigned long interval = 1000; // 延时1000毫秒,等于1秒
bool ledState = LOW;//定义LED状态为低电平
//只执行一次
void setup()
{
//设置 ledPin 引脚为 输出模式(OUTPUT)
pinMode(ledPin, OUTPUT);
}
//循环执行
void loop()
{
//定义一个变量用于存储 millis() 函数返回的值
unsigned long currentMillis = millis();
//如果当前运行的时间 减去 之前运行的时间 大于 1000毫秒
//说明已经过去了1000ms的时间
if (currentMillis - previousMillis >= interval)
{
//更新之前的时间为当前时间,方便下次计算
previousMillis = currentMillis;
// 切换 LED 的状态
ledState = !ledState;
digitalWrite(ledPin, ledState);
}
// 此处之后可以执行其他任务,而无需等待延时
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
在此示例中,使用了 millis()
函数和一个变量 previousMillis
来跟踪时间,从而实现延时操作。这种方法可以更有效地处理多任务,而不受延时阻塞的影响。
4.3 闪烁灯验证
将开发板连接LED的GPIO48引脚设置为输出模式,通过延时函数delay()
,控制LED亮一会灭一会,达到闪烁的效果。
void setup()
{
// 设置 GPIO48 Pin 为输出模式
pinMode(48,OUTPUT);
// 设置48引脚 输出低电平
digitalWrite(48,LOW);
}
void loop()
{
// 设置48引脚 输出低电平
digitalWrite(48,LOW);
//延时100ms
delay(100);
// 设置48引脚 输出高电平
digitalWrite(48,HIGH);
//延时100ms
delay(100);
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
4.4 闪烁灯效果
开发板上标记着G48的LED灯,下载代码后将一会亮一会灭,持续循环。