NodeMCU ESP8266 中断介绍以及使用详解

发布时间:2023年12月18日

前言

今天,我们将学习中断和定时器的相关概念,并且基于NodeMCU ESP8266 12E开发板搭建硬件电路,通过使用中断和定时器实现我们想要实现的功能。

中断介绍

中断在嵌入式开发中是很常见的功能,特别是在单片机的开发中。通常GPIO引脚可以接收外部的信号,根据不同的信号类型,可以触发中断,进入中断服务函数。

那什么是中断?整个流程又是怎么样的?下面做个形象的类比。

  • 上学两年半的学生正在看书;(程序执行主任务,arduino中可以认为在执行loop里的程序);
  • 电话忽然响起;(GPIO上有信号,触发了中断)
  • 上学两年半的学习放下手里的书,跑去接电话;(响应中断,执行中断服务函数)

1 看书
Alt text


2 电话响起
Alt text


3 响应中断,去接电话
Alt text

通过中断,我们不需要一直去检查当前的引脚状态,这种定时去检查引脚状态的机制一般叫做轮询

相比较于中断,轮询的响应会慢很多,并且占用CPU资源;

当检测到变化时,就会触发一个事件——调用一个函数。该函数称为中断服务程序(ISR);

当中断发生时,处理器停止主程序的执行以执行任务,然后回到主程序,如下图所示。

如何使用

AttachInterrupt() 函数

要在 Arduino IDE 中设置中断,我们可以使用attachInterrupt()函数,接受以下参数作为参数:GPIO 中断引脚、要执行的函数的名称和模式:

attachInterrupt(digitalPinToInterrupt(GPIO), ISR, mode);

GPIO中断引脚

第一个参数是 GPIO 中断。你应该使用digitalPinToInterrupt(GPIO)函数 将实际 GPIO 设置为中断引脚。

例如,如果我们想使用 GPIO 14 作为中断,请使用:

digitalPinToInterrupt(14)

ESP8266 支持除 GPIO16 之外的任何 GPIO 中断。

中断服务函数 ISR

该的第二个函数参数是 attachInterrupt() 是每次触发中断时将调用的函数的名称——中断服务例程(ISR)。

ISR 函数应该尽可能简单,以便处理器快速返回主程序的执行。

最好的方法是通过使用全局变量并在loop()检查并清除该标志,然后执行代码。

ISR 需要具备ICACHE_RAM_ATTR在函数定义之前运行 RAM 中的中断代码。

中断触发类型

第三个参数是模式,有 3 种不同的模式:

  • CHANGE:每当引脚改变值时触发中断 - 例如从高到低或从低到高;
  • FALLING:当引脚从高电平变为低电平时;
  • RISING:当引脚从低电平变为高电平时触发。

对于我们的示例,将使用 RISING 模式,因为当 PIR 运动传感器检测到运动时,它所连接的 GPIO 从低电平变为高电平。

硬件电路

这里我们需要搭建一个硬件实验电路,将运动传感器和 LED集成到面包板上。

我们将 LED 连接到通用输入输出口12(D6)和 运动传感器数据引脚通用输入输出口14(D5)。

具体如下所示;

ESP8266 NodeMCU Interrupts and Timers with PIR Motion Sensor Schematic Circuit Diagram

示例代码

按照原理图连接电路后,将提供的代码复制到 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的中断和相关概念,通过实现运动红外传感器的检测来实验中断的功能。

文章来源:https://blog.csdn.net/u010632165/article/details/134315026
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。