梁山派(GD32F450ZG)-定时器计时中断配置
这里写目录标题
配置TIME5每10ms中断一次
1、了解系统时钟、APB1时钟、定时器时钟
由GDF450的数据手册中的时钟树可以看出,定时器5的工作频率是由APB1经过一个倍频器得到,而APB1由AHB通过一个APB1预分频器产生
在GD32F4xx标准库3.0.0的system_gd32f4xx.c文件中的系统时钟初始化函数已经将系统时钟配置为200MHz,同时将APB1预分频器设置为➗4,因此APB1时钟为50MHz,而定时器时钟还需要经过一个CK_APB1的倍频器(后面讲)
2、初始化配置
2.1、时钟配置
首先使能定时器时钟
rcu_periph_clock_enable(RCU_TIMER5);
其次在通过调用以下函数设置CK_APB1倍频器参数,此处将CK_APB1设置为✖4,也就是将APB1时钟经过4倍频在提供给定时器使用,使得定时器时钟源频率变大到200MHz
rcu_timer_clock_prescaler_config(RCU_TIMER_PSC_MUL4);
2.2、定时器配置
进行定时器配置前首先将定时器进行复位操作,防止之前的一些误操作影响
timer_deinit(RCU_TIMER5);
然后创建定时器配置结构体变量,并进行参数配置
timer_parameter_struct timer_initpara;
timer_initpara.prescaler = pre - 1; //预分频系数
timer_initpara.alignedmode = TIMER_COUNTER_EDGE;
timer_initpara.counterdirection = TIMER_COUNTER_UP;
timer_initpara.period = per - 1; //重装载系数
timer_initpara.clockdivision = TIMER_CKDIV_DIV1; //输入捕获预分频(此处用不到)
timer_initpara.repetitioncounter = 0; //重复计数器,只有高级定时器才有,也就是中断多少次才进入中断服务函数
配置完成后即可将变量传入定时器初始化配置函数进行配置,并使能定时器
timer_init(RCU_TIMER5,&timer_initpara);
timer_enable(RCU_TIMER5);
2.3、中断配置
GD32的标准库中断配置较为简单,只需要调用一条函数即可完成中断优先级的配置,中断向量可以在gd32f4xx.h中找到
nvic_irq_enable(TIMER5_DAC_IRQn,3,2);//抢占优先级3,子优先级2
中断优先级配置完成后一定要记得通过以下函数开启相应的模式中断,比如我们使用定时器5进行计时中断,因此我们要选择TIMER_INT_UP更新中断
timer_interrupt_enable(RCU_TIMER5,TIMER_INT_UP);
3、中断服务函数
相应的中断服务函数名可以在汇编启动文件(startup_gd32f450_470.s)中查找
接下来就可以直接编写中断服务函数内要做的逻辑处理了,需要留意的是,一定要通过函数timer_interrupt_flag_clear(RCU_TIMER5,TIMER_INT_FLAG_UP)将中断标志进行清除,不然会导致重复中断,整个程序无法正常运行!
void TIMER5_DAC_IRQHandler(void)
{
if(timer_interrupt_flag_get(RCU_TIMER5,TIMER_INT_FLAG_UP) == SET)
{
timer_interrupt_flag_clear(RCU_TIMER5,TIMER_INT_FLAG_UP);
// 这里进行逻辑处理
}
}
4、中断时间计算
将上面的初始化配置进行封装成一个完整的函数,然后在while循环前调用并设置好相应的预分频系数和重装载值即可实现指定的时间中断,以下进行一个10ms中断的配置
#define BSP_TIMER_RCU RCU_TIMER5
#define BSP_TIMER TIMER5
#define BSP_TIMER_IRQ TIMER5_DAC_IRQn
#define BSP_TIMER_IRQHandler TIMER5_DAC_IRQHandler
void tim5_config(uint16_t pre,uint32_t per)
{
timer_parameter_struct timer_initpara;
rcu_periph_clock_enable(BSP_TIMER_RCU);
/* CK_TIMERx = 4 x CK_APB1 = 4x50M = 200MHZ */
rcu_timer_clock_prescaler_config(RCU_TIMER_PSC_MUL4);
timer_deinit(BSP_TIMER);
timer_initpara.prescaler = pre - 1;
timer_initpara.alignedmode = TIMER_COUNTER_EDGE;
timer_initpara.counterdirection = TIMER_COUNTER_UP;
timer_initpara.period = per - 1;
timer_initpara.clockdivision = TIMER_CKDIV_DIV1;
timer_initpara.repetitioncounter = 0;
timer_init(BSP_TIMER,&timer_initpara);
timer_enable(BSP_TIMER);
nvic_irq_enable(BSP_TIMER_IRQ,3,2);
timer_interrupt_enable(BSP_TIMER,TIMER_INT_UP);
}
int main(void)
{
tim5_config(2000,1000);
while(1);
}
以上代码将预分频系数设置为2000-1,重装载值设置为1000-1,因为定时器时钟源为200MHz,因此经过预分频后只剩下200MHz/2000=100KHz,因此重装载值为1000的情况下要10ms才能产生中断,你可以简单的将这两个参数都理解为除数,时钟源为被除数,中断时间为商,就会很好计算
以上就是定时器计时中断配置的全过程!
作者:学不下去的废狗