AVR 中断配置
AVR Interrupt Configuration
问题是计时行为完全错误(因子 30)。
我有一个 ATmega 644PA,它是 运行 8 Mhz(未设置 CKDIV8 保险丝)。
我想要每 1 毫秒中断一次。我在比较模式下使用 Timer1(16 位定时器)。
预分频器是根据我需要的时间范围选择的。
这里是 1 ms 到 ~2s。 (通过 16 位定时器寄存器限制)
计算
CPU:8.000.000 赫兹
预分频器:256
8.000.000 Hz / 256 = 31250 周期/秒 (Hz)
1000 毫秒 = 31250 个周期
1 毫秒 = 30.25 个周期(31.25 - 1,定时器寄存器从 0 开始)
从这里我可以计算出来,例如:
100 毫秒 = 3025 个周期
2s = 60500 次循环
代码
定时器初始化
cli(); // disable global interrupts
TCCR1A = (1 << WGM01); // CTC ON
TCCR1B = 0x04; // Prescaler 256
OCR1A = 30; // set compare reg.
TIMSK1 = (1 << OCIE1A); // set interrupt mask
TCNT1 = 0x00; // set counter reg. to zero
sei(); // enable global interrupts
ISR:
ISR(TIMER1_COMPA_vect)
{
// start own code
...
// end own code
TCNT1 = 0x00; // reset counter reg. to zero after match (same which should CTC do)
}
现在我有一个 volatile 变量,它将在 ISR 函数中递增。
我正在轮询变量并等待很长时间,直到它达到 60500,等于 2s。
之后我只是设置了一个 LED。
我用phone测了一下,led灯亮需要1分钟。
因数 30 需要很长时间 => 60s 除以 2s 是 30。
我也试过用外部程序计算,结果是一样的。 (0x1E = 30)
有人知道我的错误在哪里吗?
2 秒是 60500 个周期。但是您的 ISR 每 1 毫秒递增一次 volatile 变量。自然地,变量达到60500需要60.5秒。
附带说明一下,最好更改比较值,而不是重置 TCNT,以避免时序漂移。即让计数器运行自由发挥,用OCR1A += 31;
命中下一个中断。像你这样重置 TCNT 将忽略 ISR 中的时间。
问题是计时行为完全错误(因子 30)。
我有一个 ATmega 644PA,它是 运行 8 Mhz(未设置 CKDIV8 保险丝)。
我想要每 1 毫秒中断一次。我在比较模式下使用 Timer1(16 位定时器)。
预分频器是根据我需要的时间范围选择的。
这里是 1 ms 到 ~2s。 (通过 16 位定时器寄存器限制)
计算
CPU:8.000.000 赫兹
预分频器:256
8.000.000 Hz / 256 = 31250 周期/秒 (Hz)
1000 毫秒 = 31250 个周期
1 毫秒 = 30.25 个周期(31.25 - 1,定时器寄存器从 0 开始)
从这里我可以计算出来,例如:
100 毫秒 = 3025 个周期
2s = 60500 次循环
代码
定时器初始化
cli(); // disable global interrupts
TCCR1A = (1 << WGM01); // CTC ON
TCCR1B = 0x04; // Prescaler 256
OCR1A = 30; // set compare reg.
TIMSK1 = (1 << OCIE1A); // set interrupt mask
TCNT1 = 0x00; // set counter reg. to zero
sei(); // enable global interrupts
ISR:
ISR(TIMER1_COMPA_vect)
{
// start own code
...
// end own code
TCNT1 = 0x00; // reset counter reg. to zero after match (same which should CTC do)
}
现在我有一个 volatile 变量,它将在 ISR 函数中递增。
我正在轮询变量并等待很长时间,直到它达到 60500,等于 2s。
之后我只是设置了一个 LED。
我用phone测了一下,led灯亮需要1分钟。
因数 30 需要很长时间 => 60s 除以 2s 是 30。
我也试过用外部程序计算,结果是一样的。 (0x1E = 30)
有人知道我的错误在哪里吗?
2 秒是 60500 个周期。但是您的 ISR 每 1 毫秒递增一次 volatile 变量。自然地,变量达到60500需要60.5秒。
附带说明一下,最好更改比较值,而不是重置 TCNT,以避免时序漂移。即让计数器运行自由发挥,用OCR1A += 31;
命中下一个中断。像你这样重置 TCNT 将忽略 ISR 中的时间。