techiall / Blog

🍋 [My Blog] See discussions
https://github.com/techiall/Blog/discussions
MIT License
8 stars 1 forks source link

Arduino | 关于中断 #31

Open techiall opened 5 years ago

techiall commented 5 years ago

终于把 arduino 中断的坑给填了。

中断分类

中断 描述
外部中断 外部设备导致的中断请求(如板子上的 reset 按钮
内部中断 程序中设置的中断指令
异常中断 程序或硬件出现异常或故障

外部中断

attachInterrupt() 函数

触发中断。attachInterrupt(interrupt, ISR, mode)

参数
注意事项

digitalPinToInterrupt() 函数

将 引脚 转换成 中断信号。 digitalPinToInterrupt(pin)

参数
BOARD INT.0 INT.1 INT.2 INT.3 INT.4 INT.5
Uno, Ethernet 2 3
Mega2560 2 3 21 20 19 18
32u4 based (e.g Leonardo, Micro) 3 2 0 1 7

外部中断官方样例

关于 attachInterrupt() 和 digitalPinToInterrupt() 函数,官方给的参考代码。

const byte ledPin = 13;
const byte interruptPin = 2;
volatile byte state = LOW;

void setup() {
  pinMode(ledPin, OUTPUT);
  pinMode(interruptPin, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(interruptPin), blink, CHANGE);
}

void loop() {
  digitalWrite(ledPin, state);
}

void blink() {
  state = !state;
}

说实话,这代码,我对于整段代码运行的前后顺序还是有点迷的。

因此下面将给出我自己的测试代码。

测试代码

在官方代码的基础上修改,利用串口调试,将方便我们观察效果。

并将 interruptPin 引脚状态设置为 INPUT

利用一根杜邦线,一边接在程序设置好的 interruptPin 接口上,另一边接在 GND 引脚上。

#include <SoftwareSerial.h>

const byte ledPin = 13;
const byte interruptPin = 2;
volatile byte state = LOW;

void serial_init()
{
    Serial.begin(115200);
    while (!Serial) {}
}

void setup()
{
    serial_init();
    Serial.println("setup function begin");
    pinMode(ledPin, OUTPUT);
    pinMode(interruptPin, INPUT_PULLUP);    
    attachInterrupt(digitalPinToInterrupt(interruptPin), blink, CHANGE);
    Serial.println("setup function end");
}

void loop()
{
    Serial.println("loop start");
    digitalWrite(ledPin, state);
    Serial.println("loop end");
}

void blink()
{
    Serial.println("blink function start");
    state = !state;
    Serial.println("blink function end");
}

运行结果

setup function begin
setup function end
loop start
loop end
loop start
loop end
...
loop start
loop end
loop start
loop endloop start
loop end
loop start
loop end
loop start
loop end
loop start
blink function start
blink function end
blink function start
blink function end
blink function start
blink function end
bliloop end
loop start
loop end
loop start
loop end
...
loop start
loop end
loop start
loop end
loop stblink function start
blink function end
blink function start
blink function end
blink function start
blink function end
blirt
loop end
loop start
loop end
loop start
loop end
loop start
loop end
...
loop start
loop end
looblink function start
blink function end
blink function start
blink function end
blink function start
blink function end
bli start
loop end
loop start
loop end
loop start
loop end
loop start
loop end

结果分析

内部中断

FlexiTimer2 为例。

测试代码

#include "FlexiTimer2.h"

void Flash() 
{
    digitalWrite(13, digitalRead(13) ^ 1);
}

void setup() 
{
    pinMode(13, OUTPUT);

    FlexiTimer2::set(1000, 1.0 / 1000, Flash); 
    FlexiTimer2::start();
}

void loop() 
{
}

实验现象

LED13 灯亮一秒,熄灭一秒。依次反复。

扩展

内部中断可以作为定时器使用。也就是隔一段设定好的时间执行某段程序。

利用该特性,我们可以定时发送数据来保持与服务器的通讯。如心跳包。

参考链接

测试代码

该文章的测试代码。test.zip