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

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


📖外部中断函数

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

在这里插入图片描述

  • 🌿对于328P单片机处理INT0和IT1外部中断引脚外,还支持端口引脚中断,分别对应中断向量表中的:PCINT0,PCINT1,PCINT2,PCINT3
    在这里插入图片描述
    在这里插入图片描述
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
}

🥕对于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 <ACD.h>

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<<PCIE1;//使能PC端口引脚中断
  PCIFR=1<<PCIF1;//清空PC端口中断标志位
  PCMSK1=(1<<PCINT9);//使能端口具体中断引脚为PC1
  sei();//使能中断
}

void loop() {
  // put your main code here, to run repeatedly:

}
ISR(PCINT1_vect){
    //你的中断程序
    Serial.println("PCINT1_vect");
    PORTB ^= (1 << PINB5);//PB5状态翻转
    }

  • ⚡如果程序中使用了软串口(SoftwareSerial), 包含了( #include <SoftwareSerial.h>),程序编译会报错,该源文件中已经被定义了相关ISR函数。
  • 3
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值