AT32学习笔记-TIMER1.md
# 定时器基本使用
通过定时器来定期触发中断
## 定时器的初始化
```c
/* enable tmr1 clock */
// 开启外设时钟
crm_periph_clock_enable(CRM_TMR2_PERIPH_CLOCK, TRUE);
// 开启定时器2
tmr_32_bit_function_enable(TMR2, TRUE);
// 单次模式,执行完一次之后就会停止
// tmr_one_cycle_mode_enable(TMR2,TRUE);
// 设置参数,实际值=参数值+1
// 15999 计到这个数字就触发中断
// 19200 首先对systemclock进行预分频
tmr_base_init(TMR2, 19999, (19200) - 1);
// 设置计数方式(这里没有区别)
tmr_cnt_dir_set(TMR2, TMR_COUNT_UP);
```
## 预分频的概念
系统主频为192Mhz,也就是192000000hz,也就是说每次经过1/192000000秒定时器会把cnt+1,但是16位定时器最大cnt只能到65535,很快就满了。
所以说需要对时钟进行分频。
这里分频值为19200,也就是对主频/19200,也就是10khz,也就是说分频后经过1/10000秒后定时器会把cnt+1,然后设置tmr_pr为19999,实际值+参数值+1,也就是cnt到2w会触发中断,20000*1/10000刚好是2秒。
需要注意的是,按照数据手册的要求,分频系数最大65535,超过这个值后就会溢出,最后效果就和预期效果不一样了。
## 开启32位cnt
`tmr_32_bit_function_enable(TMR2, TRUE);`
TIM2和TIM8支持32位计数,也就是说最大范围可以到0xffffffff,大大的提提升了范围。
## 定时器中断的设置
```c
// 开启定时器溢出中断
/* overflow interrupt enable */
tmr_interrupt_enable(TMR2, TMR_OVF_INT, TRUE);
/* tmr1 overflow interrupt nvic init */
// 设置抢占优先级和响应优先级
nvic_priority_group_config(NVIC_PRIORITY_GROUP_4);
// 在nvic中开启该中断,让nvic去管理这个中断
nvic_irq_enable(TMR2_GLOBAL_IRQn, 0, 0);
```
## 定义中断处理函数
`TMR2_GLOBAL_IRQHandler`在startup_at32xxxx.s文件中被定义,也就是常说的中断向量表中被定义
```c
void TMR2_GLOBAL_IRQHandler(void)
{
// 中断处理函数可能被多个定时器公用,所以我们要检查定时器的flag
if(tmr_flag_get(TMR2, TMR_OVF_FLAG) != RESET)
{
/* add user code... */
// 点灯,打印
i++;
at32_led_toggle(LED3);
printf("tmr10 %d\r\n",i);
// 按照寄存器要求,这个flag需要软件置0,要不然一直会触发中断
tmr_flag_clear(TMR2, TMR_OVF_FLAG);
}
}
```