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。也许它没有像预期的那样自动执行。
我正在尝试让 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。也许它没有像预期的那样自动执行。