中断在上面讲完PWM之后,我们再来讲一下中断,以及中断的一个实际案例 。中断,顾名思义,是在程序执行期间,遇到某一个事件的时候,将暂停手上的工作先去执行某一件事情,这个事情则是我们中断当下工作,去执行的事情,这个动作,称之为中断 。虽然在代码中,可以注册一个后台任务(在纯c中),进行不停的while,但是这样在性能上还是无法发挥单片机的功效,所以这种场景下我们便需要使用中断,来实现我们的某种功能,例如使用按钮,来判断是否需要打开LED,或者是其他的行为 。
在Arduino中,我们可以使用attachInterrupt函数来进行对引脚增加中断以及使用detachInterrupt来移除中断,
attachInterrupt函数需要三个参数,第一个为中断需要使用的引脚pin,第二个为中断触发的函数,第三个为中断的类型,对于ESP32的中断,在Arduino中,其方法名前面必须加一个IRAM_ATTR标记其为中断函数,第一个函数中的digitalPinToInterrupt为将27和中断进行一个绑定,同时还有其他方法,但是官方均不推荐,
在下方的代码中,我们定义了一个change的函数用来处理ESP32 27引脚的中断,用27引脚的电平控制LED引脚2的电平,以此来控制是否点亮LED灯,先设置引脚2为输出模式,27引脚为上拉输入模式,可以理解为上拉电阻的一般都需要用到这种模式,然后我们将引脚27和中断进行关联,设置中断函数为change,模式为CHANGE 。然后在LOOP函数中,我们给引脚2写入state的值,当进入change中断函数中,会将state取反,然后进入loop写入值 。以此实现控制LED的显示和不显示,在这里,提醒一下,由于在单片机中,中断以及定时器都是非阻塞模式,而Serial.println函数是阻塞写入缓冲区,会导致中断函数会不断的输出错误,错误:Guru Meditation Error: Core 1 panic'ed (Interrupt wdt timeout on CPU1).
这是因为println函数阻塞导致定时器无法继续执行,所过非要使用此函数,可以尝试设置中间变量,然后在loop函数中判断是否改变值,然后进行输出信息到串口 。
可以在下方GIF看到,我们使用按钮进行控制LED的显示和不显示 。
volatile byte state = LOW;void IRAM_ATTR change(){state=!state;}void setup() {// put your setup code here, to run once:Serial.begin(9600);pinMode(2, OUTPUT);pinMode(27, INPUT_PULLUP);attachInterrupt(digitalPinToInterrupt(27), change, CHANGE);}void loop() {digitalWrite(2, state);// put your main code here, to run repeatedly:}
可以看到第二个方法是传入一个interrupt的中断编号,但是ESP32上面的中断编号,不在官方资料中,所以我们只有需要第一个方法来进行引脚和中断函数的关联,当然了可能最后一个也是可以,只是此处我没有尝试,感兴趣的可以进行尝试,
在mode中,Arduino是支持五种模式,第一种为LOW,,看翻译我们知道,这个是在电平处于低电平时会触发中断函数,
第二个CHANGE是不管是高到低,还是低到高,都会触发
第三种是引脚在由低电平到高电平时触发,而不是已经到了高电平触发,
第四种是下降,当电平由高到低时会触发中断函数,
第五种是电平处于高电平时会触发中断函数 。
文章插图
文章插图
结语今天讲了PWM还有中断的使用,可能一次性讲的有点多,有点难以消化,有什么不懂的可以及时问我,以及后面我更新的时间会稍微慢一点,防止讲的过快,一时间不明白,后面还会有对于IIC,SPI的一个案例讲解,在这些讲完后,我会开始准备最终极的目标,做一个智能小车,其中会需要的配件,这两天我会总结好发到群里,以及购买链接 。有感兴趣的同学可以加QQ群,一起学习,一起讨论,博主也是一个刚开始玩单片机的学徒,后面也会研究stm32系列单片机,欢迎大家加入讨论,学习 。