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


    前言

    今天,我们将学习中断和定时器的相关概念,并且基于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);
    
    • 1

    GPIO中断引脚

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

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

    digitalPinToInterrupt(14)
    
    • 1

    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;
      }
    }
    
    • 1
    • 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
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43

    结论

    本文简单介绍了ESP8266的中断和相关概念,通过实现运动红外传感器的检测来实验中断的功能。

  • 相关阅读:
    金字塔型自动化的利弊
    std::minus
    【PDF合并】利用 Python 合并 PDF 文件
    JS逆向实战23——某市wss URL加密+请求头+ws收发
    base64编码的原理
    数据分析(1)——如何用postgres快速找出数据库中所有表格包含空值的列
    SpringBoot 配置进阶
    Mybatis-Plus介绍
    Google Colab
    Golang实现一个批量自动化执行树莓派指令的软件(2)指令
  • 原文地址:https://blog.csdn.net/u010632165/article/details/134315026