arduino的硬件中断和定时器中断
sean 编辑于2021-06-09 16:35Arduino
中断是一种相对于轮询来说更高效的一种调度方式:
arduino uno只有两个引脚支持硬件中断,(D2, 0),(D3, 1),D2对应0中断号,D3对应1中断号。
其他板的中断引脚多一些,
void setup()
{
pinMode(12, OUTPUT);
//初始化D2针脚,没有信号时默认高电平
pinMode(2, INPUT_PULLUP);
//这里0,号为中断号连接D2引脚,1号连接D3引脚。
//FALLING,说明当D2从高电平降为低电平变化时则触发,mycallbackfunc则会被调用,这里这个mycallbackfunc则称为ISR中断服务程序。
attachInterrupt(0, mycallbackfunc, FALLING);
}
void loop(){}
void mycallbackfunc(){
digitalWrite(12, HIGH);
}
attachInterrupt()为中断关联函数,这里参数0,号为中断号连接D2引脚,1号连接D3引脚。FALLING,说明当D2从高电平降为低电平变化时则触发,mycallbackfunc则会被调用,这里这个mycallbackfunc则称为ISR中断服务程序。
如果要禁用0号中断号的所有中断可以使用detachInterrupt(0)这个函数。
关于中断模式不仅仅有FALLING(下降沿),还有RISING(上升沿):
中断模式 | 模式解释 |
FALLING | 当引脚电平从高电平降为低电平时,触发中断 |
RISING | 当引脚电平从低电平升为高电平时,触发中断 |
CHANGE | 当引脚电平发生变化时,触发中断 |
HIGH | 当引脚处于高电平时,触发中断,并持续运行ISR |
LOW | 当引脚处于低电平时,触发中断,并持续运行ISR |
- ISR(中断服务程序)运行的时候,loop()函数不会运行,直到ISR运行完成。
- ISR运行时,中断是被关闭的,目的是防止ISR之间互相干扰,如果中断中使用的delay()或者millis()函数,将不会生效,因为delay()函数使用了中断和定时器。
- 而millis()在会记录程序执行毫秒数由于使用到了中断,在ISR中,millis()是不会产生变化的。
- 如果要用类似功能可以用delayMicroseconds(),它没有用到中断。
- Serial通讯也用到中断,所以在ISR中也不能稳定可靠运行。
- ISR中,无法传递参数,所以要用到全局变量。但在声明全局变量的时候,最好使用volatile,来防止编译器把该变量缓存到寄存器中,如果缓存过程被中断,则会而导致的变量更新失败。
ISR注意事项:
- 程序短而快
- ISR传参要用volatile来声明变量
- 不要使用millis(),因为它的返回值不会在ISR中变化的。
- 不使用delay() ,不可以被使用,但可以用delayMicroseconds()。
- 尽量避免使用串口通讯,因为通讯不可靠。
- 如果想在某些程序中,不想被中断打扰可以通过interrupts()和noInterrupts()来打开和关闭中断。关闭中断场景:使用串口通讯时,或者是使用delayMicroseconds生成精确计时的脉冲的情况下。
定时器中断
关于定时器中断,是由定时事件触发调用ISR的过程。
这里会用到TimerOne的库,Timer1是 ATmega168/328上的16位精度(0~65535)的硬件计时器的库
Arduino具有3个Timers和6个PWM输出引脚。计时器和PWM输出之间的关系是:
- 引脚5和6:由计时器0 控制
- 引脚9和10:由计时器1 控制。
- 引脚11和3:由计时器2 控制。
#include <TimerOne.h>
int outputPin = 12;
volatile int output = Low;
void setup(){
pinMode(12, OUTPUT);
Timer1.initialize(500); //1~8388480us(8.4s)
Timer1.attachInterrupt(myoutput);
}
void loop(){}
void myoutput(){
digitalWrite(outputPin, output);
output = ! output;
}
这个程序如果用delay()来替代,则不会精确产生波形,实际输出高电平的时间在延迟中会被忽略。
利用TimerOne库,可以在9,10引脚使用定时器产生pwm,相对于analogWrite()的优点:
TimerOne | analogWrite | |
占空比精度 | (0~1023) | (0~255) |
频率固定 | 频率不固定,可以定制 | 500Hz |
TimerOne生成pwm的范例:
#include <TimerOne.h>
void setup(){
pinMode(9, OUTPUT);
pinMode(10, OUTPUT);
Timer1.initialize(1000);//周期1000us,频率为1khz的pwm,如果设置的是10us的周期,频率为100khz的pwm
Timer1.pwm(9, 512); //占空比50%的pwm
Timer1.pwm(10, 255); //占空比25%的pwm
}
关于本站
肥龙软件分享的软件是本站作者开发的免费,无广告,安全可靠,绝不附带任何无关软件,绝不困绑任何插件的实用软件。如果您感觉好用,可以捐赠我们,这样我们可以有更积极的动力去改进升级软件,维持服务器运转,感谢您的捐助,谢谢!
致谢 赞赏/捐助名单
更新时间:2024.8.31
联系作者(邮箱)
软件