AVR Xmega16E5 定时器只创建一个 cc 中断

AVR Xmega16E5 Timer creates only one cc interrupt

我正在尝试让 atxmega16e5 上的 TCC4 工作。我的问题是比较通道中断只触发一次。中断标志甚至被设置,但 ISR 永远不会执行。我启用了溢出中断,它一直工作得很好。我已经在模拟器和我的实际芯片上进行了测试,结果相同。我正在使用 Atmel 软件框架。我真的觉得我缺少一些基本的东西,我就是想不通。

代码如下:

#define TIMER_TC              TCC4
#define TIMER_INT_LVL         TC45_INT_LVL_LO

int main (void) {
    sysclk_init();
    eeprom_enable_mapping();
    board_init();
    pmic_init();

    timer_init();
    timer_set_top(100);

    cpu_irq_enable();

    timer_start();

    while(1) {}
}

void timer_cca(void) { //Breakpoint here - reached just once
}

void timer_ccb(void) { //Breakpoint here - reached just once
}

void timer_ccc(void) { //Breakpoint here - reached just once
}

void timer_ccd(void) { //Breakpoint here - reached just once
}

void timer_overflow(void) { //Breakpoint here - reached multiple times
}

void timer_init() {
    tc45_enable(&TIMER_TC);
    tc45_set_wgm(&TIMER_TC, TC45_WG_NORMAL);
    tc45_enable_cc_channels(&TIMER_TC, TC45_CCACOMP | TC45_CCBCOMP | TC45_CCCCOMP | TC45_CCDCOMP);
    tc45_set_cca_interrupt_callback(&TIMER_TC, &timer_cca);
    tc45_set_cca_interrupt_level(&TIMER_TC, TIMER_INT_LVL);
    tc45_set_ccb_interrupt_callback(&TIMER_TC, &timer_ccb);
    tc45_set_ccb_interrupt_level(&TIMER_TC, TIMER_INT_LVL);
    tc45_set_ccc_interrupt_callback(&TIMER_TC, &timer_ccc);
    tc45_set_ccc_interrupt_level(&TIMER_TC, TIMER_INT_LVL);
    tc45_set_ccd_interrupt_callback(&TIMER_TC, &timer_ccd);
    tc45_set_ccd_interrupt_level(&TIMER_TC, TIMER_INT_LVL);

    tc45_write_cc(&TIMER_TC, TC45_CCA, 1);
    tc45_write_cc(&TIMER_TC, TC45_CCB, 1);
    tc45_write_cc(&TIMER_TC, TC45_CCC, 1);
    tc45_write_cc(&TIMER_TC, TC45_CCD, 1);

    tc45_set_overflow_interrupt_level(&TIMER_TC, TC45_INT_LVL_LO);
    tc45_set_overflow_interrupt_callback(&TIMER_TC, &timer_overflow);
}

void timer_start() {
    tc45_write_clock_source(&TIMER_TC, TC45_CLKSEL_DIV64_gc);
}

void timer_set_top(uint16_t top) {
    tc45_write_period(&TIMER_TC, top);
}

这是 ASF 快速入门文档的 link,用于使用 TC45 处理通道比较中断: http://asf.atmel.com/docs/3.11.0/xmegae/html/xmega_tc45_quickstart.html#xmega_tc45_qs_cc

看起来你很接近。我看到的唯一真正区别是它们将 ISR 声明为 static void 并将它们直接传递给 set_callback 函数,而不是传递指针:
tc45_set_cca_interrupt_callback(&TIMER_TC, timer_cca);

而不是:
tc45_set_cca_interrupt_callback(&TIMER_TC, &timer_cca);

为了安心,我还会在 cc 通道启用周围添加括号:
tc45_enable_cc_channels(&TIMER_TC, (TC45_CCACOMP | TC45_CCBCOMP | TC45_CCCCOMP | TC45_CCDCOMP));

尝试增加比较值。调试器可能不够快,无法在重置计数器并处理溢出中断后捕获比较值 1。

如果您仍然遇到问题,请尝试在 ISR 中手动清除 CCxIF。也许它没有像预期的那样自动执行。