今天,我们将学习中断和定时器的相关概念,并且基于NodeMCU ESP8266 12E开发板搭建硬件电路,通过使用中断和定时器实现我们想要实现的功能。
中断在嵌入式开发中是很常见的功能,特别是在单片机的开发中。通常GPIO
引脚可以接收外部的信号,根据不同的信号类型,可以触发中断,进入中断服务函数。
那什么是中断?整个流程又是怎么样的?下面做个形象的类比。
loop
里的程序);1 看书
2 电话响起
3 响应中断,去接电话
通过中断,我们不需要一直去检查当前的引脚状态,这种定时去检查引脚状态的机制一般叫做轮询;
相比较于中断,轮询的响应会慢很多,并且占用CPU资源;
当检测到变化时,就会触发一个事件——调用一个函数。该函数称为中断服务程序(ISR
);
当中断发生时,处理器停止主程序的执行以执行任务,然后回到主程序,如下图所示。
要在 Arduino IDE 中设置中断,我们可以使用attachInterrupt()
函数,接受以下参数作为参数:GPIO 中断引脚、要执行的函数的名称和模式:
attachInterrupt(digitalPinToInterrupt(GPIO), ISR, mode);
第一个参数是 GPIO 中断。你应该使用digitalPinToInterrupt(GPIO)
函数 将实际 GPIO 设置为中断引脚。
例如,如果我们想使用 GPIO 14 作为中断,请使用:
digitalPinToInterrupt(14)
ESP8266 支持除 GPIO16 之外的任何 GPIO 中断。
该的第二个函数参数是 attachInterrupt()
是每次触发中断时将调用的函数的名称——中断服务例程(ISR)。
ISR 函数应该尽可能简单,以便处理器快速返回主程序的执行。
最好的方法是通过使用全局变量并在loop()
检查并清除该标志,然后执行代码。
ISR 需要具备ICACHE_RAM_ATTR在函数定义之前运行 RAM 中的中断代码。
第三个参数是模式,有 3 种不同的模式:
对于我们的示例,将使用 RISING 模式,因为当 PIR 运动传感器检测到运动时,它所连接的 GPIO 从低电平变为高电平。
这里我们需要搭建一个硬件实验电路,将运动传感器和 LED集成到面包板上。
我们将 LED 连接到通用输入输出口12(D6)和 运动传感器数据引脚通用输入输出口14(D5)。
具体如下所示;
按照原理图连接电路后,将提供的代码复制到 Arduino IDE。
您可以按原样上传代码,也可以修改检测到运动后 LED 点亮的秒数。只需更改timeSeconds
变量与我们想要的秒数。
#define timeSeconds 10
// Set GPIOs for LED and PIR Motion Sensor
const int led = 12;
const int motionSensor = 14;
// Timer: Auxiliary variables
unsigned long now = millis();
unsigned long lastTrigger = 0;
boolean startTimer = false;
// Checks if motion was detected, sets LED HIGH and starts a timer
ICACHE_RAM_ATTR void detectsMovement() {
Serial.println("MOTION DETECTED!!!");
digitalWrite(led, HIGH);
startTimer = true;
lastTrigger = millis();
}
void setup() {
// Serial port for debugging purposes
Serial.begin(115200);
// PIR Motion Sensor mode INPUT_PULLUP
pinMode(motionSensor, INPUT_PULLUP);
// Set motionSensor pin as interrupt, assign interrupt function and set RISING mode
attachInterrupt(digitalPinToInterrupt(motionSensor), detectsMovement, RISING);
// Set LED to LOW
pinMode(led, OUTPUT);
digitalWrite(led, LOW);
}
void loop() {
// Current time
now = millis();
// Turn off the LED after the number of seconds defined in the timeSeconds variable
if(startTimer && (now - lastTrigger > (timeSeconds*1000))) {
Serial.println("Motion stopped...");
digitalWrite(led, LOW);
startTimer = false;
}
}
本文简单介绍了ESP8266
的中断和相关概念,通过实现运动红外传感器的检测来实验中断的功能。