Arduino-外部中断函数介绍和使用

Arduino-外部中断函数介绍和使用

Arduino-外部中断函数介绍和使用

📖外部中断函数

attachInterrupt():设置中断,根据不同的开发板,中断引脚不同。

📍参考:https://www.arduino.cc/reference/en/language/functions/external-interrupts/attachinterrupt/

🌿对于328P单片机处理INT0和IT1外部中断引脚外,还支持端口引脚(电平变化)中断,分别对应中断向量表中的:PCINT0,PCINT1,PCINT2,PCINT3,几乎所有的引脚都支持这种电平变化中断,不过它们都共用这4个中断源。

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

detachInterrupt():取消指定引脚的中断interrupts():开中断noInterrupts():关中断

📝注意事项

在中断服务函数中,delay()不起作用,而millis()返回的值也不会递增。在函数中接收的串行数据可能会丢失。在中断服务函数中修改的任何变量都应该声明为volatile。如果想在中断服务函数中使用延时,delayMicroseconds()可以使用这个来延时。

中断函数语法、

attachInterrupt(digitalPinToInterrupt(pin), ISR, mode)

digitalPinToInterrupt(pin):中断引脚 ISR中断发生时调用的ISR;这个函数不能接受任何参数,也不能返回任何内容。这个函数有时被称为中断服务程序。 mode:中断模式(4种)

CHANGE:当引脚改变值时触发中断-例如从HIGH到LOW或LOW到HIGH;FALLING:当触发信号从高电平到低电平是触发;RISING:当引脚从低电平到高电平时触发。LOW: 当引脚为低电平时触发中断服务程序

🔖AVR单片机中断控制:

📑Arduino UNO开启外部2号引脚触发中断 (Arduino UNO中断引脚有2个,2和3)

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;

}

📝detachInterrupt(digitalPinToInterrupt(pin)):取消指定类型的中断.

interrupts()函数原型:#define interrupts() sei()

void setup() {}

void loop()

{

noInterrupts();

// critical, time-sensitive code here

interrupts();

// other code here

}

noInterrupts()函数原型:#define noInterrupts() cli()

void setup() {}

void loop()

{

noInterrupts();

// critical, time-sensitive code here

interrupts();

// other code here

}

📘寄存器配置外部中断示例

配置外部中断0(PD2)2号引脚作为外部中断引脚

volatile bool ext_int0_flag = 0;

void ext_int0_init(void)

{

// External Interrupt(s) initialization

// INT0: On

// INT0 Mode: Any change

// INT1: Off

EICRA=(0<

EIMSK=(0<

EIFR=(0<

PCICR=(0<

}

// the setup function runs once when you press reset or power the board

void setup() {

// initialize digital pin LED_BUILTIN as an output.

pinMode(LED_BUILTIN, OUTPUT);

Serial.begin(115200);

ext_int0_init();

}

ISR(INT0_vect)

{

ext_int0_flag = 1;

}

// the loop function runs over and over again forever

void loop() {

if (ext_int0_flag)

{

ext_int0_flag = 0;

PORTB ^= (1 << PINB5);//板载led 闪烁一次

Serial.println("ext int0 Trg!\r\n");

}

}

如果需要开启外部中断0和1:

volatile bool ext_int0_flag = 0;

volatile bool ext_int1_flag = 0;

void ext_int0_init(void)

{

// External Interrupt(s) initialization

// INT0: On

// INT0 Mode: Any change

// INT1: Off

EICRA=(0<

EIMSK=(1<

EIFR=(1<

PCICR=(0<

}

// the setup function runs once when you press reset or power the board

void setup() {

// initialize digital pin LED_BUILTIN as an output.

pinMode(LED_BUILTIN, OUTPUT);

Serial.begin(115200);

ext_int0_init();

}

//外部中断0

ISR(INT0_vect)

{

ext_int0_flag = 1;

}

//外部中断1

ISR(INT1_vect)

{

ext_int1_flag = 1;

}

// the loop function runs over and over again forever

void loop() {

// digitalWrite(LED_BUILTIN, HIGH); // turn the LED on (HIGH is the voltage level)

// delay(1000); // wait for a second

// digitalWrite(LED_BUILTIN, LOW); // turn the LED off by making the voltage LOW

// delay(1000); // wait for a second

// Serial.println("Hello World2");

if (ext_int0_flag)

{

ext_int0_flag = 0;

PORTB ^= (1 << PINB5);//1秒钟闪烁一次

Serial.println("ext int0 Trg!\r\n");

}

if (ext_int1_flag)

{

ext_int1_flag = 0;

PORTB ^= (1 << PINB5);//1秒钟闪烁一次

Serial.println("ext int1 Trg!\r\n");

}

}

🥕对于Atmega328P、ATmega8等AVR带比较器外设的,可以利用比较器扩展外部中断

📍资料参考来运:https://www.geek-workshop.com/thread-11507-1-1.html📝测试代码:

/*

328p通过内部比较器扩展外部中断

对应的引脚是arduino 的PIN D6 ,D7 .

AIN0 -> PD6 (正反馈输入引脚)

AIN1 -> PD7 (负反馈输入引脚)

比较器大家都比较熟悉,常用的比较器型号像LM393分正反馈与负反馈,

328P片上集成的也是一样有正负反馈. D6是正反馈,D7是负反馈.

D6正反馈可以通过寄存器操作与能隙基准源连接,D6引脚

中断号:ISR(ANALOG_COMP_vect) 24

*/

#include

int pin = 13;

volatile int state = LOW;

QUN M; //你要做的只是添加上这个

void setup()

{

pinMode(pin, OUTPUT);

M.attachInterrupt(blink, M_CHANGE); //格式是:M.attachInterrupt(blink, M_CHANGE);

//blink是要执行的函数,

// M_CHANGE 当引脚电平发生改变时,触发中断

// M_RISING 当引脚由低电平变为高电平时,触发中断

// M_FALLING 当引脚由高电平变为低电平时,触发中断

Serial.begin(9600);

}

void loop()

{

digitalWrite(pin, state);

}

void blink()

{

state = !state;//当负反馈端(AIN1)PD7引脚电平发生改变时,触发中断

Serial.println("ANALOG_COMP ISR Trg");

}

📗不使用库代码实现:

//------------------------------------------------------------

// The two LEDs are a red one on D13 which simply blinks every

// 'redDelay' milli-seconds and a green one on D8 controlled

// by the Analog Comparator interrupt.

//------------------------------------------------------------

const uint8_t redLED = 13;

#define M_CHANGE 0

#define M_RISING 2

#define M_FALLING 3

void CMP_Init(unsigned char bytes)

{

PORTD|=_BV(PORTD7);

DIDR1|=_BV(AIN1D)|_BV(AIN0D);

ACSR=0;

ACSR|=_BV(ACIE)|_BV(ACBG)|bytes;

SREG|=(1<<7);

}

void setup() {

// put your setup code here, to run once:

pinMode(redLED, OUTPUT);

Serial.begin(9600);

CMP_Init(M_CHANGE);

}

void loop() {

// put your main code here, to run repeatedly:

}

// The ISR for the Analog Comparator sets the LED on pin 8 to

// the same state as the ACO bit in the ACSR register.

//------------------------------------------------------------

ISR(ANALOG_COMP_vect) {

digitalWrite(redLED, !!(ACSR & (1 << ACO)));

Serial.println("ANALOG_COMP ISR Trg");

}

🎈其它相关比较器使用库:https://github.com/NormanDunbar/libAnaComp/tree/main

📙端口引脚电平变化中断

在Atmega328上有两个正常的硬件中断,从中断向量表中可以看到分别是INT0和INT1。这两个中断对应的引脚为PD2和PD3。除了这两个中断外,其余的硬件中断为“Pin-Change Interrupt”,简记为PCINT。PCINT分为三组。每组对应8个Pin,通过寄存器PCICR、PCIFR和PCMSKn(n:0-3),从而实现了所有GPIO都可以用作中断引脚。

📒测试例程:

/*

PCICR – 引脚改变中断控制寄存器,BIT4:0 ->PCIE4:PCIE0分别对应PF PE PD PC PB端口;当对应为写1时,对应端口引脚中断被使能。

PCIFR – 引脚改变中断标志寄存器BIT4:0 -> PCIF4:PCIF1 分别对应PF PE PD PC PB端口引脚改变中断标志位;对应为写1清零

PCMSK0 引脚改变中断屏蔽寄存器0 BIT7:0 对应PCINT7:PCINT0 对应端口:PB0 - PB7

PCMSK1 引脚改变中断屏蔽寄存器1 BIT7:0 对应PCINT14:PCINT8 对应端口:PC0 - PC7

PCMSK2 引脚改变中断屏蔽寄存器2 BIT7:0 对应PCINT23:PCINT16 对应端口:PD0 - PD7

PCMSK3 – 引脚改变中断屏蔽寄存器3 BIT7:0 对应PCINT27:PCINT24 对应端口:PE0 - PE7

引脚端口 中断向量 中断号

PB0-PB7 PCINT0 3

PC0-PC7 PCINT1 4

PD0-PD7 PCINT2 5

PE0 - PE7 PCINT3 27

ISR (PCINT0_vect) 处理 Pin D8 to D13

ISR (PCINT1_vect) 处理 Pin A0 to A5

ISR (PCINT2_vect) 处理 Pin D0 to D7

ISR (PCINT3_vect) 处理 Pin PE00 to PE7

*/

void setup() {

// put your setup code here, to run once:

pinMode(LED_BUILTIN, OUTPUT);

Serial.begin(9600);

PCICR=1<

PCIFR=1<

PCMSK1=(1<

sei();//使能中断

}

void loop() {

// put your main code here, to run repeatedly:

}

ISR(PCINT1_vect){

//你的中断程序

Serial.println("PCINT1_vect");

PORTB ^= (1 << PINB5);//PB5状态翻转

}

⚡如果程序中使用了软串口(SoftwareSerial), 包含了( #include ),程序编译会报错,该源文件中已经被定义了相关ISR函数。

相关推荐

平板怎么不能打字了
beat365英超欧冠平台

平板怎么不能打字了

📅 08-25 👁️ 4813
汽车之家
365betappios

汽车之家

📅 09-18 👁️ 1897
快看漫画
beat365英超欧冠平台

快看漫画

📅 07-08 👁️ 1110
打哈欠为什么会流眼泪
be365

打哈欠为什么会流眼泪

📅 09-22 👁️ 9176
黎明之光什么职业好玩又厉害 职业特点与新手职业选择推荐
哈萨克斯坦《今日丝路报》探访中国女排的“娘家”