NodeMCU ESP8266中断的介绍与详细使用说明

文章目录

  • 前言
  • 中断介绍
  • 如何使用
  • AttachInterrupt() 函数
  • GPIO中断引脚
  • 中断服务函数 ISR
  • 中断触发类型
  • 硬件电路
  • 示例代码
  • 结论
  • 前言

    今天,我们将学习中断和定时器的相关概念,并且基于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的中断和相关概念,通过实现运动红外传感器的检测来实验中断的功能。

    物联沃分享整理
    物联沃-IOTWORD物联网 » NodeMCU ESP8266中断的介绍与详细使用说明

    发表评论