GD32L233C TRNG 处理和PWM配置(II)
[复制链接]
前几天发了TRNG的生成调试,今天继续PWM使用,做智能LED灯要控制LED生成不同的颜色,离不开PWM,通过PWM控制RGBW不同占空比就可以使LED灯出现不同的颜色和等效,比如颜色渐变,灯的呼吸,甚至模拟出不同太阳的生物节律灯,让LED跟随日出日落的颜色变化成为可能。现在就讲如何实现PWM配置。PWM要占用timer,为了减少定时器的占用,尽可能选择一个timer可以控制多个GPIO的定时器,查看GD233C的SPEC,可以看到Timer2 可以支持4路PWM输出,正好符合LED灯RGBW四色LED的控制。
选择好定时器后可以开始配置定时器
void timer_config(void)
{
timer_parameter_struct timer_struct;
timer_oc_parameter_struct timer_ocintpara;
rcu_periph_clock_enable(RCU_TIMER6);
timer_struct_para_init(&timer_struct );
timer_struct.period =999;//1000
timer_struct.prescaler = 47;//63;//TIMER_EXT_TRI_PSC_DIV8;
timer_struct.counterdirection = TIMER_COUNTER_UP;
timer_struct.alignedmode = TIMER_COUNTER_EDGE;
timer_struct.clockdivision = TIMER_CKDIV_DIV1;
timer_deinit(TIMER6);
timer_init(TIMER6,&timer_struct);
//NVIC_SetPriority(TIMER6_IRQn, 0x02U);
timer_interrupt_enable(TIMER6,TIMER_INT_UP);
nvic_irq_enable(TIMER6_IRQn, 0x00U);
timer_enable(TIMER6);
rcu_periph_clock_enable(RCU_TIMER2);
timer_struct_para_init(&timer_struct );
timer_struct.period = 255;//255;//1000
timer_struct.prescaler = 479;//639;//TIMER_EXT_TRI_PSC_DIV8;
timer_struct.counterdirection = TIMER_COUNTER_UP;
timer_struct.alignedmode = TIMER_COUNTER_EDGE;
timer_struct.clockdivision = TIMER_CKDIV_DIV1;
timer_channel_output_struct_para_init(&timer_ocintpara);
timer_ocintpara.ocpolarity = TIMER_OC_POLARITY_HIGH;
timer_ocintpara.outputstate = TIMER_CCX_ENABLE;
timer_deinit(TIMER2);
timer_init(TIMER2,&timer_struct);
timer_channel_output_config(TIMER2,TIMER_CH_0,&timer_ocintpara);//PA6 RED
timer_channel_output_config(TIMER2,TIMER_CH_1,&timer_ocintpara);//PA7//GREEN LED1
timer_channel_output_config(TIMER2,TIMER_CH_2,&timer_ocintpara);//PB0 BLUE
timer_channel_output_config(TIMER2,TIMER_CH_3,&timer_ocintpara);//PB1 YELLOW
timer_channel_output_pulse_value_config(TIMER2, TIMER_CH_0, 0);
timer_channel_output_pulse_value_config(TIMER2, TIMER_CH_1, 0);
timer_channel_output_pulse_value_config(TIMER2, TIMER_CH_2, 0);
timer_channel_output_pulse_value_config(TIMER2, TIMER_CH_3, 0);
timer_channel_output_mode_config(TIMER2, TIMER_CH_0, TIMER_OC_MODE_PWM0);
timer_channel_output_mode_config(TIMER2, TIMER_CH_1, TIMER_OC_MODE_PWM0);
timer_channel_output_mode_config(TIMER2, TIMER_CH_2, TIMER_OC_MODE_PWM0);
timer_channel_output_mode_config(TIMER2, TIMER_CH_3, TIMER_OC_MODE_PWM0);
timer_auto_reload_shadow_enable(TIMER2);
timer_enable(TIMER2);
}
按如上配置每路PWMperiod 设置为255,可以实现LED8bit 256级输出,理论上可以产生255X255X255=16,581,375种颜色输出
接下来是封装一个pwm输出接口
void gpio_pwm(xt_rgb duty){
timer_channel_output_pulse_value_config(TIMER2, TIMER_CH_0, duty.rgb_r_pwm);
timer_channel_output_pulse_value_config(TIMER2, TIMER_CH_1, duty.rgb_g_pwm);
timer_channel_output_pulse_value_config(TIMER2, TIMER_CH_2, duty.rgb_b_pwm);
timer_channel_output_pulse_value_config(TIMER2, TIMER_CH_3, duty.rgb_w_pwm);
}
把rgbw 的数据通过一个结构体传递给定时器就可以控制4路LED输出。
网络上的渐变和呼吸LED使用的都是简单的在一个循环通过延时控制pwm递增递减实现,这个只适合最演示效果,要实现渐变和呼吸等效
单独使用一个定时器,通过这个定时器实现更加精准的渐变和呼吸等效,这里采用timer6实现
实现1u秒的延时,通过这个定时器封装一类定时功能的函数,实现定时器开启,定时器失效等功能,这个定时器不是使用简单的delay()功能,执行更高效
搭好以上基础设施后就可以编写灯的各种功能实现渐变开机渐变关机,呼吸等等
举个简单的栗子:
case LIGHT_BLUE:
if(light_state.is_start==XTRUE){
break;
}
if (pdTRUE==result){
target_pwm.rgb_r_pwm=0;//?????
target_pwm.rgb_g_pwm=0;
target_pwm.rgb_b_pwm=PWM(255);
XtimerStop(sg_pwm_timer);
//light_state.cct = 2700;
gradient_time_ms=light_state.gradient_time_ms;
//light_pwm_send(light_pwm);
//time_previous = 0;
}
if (XTRUE==set_pwm(&light_pwm,&target_pwm,&gradient_time_ms,&light_state, &time)){
step =1;
gradient_time_ms=light_state.gradient_time_ms;
light_state_response(light_state);
}
|