在 Arduino 编程中,delay()
函数是一个常见的工具,用于创建代码执行的延时。然而,delay()
函数的一个显著缺点是它会阻塞代码的执行。这意味着当 delay()
函数运行时,Arduino 将暂停其他所有的操作,直到延时结束。这种阻塞行为在某些简单的项目中可能是可接受的,但在需要同时运行多个任务的复杂项目中,这种方式会带来严重的问题。
例如,在一个需要同时读取传感器数据、控制输出设备和处理用户输入的项目中,使用 delay()
函数会导致其他任务无法按时执行,影响整个系统的响应能力和效率。为了解决这个问题,我们可以使用 millis()
函数来实现非阻塞延时。
millis()
函数返回自 Arduino 开机以来经过的毫秒数。这使得我们可以通过记录特定时刻的时间戳,并在后续的代码中检查是否已经经过了预定的时间,从而实现非阻塞延时。这种方法的核心思想是持续检查当前时间与记录的时间之间的差值,而不是暂停代码执行。
实现非阻塞延时的步骤
- 记录初始时间:在执行延时操作之前,使用
millis()
函数记录当前时间。 - 检查时间差:在循环中持续检查当前时间与初始时间的差值,判断是否已经经过了预定的延时时间。
- 继续其他任务:在等待时间达到的过程中,允许代码继续执行其他任务。
以下是一个简单的例子,演示如何使用 millis()
函数实现非阻塞延时:
unsigned long previousMillis = 0; // 记录上一次更新的时间
const long interval = 1000; // 延时间隔(毫秒)void setup() {Serial.begin(9600);
}void loop() {unsigned long currentMillis = millis(); // 获取当前时间// 检查是否已经到达预定时间间隔if (currentMillis - previousMillis >= interval) {previousMillis = currentMillis; // 更新记录的时间// 执行需要延时的操作Serial.println("1秒已过");}// 执行其他任务// 例如,读取传感器数据或处理用户输入int sensorValue = analogRead(A0);Serial.println(sensorValue);
}
在这个例子中,程序每隔1秒钟执行一次特定的任务,同时在等待时间到达的过程中继续执行其他任务,如读取传感器数据。通过这种方式,我们避免了 delay()
函数带来的阻塞问题。
优势
使用 millis()
函数实现非阻塞延时有以下几个主要优势:
- 提高响应能力:代码可以在等待时间到达的过程中继续运行其他任务,提高了系统的响应速度。
- 多任务处理:允许多个任务并行运行,而不是因为一个延时操作而暂停整个系统。
- 更灵活的时间管理:可以轻松实现不同任务的不同延时要求,而不需要嵌套多个
delay()
调用。
应用场景
在实际应用中,非阻塞延时的使用场景非常广泛。典型的应用包括:
- 实时数据采集:在传感器数据采集中,定期读取数据而不影响其他处理逻辑。
- LED 控制:在 LED 闪烁或其他定时控制中,同时处理按钮输入和状态显示。
- 机器人控制:在机器人项目中,处理多个传感器输入和执行动作,而不会因为单一的延时操作而影响整体协调。
总之,使用 millis()
函数来实现非阻塞延时是提升 Arduino 项目效率和响应能力的有效方法。通过理解和应用这种技术,开发者可以设计出更为复杂和功能强大的嵌入式系统。