GD32/STM32 定时器TIMER使用指南
✨定时器可以对输入的时钟进行计数,并在计数值达到设定值时触发中断✨
如何计数看动画讲解:bilibili_【STM32】第16集 动画告诉你, STM32的定时器到底怎么回事
🐼 如无特别说明,以GD32F450作为例子
🐼 附有GD32F450 TIMER0定时器输出1Khz的互补PWM波源码
1. 配置流程
🟡2. 计算定时时间
2.1 定时器时钟频率CK_TIMERx
对STM32F407
对GD32F450
- 看系统时钟:__SYSTEM_CLOCK_200M_PLL_25M_HXTA
- 看外设挂载的总线的时钟:
- 看定时器时钟配置:
参考:GD32F4(7):GD32F4定时器使用_gd32定时器中断_哈搭石的博客-CSDN博客
/* CK_TIMERx = 4 x CK_APB1 = 4x50M = 200MHZ */
rcu_timer_clock_prescaler_config(RCU_TIMER_PSC_MUL4); //定时器时钟就是AHB总线时钟
定时时间: (prescaler+1)* (period+1)/ CK_TIMERx
eg:CK_TIMERx,若为TIMER0,挂载在APB1上,则CK_TIMERx=系统时钟4分频再4倍频=系统时钟
2.2 定时器参数
📍举例定时器时钟频率=CK_TIMERx,问:定时器的工作频率?
/* 配置定时器参数 */
timer_initpara.prescaler = pre -1; // 时钟预分频值 0-65535 psc_clk 计数器时钟频率 = CK_TIMERx / pre
timer_initpara.alignedmode = TIMER_COUNTER_EDGE; // 对齐方式:边缘对齐
timer_initpara.counterdirection = TIMER_COUNTER_UP; // 计数方式:向上计数
timer_initpara.period = per - 1; // 计数器周期
/*在输入捕获的时候使用 数字滤波器使用的采样频率之间的分频比例*/
timer_initpara.clockdivision = TIMER_CKDIV_DIV1; // 分频因子
/*只有高级定时器才有 配置为x,就重复x+1次进入中断 */
timer_initpara.repetitioncounter = 0; // 重复计数器
timer_init(BSP_TIMER,&timer_initpara); // 初始化定时器
几个相关的频率
定时器时钟频率 =CK_TIMERx
定时器计数器时钟频率 =PSC_CLK
定时器的工作频率 = CK_TIMERx / pre / per
-
prescaler 预分频值
对CK_TIMERx进行分频,CK_TIMERx经过预分频之后得到PSC_CLK。每经过一个PSC_CLK都会产生一个计数周期,prescaler参数将决定一个计数周期的时间。设预分频值为pre,则计数器时钟频率PSC_CLK=TIMER_CK / (pre + 1)。 -
alignedmode 对齐方式
TIMER_COUNTER_EDGE边缘对齐/TIMER_COUNTER_CENTER_BOTH中心对齐 -
counterdirection 计数方式
向上/向下。基本定时器只能向上计数,计数器从0开始向上连续计数到自动加载值(定义在TIMERx_CAR寄存器中),一旦计数器计数到自动加载值,会重新从0开始向上计数并产生上溢事件。 -
period 计数器周期
【例子:(不考虑对齐方式和重复计数器)预分频值=1,则计数器时钟频率=定时器时钟频率;计数器周期=10,即10个计数器时钟周期为定时器工作的1个周期,即工作频率=计数器时钟频率/10】 -
clockdivision 时钟分频
在输入捕获的时候使用,定时器时钟频率与死区发生器和数字滤波器使用的采样频率之间的分频比 -
repetitioncounter 重复计数器
(只有高级定时器有)=更新事件的生成频率,重复计数器是用来在N+1个计数周期之后产生更新事件。
在每次计数器上溢和下溢时递减(向上计数模式中不存在下溢事件;向下计数模式中不存在上溢事件)。
📍在上述例子中,修改重复计数器,定时器时钟频率CK_TIMERx 为120Mhz,请问定时器的工作频率是多少
timer_initpara.prescaler = 1-1;
timer_initpara.alignedmode = TIMER_COUNTER_EDGE;
timer_initpara.counterdirection = TIMER_COUNTER_UP;
timer_initpara.period = 2000-1;
timer_initpara.clockdivision = TIMER_CKDIV_DIV1;
timer_initpara.repetitioncounter = 2;
timer_init(timer,&timer_initpara);
🐼此公式的 时钟频率 为 定时器计数器时钟频率
3. PWM输出配置——OC(Output Compare)输出比较
- 高级定时器可输出互补通道,产生互补PWM波
- 在 PWM 输出模式下,通道根据 TIMERx_CAR 寄存器和 TIMERx_CHxCV 寄存器的值,输出 PWM 波形
timer_oc_parameter_struct timer_ocintpara;
timer_ocintpara.outputstate = TIMER_CCX_ENABLE;
timer_ocintpara.outputnstate = TIMER_CCXN_ENABLE;
timer_ocintpara.ocpolarity = TIMER_OC_POLARITY_HIGH;
timer_ocintpara.ocnpolarity = TIMER_OCN_POLARITY_HIGH;
timer_ocintpara.ocidlestate = TIMER_OC_IDLE_STATE_LOW;
timer_ocintpara.ocnidlestate = TIMER_OCN_IDLE_STATE_LOW;
timer_channel_output_config(TIMER0,TIMER_CH_0,&timer_ocintpara);
timer_channel_output_pulse_value_config(TIMER0,TIMER_CH_0,50-1);
timer_channel_output_mode_config(TIMER0,TIMER_CH_0,TIMER_OC_MODE_PWM0);//配置通道输出比较模式为PWM0模式
timer_channel_output_shadow_config(TIMER0,TIMER_CH_0,TIMER_OC_SHADOW_DISABLE);
timer_channel_output_pulse_value_config(TIMER0, TIMER_CH_0, 50);//比较寄存器的数值【影响PWM波占空比大小】
timer_enable(TIMER0);
3.1 输出比较模式
ST
3.2 比较事件
- 比较事件是CNT和CHxCV比较后触发的,触发后CHxIF置1。
- 由它来控制电平输出以生成PWM波,所以PWM波频率受 对齐模式 的影响
3.3 计算PWM波频率
📍定时器时钟频率CK_TIMERx 为120Mhz,请问生成PWM波频率是多少
timer_initpara.prescaler = 1-1;
timer_initpara.alignedmode = TIMER_COUNTER_EDGE;//边缘计数,为EAPWM
timer_initpara.counterdirection = TIMER_COUNTER_UP;
timer_initpara.period = 2000-1;
timer_initpara.clockdivision = TIMER_CKDIV_DIV1;
timer_initpara.repetitioncounter = 2;
timer_init(timer,&timer_initpara);
PWM波频率=30kHz
🐼EAPWM 的周期=计数器从0递增的一个周期,EAPWM 的周期由 TIMERx_CAR 寄存器值决定,占空比由 TIMERx_CHxCV 寄存器值决定。
📍若把对齐方式改为中央对其,定时器时钟频率CK_TIMERx 为120Mhz,请问生成PWM波频率是多少
timer_initpara.prescaler = 1-1;
timer_initpara.alignedmode = TIMER_COUNTER_CENTER_BOTH;//中央对齐上下计数为CAPWM
timer_initpara.counterdirection = TIMER_COUNTER_UP;
timer_initpara.period = 2000-1;
timer_initpara.clockdivision = TIMER_CKDIV_DIV1;
timer_initpara.repetitioncounter = 2;
timer_init(timer,&timer_initpara);
🐼 中央对齐时,和上一例子不同在于,计数器的两个变化过程(一个递增计数【只包含了PWM的一半】+一个递减计数)才是PWM的一个周期;因此有:CAPWM 的周期由(2TIMERx_CAR 寄存器值)决定,占空比由(2TIMERx_CHxCV 寄存器值)决定
PWM波频率=15kHz
4. 基本功能
4.1 更新事件
更新事件是当计数器上溢或者下溢而开始新的计数周期时触发的。更新事件可以触发DMA请求,以用于在下一个计数周期开始时及时更新定时器的运行参数,特别适合用于实时控制。
4.2 TRGO信号
TRGO信号包括复位事件、使能事件、更新事件、捕获比较脉冲事件、比较事件。
TRGO信号可以用于作为ADC转换的外部触发源
timer_master_output_trigger_source_select(timer, TIMER_TRI_OUT_SRC_UPDATE);// update event as trigger output */
//当产生一个定时器更新事件后,输出一个TRGO信号,用于触发外设如ADC
4.3 计数器寄存器(TIMERx_CNT)
当TIMER0137均配置成一样,但初始化时候,把它们的CNT设成不同,即TIMER0的计数器初始值就比其他大,会最先到达周期值,可以形成如下
TIMER_CNT(TIMER0) = 300/3*3;//先
TIMER_CNT(TIMER1) = 300/3*2;
TIMER_CNT(TIMER7) = 300/3*1;
TIMER_CNT(TIMER3) = 0;//后
现象:同一定时器不同通道PWM波开始时间不同
4.4 死区
死区时间的插入,确保了通道互补的两路信号不会同时有效。