GD32L23x定时器的使用
呼吸灯是一个很常见的LED点亮模式,显示的效果也很好看。本例通过定时器的PWM功能实现呼吸灯的效果。
定时器的种类和功能
GD32L23x内部包含2大类定时器:
- 定时器TIMER
- 低功耗定时器LPTIMER。低功耗定时器的特点是能在除待机模式以外的其它模式使用,也就是说在低功耗模式也可以使用低功耗定时器,并可通过这个定时器实现唤醒操作。
定时器里分为3类:
- 通用定时器L0,包括定时器1、2
- 通用定时器L1,包括定时器8、11
- 基本定时器,包括定时器5、6
三类定时器的区别如下图所示:
可以看出定时器L0比L1要高级一些。而基本定时器主要是做时基单元。
定时器可以说是非常常用的一个基础外设,用到的主要功能有:
- 最基础的时基单元,如定时产生一个中断或事件
- 输入捕获,如编码器信号的读取
- 输出比较,如PWM功能
实现呼吸灯效果
呼吸灯的效果是LED的亮度逐渐变亮然后再逐渐变暗。实现这个效果的方式就是使用PWM信号驱动LED的引脚,通过改变PWM的占空比,使得LED的亮度发生变化。当PWM的周期频率很高的时候,就不会看出闪烁的效果,而是显示亮度变化的效果。
因此要实现上述的效果,可以将LED接到TIMER的输出引脚上,在输出引脚上产生PWM信号。再通过TIMER的更新中断逐渐改变PWM的占空比。需实现的功能如下:
- TIMER的配置
- 时钟使能
- 时基单元的设置(周期的设置)
- 输出通道设置
- PWM设置
- 定时器和中断使能
- LED的GPIO设置,需设置为复用功能
- 编写中断函数
定时器的初始化
timer_oc_parameter_struct timer_ocintpara;
timer_parameter_struct timer_initpara;
rcu_periph_clock_enable(RCU_TIMER2);
timer_deinit(TIMER2);
//时基单元的配置
timer_struct_para_init(&timer_initpara);
timer_initpara.prescaler = 7;
timer_initpara.alignedmode = TIMER_COUNTER_EDGE;
timer_initpara.counterdirection = TIMER_COUNTER_UP;
timer_initpara.period = 4999;
timer_initpara.clockdivision = TIMER_CKDIV_DIV1;
timer_init(TIMER2, &timer_initpara);
//输出通道的配置
timer_channel_output_struct_para_init(&timer_ocintpara);
timer_ocintpara.ocpolarity = TIMER_OC_POLARITY_HIGH;
timer_ocintpara.outputstate = TIMER_CCX_ENABLE;
timer_channel_output_config(TIMER2, TIMER_CH_0, &timer_ocintpara);
timer_channel_output_pulse_value_config(TIMER2, TIMER_CH_0, 25000);
//PWM模式的配置
timer_channel_output_mode_config(TIMER2, TIMER_CH_0, TIMER_OC_MODE_PWM0);
timer_channel_output_shadow_config(TIMER2, TIMER_CH_0, TIMER_OC_SHADOW_DISABLE);
//定时器使能
timer_auto_reload_shadow_enable(TIMER2);
timer_enable(TIMER2);
//中断的设置
nvic_irq_enable(TIMER2_IRQn,0);
timer_interrupt_enable(TIMER2,TIMER_INT_UP);
LED引脚的设置
注意LED引脚接到定时器的输出引脚,因此需要将GPIO设置为复用模式。通过数据手册可知PC6的复用功能AF1是定时器2的通道0。
#define LED1_PORT GPIOC
#define LED1_PIN GPIO_PIN_6
gpio_mode_set(LED1_PORT, GPIO_MODE_AF, GPIO_PUPD_NONE, LED1_PIN);
gpio_output_options_set(LED1_PORT, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, LED1_PIN);
gpio_af_set(LED1_PORT, GPIO_AF_1, LED1_PIN);
中断函数
void TIMER2_IRQHandler(void)
{
static uint32_t pulse = 0,state = 0;
if(timer_flag_get(TIMER2,TIMER_FLAG_UP) == SET){
timer_channel_output_pulse_value_config(TIMER2,TIMER_CH_0,pulse);
if(state == 0){
pulse += 3;
if(pulse >= 4999){
pulse = 4999;
state = 1;
}
}else{
pulse -= 3;
if(pulse < 3){
pulse = 0;
state = 0;
}
}
timer_flag_clear(TIMER2,TIMER_FLAG_UP);
}
}
最后的效果