ATmega328P 定时器中断不触发
配置了定时器溢出中断,但 ISR 就是不执行。已经检查了预分频器和中断使能位,求有经验的朋友指点 你应该晒出代码啊以下是一个基于 ATmega328P 的定时器溢出中断(Timer Overflow Interrupt)示例代码,使用 Timer1(16位定时器)实现周期性中断,并在中断服务程序(ISR)中翻转LED状态(假设LED连接在 PB5,即Arduino的D13引脚)。
#include <avr/io.h>
#include <avr/interrupt.h>
#define LED_PIN PB5 // Arduino D13 (ATmega328P的PB5)
void initTimer1() {
// 1. 设置定时器1为普通模式(Normal Mode),计数到最大值0xFFFF后溢出
TCCR1A = 0; // 普通模式,无需波形生成
TCCR1B = 0; // 先停止定时器
// 2. 设置预分频器(Prescaler)为1024,启动定时器
// 计算公式:溢出时间 = (65536 / F_CPU) * 分频系数
// 例如:16MHz时钟,分频1024 → 溢出时间 ≈ 4.096秒
// 若需更短时间,可设置初始计数值(TCNT1)
TCCR1B |= (1 << CS12) | (1 << CS10); // 分频1024 (CS12:CS10 = 101)
// 3. 使能定时器1溢出中断
TIMSK1 |= (1 << TOIE1);
// 4. 全局中断使能
sei();
}
// 定时器1溢出中断服务程序
ISR(TIMER1_OVF_vect) {
// 翻转LED状态
PORTB ^= (1 << LED_PIN);
// 可选:重新加载定时器初值(如需精确周期)
// TCNT1 = 65536 - (目标计数值);
}
int main() {
// 初始化LED引脚为输出
DDRB |= (1 << LED_PIN);
PORTB &= ~(1 << LED_PIN); // 初始状态低电平
// 初始化定时器1
initTimer1();
while (1) {
// 主循环可执行其他任务
// 中断会异步触发LED翻转
}
} 其他定时器:若需更短周期,可使用8位定时器(如Timer0或Timer2),或调整预分频。
CTC模式:通过 OCR1A 设置比较值,触发中断而非溢出(模式更精确)。 本帖最后由 lcczg 于 2025-7-25 11:32 编辑
幸福小强的代码可以运行。我在板子上可以看到LED灯在闪烁,闪的比较慢,大概8秒翻转一下。 定时器是很基础的应用,参考一下楼上的代码,或者发出来自己的。 检查一下你的中断使能代码是否正确,有时候一个小小的错误就可能导致中断无法触发。
检查一下你的中断使能代码是否正确,有时候一个小小的错误就可能导致中断不被触发。
检查中断向量名称 中断向量冲突? 参考ATmega328P数据手册。 在配置定时器寄存器前禁用中断(cli()),配置完成后再启用(sei())。 在配置中断前,必须通过sei()指令启用全局中断。若未启用,即使定时器中断已配置,ISR也不会执行。 检查一下是否正确设置了定时器的模式和初始值,有时候设置不当也会导致中断不触发。
页:
[1]