目录
4.2.1 通道控制寄存器TIMERx_CHCTL0和TIMERx_CHCTL1
4.2.2 通道控制寄存器2 (TIMERx_CHCTL2)
GD32F450最多有14组Timer,这些定时器分成5种类型。
定时器的常规作用是测量输入信号的脉冲长度(输入捕获)或者产生输出波形(输出比较和 PWM)等
1. 定时器时钟设定
定时器的时钟源包括APB1和APB2,每个定时器根据芯片设定链接到不同APB,然后由时钟配置寄存器 1 (RCU_CFG1)的TIMERSEL位决定是APB频率的2倍还是4倍,但是这个频率不能超过AHB(最大200MHz)。
为了程序的简单性,可以设置每个Timer的频率都为最大值200MHz。
2. GPIO初始化
PWM需要对应TIMER的通道管脚上,可以查看Datasheet的管脚定义,例如官方例程中用到的PB10,对应TIMER1的CH2。
3. 定时器Timer初始化
3.1 使能RCU
rcu_periph_clock_enable(RCU_TIMERx);
rcu_timer_clock_prescaler_config(RCU_TIMER_PSC_MUL4);
x的范围0-13。
3.2 设置分频比
timer_initpara.prescaler = SystemCoreClock / clk - 1;
这里的配置是当前面设置的定时器时钟为SystemCoreClock的情况(这里就是对应AHB的频率2,000,000Hz)。clk是频率,比如clk为10,000(1MHz,表示定时器每1us计数一次),presaler = 199。
3.3 设置计数方式
计数方式分为向上计数、向下计数、中央对齐三种方式。这3种方式由控制寄存器 0 (TIMERx_CTL0) 的CAM[1:0]和DIR选择。
默认采用向上计数。
3.3.1 向上计数
计数器从0计数到自动加载值,然后重新从0开始计数并且产生一个计数器溢出事件。
CAM[1:0] = 0b00,DIR = 0即
timer_initpara.alignedmode = TIMER_COUNTER_EDGE;
timer_initpara.counterdirection = TIMER_COUNTER_UP;
3.3.2 向下计数
计数器从自动装入的值开始向下计数到0,然后从自动装入的值重新开始,并产生一个计数器溢出事件。
CAM[1:0] = 0b00,DIR = 1即
timer_initpara.alignedmode = TIMER_COUNTER_EDGE;
timer_initpara.counterdirection = TIMER_COUNTER_DOWN;
3.3.3 中央对齐
计数器从0开始计数到自动装入的值 - 1,然后向下计数到1,然后再从0开始重新计数。中央对齐只用在通道设置为输出的情况。
溢出事件有3种方式,由CAM[1:0]决定
#define TIMER_COUNTER_CENTER_DOWN CTL0_CAM(1)
#define TIMER_COUNTER_CENTER_UP CTL0_CAM(2)
#define TIMER_COUNTER_CENTER_BOTH CTL0_CAM(3)
timer_initpara.counterdirection = TIMER_COUNTER_CENTER_DOWN;
timer_initpara.counterdirection = TIMER_COUNTER_CENTER_UP;
timer_initpara.counterdirection = TIMER_COUNTER_CENTER_BOTH;
3.4 设置时钟分频
timer_initpara.clockdivision = TIMER_CKDIV_DIV1;
3.5 设置自动重载值
timer_initpara.period = period;
4. 通道设定
并不是所有定时器有通道,每个定时器最多4路通道。定时器0和7属于高级定时器,常用于PWM控制电机。一共有32个通道,枚举如下:
enum
{
HW_TIMER_CH_0 = 0, //TIMER0_CH0:PE9/PA8
HW_TIMER_CH_1, //TIMER0_CH1:PE11/PA9
HW_TIMER_CH_2, //TIMER0_CH2:PE13/PA10
HW_TIMER_CH_3, //TIMER0_CH3:PE14/PA11
HW_TIMER_CH_4, //TIMER1_CH0:PA0/PA5/PA15/PB8
HW_TIMER_CH_5, //TIMER1_CH1:PA1/PB3/PB9
HW_TIMER_CH_6, //TIMER1_CH2:PA2/PB10
HW_TIMER_CH_7, //TIMER1_CH3:PA3/PB2/PB11
HW_TIMER_CH_8, //TIMER2_CH0:PA6/PC6/PB4
HW_TIMER_CH_9, //TIMER2_CH1:PA7/PC7/PB5
HW_TIMER_CH_10, //TIMER2_CH2:PB0/PC8
HW_TIMER_CH_11, //TIMER2_CH3:PB1/PC9
HW_TIMER_CH_12, //TIMER3_CH0:PD12/PB6
HW_TIMER_CH_13, //TIMER3_CH1:PD13/PB7
HW_TIMER_CH_14, //TIMER3_CH2:PD14/PB8
HW_TIMER_CH_15, //TIMER3_CH3:PD15/PB9
HW_TIMER_CH_16, //TIMER4_CH0:PA0/PH10
HW_TIMER_CH_17, //TIMER4_CH1:PA1/PH11
HW_TIMER_CH_18, //TIMER4_CH2:PA2/PH12
HW_TIMER_CH_19, //TIMER4_CH3:PA3/PI0
HW_TIMER_CH_20, //TIMER7_CH0:PC6/PI5
HW_TIMER_CH_21, //TIMER7_CH1:PC7/PI6
HW_TIMER_CH_22, //TIMER7_CH2:PC8/PI7
HW_TIMER_CH_23, //TIMER7_CH3:PC9/PI2
HW_TIMER_CH_24, //TIMER8_CH0:PE5/PA2
HW_TIMER_CH_25, //TIMER8_CH1:PE6/PA3
HW_TIMER_CH_26, //TIMER9_CH0:PF6/PB8
HW_TIMER_CH_27, //TIMER10_CH0:PF7/PB9
HW_TIMER_CH_28, //TIMER11_CH0:PH6/PB14
HW_TIMER_CH_29, //TIMER11_CH1:PH9/PB15
HW_TIMER_CH_30, //TIMER12_CH0:PF8/PA6
HW_TIMER_CH_31, //TIMER13_CH0:PF9/PA7
HW_TIMER_CH_MAX,
};
4.1 通道枚举
void timeGetCH(uint8_t chPort, uint8_t *timer, uint8_t *ch)
{
switch(chPort)
{
case HW_TIMER_CH_0:
case HW_TIMER_CH_1:
case HW_TIMER_CH_2:
case HW_TIMER_CH_3:
*timer = HW_TIMER0;
*ch = chPort - HW_TIMER_CH_0;
break;
case HW_TIMER_CH_4:
case HW_TIMER_CH_5:
case HW_TIMER_CH_6:
case HW_TIMER_CH_7:
*timer = HW_TIMER1;
*ch = chPort - HW_TIMER_CH_4;
break;
case HW_TIMER_CH_8:
case HW_TIMER_CH_9:
case HW_TIMER_CH_10:
case HW_TIMER_CH_11:
*timer = HW_TIMER2;
*ch = chPort - HW_TIMER_CH_8;
break;
case HW_TIMER_CH_12:
case HW_TIMER_CH_13:
case HW_TIMER_CH_14:
case HW_TIMER_CH_15:
*timer = HW_TIMER3;
*ch = chPort - HW_TIMER_CH_12;
break;
case HW_TIMER_CH_16:
case HW_TIMER_CH_17:
case HW_TIMER_CH_18:
case HW_TIMER_CH_19:
*timer = HW_TIMER4;
*ch = chPort - HW_TIMER_CH_16;
break;
case HW_TIMER_CH_20:
case HW_TIMER_CH_21:
case HW_TIMER_CH_22:
case HW_TIMER_CH_23:
*timer = HW_TIMER7;
*ch = chPort - HW_TIMER_CH_20;
break;
case HW_TIMER_CH_24:
case HW_TIMER_CH_25:
*timer = HW_TIMER8;
*ch = chPort - HW_TIMER_CH_24;
break;
case HW_TIMER_CH_26:
*timer = HW_TIMER9;
*ch = chPort - HW_TIMER_CH_26;
break;
case HW_TIMER_CH_27:
*timer = HW_TIMER10;
*ch = chPort - HW_TIMER_CH_27;
break;
case HW_TIMER_CH_28:
case HW_TIMER_CH_29:
*timer = HW_TIMER11;
*ch = chPort - HW_TIMER_CH_28;
break;
case HW_TIMER_CH_30:
*timer = HW_TIMER12;
*ch = chPort - HW_TIMER_CH_30;
break;
case HW_TIMER_CH_31:
*timer = HW_TIMER13;
*ch = chPort - HW_TIMER_CH_31;
break;
default:
*timer = HW_TIMER_MAX;
break;
}
}
4.2 输出捕获初始化
PWM用到的是Timer的输出捕获功能,输出捕获功能可以支持2种PWM模式,PWM0和PWM1。而根据计数模式也可以分为两种PWM 波:EAPWM(边沿对齐PWM)和CAPWM(中央对齐
PWM)。
4.2.1 通道控制寄存器TIMERx_CHCTL0和TIMERx_CHCTL1
4.2.2 通道控制寄存器2 (TIMERx_CHCTL2)
4.2.3 影子寄存器
设置影子寄存器后,用户设定的值->寄存器->影子寄存器->work,未设置的情况下,用户设定的值->寄存器->work,这样影子寄存器起到缓冲的作用。
timer_ocintpara.ocpolarity = TIMER_OC_POLARITY_HIGH;
timer_ocintpara.outputstate = TIMER_CCX_ENABLE;
timer_ocintpara.ocnpolarity = TIMER_OCN_POLARITY_HIGH;
timer_ocintpara.outputnstate = TIMER_CCXN_DISABLE;
timer_ocintpara.ocidlestate = TIMER_OC_IDLE_STATE_LOW;
timer_ocintpara.ocnidlestate = TIMER_OCN_IDLE_STATE_LOW;
timer_channel_output_config(timer, ch, &timer_ocintpara);
timer_channel_output_pulse_value_config(timer, ch, 0);
timer_channel_output_mode_config(timer, ch, TIMER_OC_MODE_PWM0);
timer_channel_output_shadow_config(timer,ch, TIMER_OC_SHADOW_DISABLE);
timer_auto_reload_shadow_enable(timer);
/* TIMERx enable */
timer_enable(timer);
5. 设置占空比
*((uint32_t *)&TIMER_CH0CV(timer) + ch) = ((TIMER_CAR(timer) + 1) * duty) / 100;
占空比的值从0到100。