首页 > 解决方案 > ATSAML21 硬件定时器

问题描述

我一直在尝试通过 SAML21 MCU 配置和运行硬件计时器以生成 100 毫秒的延迟,即 ISR 应该每 100 毫秒触发一次。但可以观察到,在启动定时器后,ISR 每 10us 触发一次,并且更改预分频器和比较寄存器值不会在 10us 间隔中产生任何差异。请检查我的代码,让我知道我做错了什么。我正在尝试将 Timer1(TC1) 配置为 16 位模式,使用 GCLK_GENERATOR_1 作为其时钟源,以 8MHz 频率(CPU 主时钟:16MHz)运行。定时器预计每 100ms 产生一次溢出中断。

TcCount16 *tc_hw1 = NULL;   /* Pointer to TC1 hardware registers Initilized later */
void init_timer1(void)
{
   struct tc_module tc_inst1;   
   struct tc_config conf_tc1;

   tc_get_config_defaults(&conf_tc1);

   conf_tc1.clock_source = GCLK_GENERATOR_1;
   conf_tc1.clock_prescaler = TC_CLOCK_PRESCALER_DIV64; /* 8MHz/64 = 125KHz*/
   conf_tc1.reload_action = TC_RELOAD_ACTION_GCLK;
   conf_tc1.counter_size = TC_COUNTER_SIZE_16BIT;
   conf_tc1.count_direction = TC_COUNT_DIRECTION_UP;
   conf_tc1.counter_16_bit.value = 0x0000;
   /** Rest of the settings are used as defaults **/
   while (tc_init(&tc_inst1, TC1, &conf_tc1) != STATUS_OK){
   }

   tc_set_top_value(&tc_inst1, 12500); /* Set counter compare top value */
   /* Enable interrupt & Set Priority */
   tc_hw1 = &(tc_inst1.hw->COUNT16);   /* Initialize pointer to TC1 hardware register */
   tc_hw1->INTENSET.reg |= TC_INTFLAG_OVF;  /* Enable Overflow Interrupt */
   NVIC_SetPriority(TC1_IRQn, 2);
   NVIC_EnableIRQ(TC1_IRQn);        
   tc_enable(&tc_inst1);    /*Start The TIMER*/
}

void TC1_Handler(void)
{

   if((tc_hw1->INTFLAG.reg) & (TC_INTFLAG_OVF))
   {
      port_pin_toggle_output_level(PIN_PB03);
   }
   system_interrupt_clear_pending(SYSTEM_INTERRUPT_MODULE_TC1);
}

调试器信息:我可以看到定时器寄存器配置正确,但每次我暂停捕获调试信息时,计数寄存器都不会自行递增,它只显示 0x0000 值。请帮忙。谢谢!

标签: timercortex-matmelmicrochipsam

解决方案


我解决了这个问题,实际上它是强制清除 INTFLAG 寄存器中的定时器 OVF 位的。所以中断处理程序应该是这样的:

void TC1_Handler(void)
{

   if((tc_hw1->INTFLAG.reg) & (TC_INTFLAG_OVF))
   {
     tc_hw1->INTFLAG.reg = TC_INTFLAG_OVF;  /*Clears the flag by writing 1 to it*/
     port_pin_toggle_output_level(PIN_PB03);
   }
   system_interrupt_clear_pending(SYSTEM_INTERRUPT_MODULE_TC1);  /*Not necessarily needed*/
}

推荐阅读