我正在尝试用 Arduino 创建一个延时中断。我想使用 interrupts() 函数,因为它是一个内部中断。
示例:假设我想让灯闪烁,只有中断的时间。
有示例代码,但它使用外部中断(attachInterrupt())。我想继续使用内部中断。
我正在尝试用 Arduino 创建一个延时中断。我想使用 interrupts() 函数,因为它是一个内部中断。
示例:假设我想让灯闪烁,只有中断的时间。
有示例代码,但它使用外部中断(attachInterrupt())。我想继续使用内部中断。
Noah Stahl 的博客有一个使用 Timer2 闪烁 LED的示例。有了它和数据表,您应该能够使其适应您想要使用的任何中断 - 即,您最能够放弃或愿意修改其正常功能的中断。Timer2 通常用于一些 PWM 功能。
他的例子引用了 ATmega2560;我可以确认它也适用于 ATmega328p。在他的网站上查看更多有用的 Arduino 中断示例。
编辑:
这是我稍微编辑过的——主要是在评论中——诺亚代码的版本。在初始化任何相关的数据结构或硬件后,从 Arduino setup() 函数调用 Timer2init(),因为一旦你这样做,计时和中断就会开始。
F/ex,我用它来多路复用一个 3 位 7 段显示器,所以在初始化定时器之前,我初始化了显示 I/O 寄存器并将显示数据消隐在 ISR 将查找它的位置。
数据表中一些有用的时序数据和我自己的计算的注释中有一个表格,供参考以设置另一个时序方案。
ISR() 宏负责为 ISR 创建中断进入和退出代码,而不是普通函数的进入和退出,并将其与适当的中断向量链接。该函数的其余部分是 1) 在每个中断处运行的代码,以及 2) 用于为下一个中断复位定时器的代码。
如所写,这应该放入 .pde 或 .ino 草图(或 .cpp 文件,如果您使用 eclipse,f/ex)。草图需要#define LEDPIN,setup() 需要调用 Timer2init()。循环函数可以为空,也可以不为空;LED 应该在下载时开始闪烁(好吧,字面意思是,在调用 Timer2init() 之后)。
/*
* From sample interrupt code published by Noah Stahl on his blog, at:
* http://arduinomega.blogspot.com/p/arduino-code.html
*
*/
/*** FUNC
Name: Timer2init
Function: Init timer 2 to interrupt periodically. Call this from
the Arduino setup() function.
Description: The pre-scaler and the timer count divide the timer-counter
clock frequency to give a timer overflow interrupt rate:
Interrupt rate = 16MHz / (prescaler * (255 - TCNT2))
TCCR2B[b2:0] Prescaler Freq [KHz], Period [usec] after prescale
0x0 (TC stopped) 0 0
0x1 1 16000. 0.0625
0x2 8 2000. 0.500
0x3 32 500. 2.000
0x4 64 250. 4.000
0x5 128 125. 8.000
0x6 256 62.5 16.000
0x7 1024 15.625 64.000
Parameters: void
Returns: void
FUNC ***/
void Timer2init() {
// Setup Timer2 overflow to fire every 8ms (125Hz)
// period [sec] = (1 / f_clock [sec]) * prescale * (255-count)
// (1/16000000) * 1024 * (255-130) = .008 sec
TCCR2B = 0x00; // Disable Timer2 while we set it up
TCNT2 = 130; // Reset Timer Count (255-130) = execute ev 125-th T/C clock
TIFR2 = 0x00; // Timer2 INT Flag Reg: Clear Timer Overflow Flag
TIMSK2 = 0x01; // Timer2 INT Reg: Timer2 Overflow Interrupt Enable
TCCR2A = 0x00; // Timer2 Control Reg A: Wave Gen Mode normal
TCCR2B = 0x07; // Timer2 Control Reg B: Timer Prescaler set to 1024
}
/*** FUNC
Name: Timer2 ISR
Function: Handles the Timer2-overflow interrupt
Description: Maintains the 7-segment display
Parameters: void
Returns: void
FUNC ***/
ISR(TIMER2_OVF_vect) {
static unsigned int led_state = 0; // LED state
led_state = !led_state; // toggles the LED state
digitalWrite(TOGGLE_PIN, led_state);
TCNT2 = 130; // reset timer ct to 130 out of 255
TIFR2 = 0x00; // timer2 int flag reg: clear timer overflow flag
};
Arduino 正在使用 ATMega328 中的所有三个计时器。Timer1(16 位)用于引脚 5 和 6 上的 PWM 输出等功能delay()。另外millis()两个定时器用于引脚 3、9、10、11 上的 PWM 输出。Timer0Timer2
因此,没有用于定时器中断的 Arduino 功能。但是有办法。您可以使用此代码启用定时器中断Timer2:
ISR(TIMER2_OVF_vect) {
// Interrupt routine.
}
void setup() {
// Enable Timer2 interrupt.
TIMSK2 = (0<<OCIE2A) | (1<<TOIE2);
}
void loop() {
// Your main loop.
}
我没有测试就写了这段代码,所以我可能犯了一个错误。在这种情况下,请检查数据表,第 156 页。
如果要更改定时器频率(预分频器),只需更改 register TCCR2A。有关更多信息,请查看数据表第 153 页。但是,如果您更改定时器的频率,您也会更改两个输出引脚上 PWM 信号的频率!