[GD32L233C-START Review] IV. Timer PWM Application to Drive RGB Lights
[Copy link]
Timer PWM is one of the most commonly used peripherals of MCU. GD32L233C has multiple timers and PWM output channels. The timer resources are as follows:
Through pin multiplexing, you can know which IO has PWM function:
The GD32L233C-START development board is said to be compatible with the Arduino Uno interface (the benefit of the Arduino Uno interface is that there are a large number of expansion boards in the Arduino ecosystem that can be plug-and-play), but it is not fully supported. It can only be said that the design of this development board is very poor . The GD32L233C can output PWM with far more than 6 IOs, but the development board does not connect the IO with PWM function to D3, D5, D6, D9, D10, and D11 according to the standard of the Arduino Uno interface... Only D3, D9, and D11 are supported... This means that when the Arduino expansion board needs more than 3 PWM control signals, it cannot be plug-and-play.
In addition, there are several serial ports, so there is no need to reuse the USB debugging serial port on the development board and D0 and D1 of the Arduino Uno interface.
Standard Arduino Uno R3 interface:
To test the PWM function, use Tuya's Arduino Uno R3 compatible RGB expansion board:
Effect of plugging the RGB expansion board into GD32L233C-START
According to the schematic diagram of the GD32L233C-START development board, only PB15, PB0, and PB5 can use PWM. Unfortunately:
Tuya Sandwich (PWM) Lighting Function Board is an LED controller that supports five-way dimming of colored lights. The lighting function board (PWM) can realize five-way lighting functions, with warm light, cold white and RGB lamp beads and corresponding control chips.
- The cool white and warm white control adopts SLM211A DC-DC step-down PWM linear constant current dimming control chip.
- RGB control uses BP168CJ DC-DC step-down PWM linear constant current control chip.
I/O |
illustrate |
PWMC |
Cold white PWM control signal, high level is effective |
PWMW |
Warm white PWM control signal, high level is effective |
PWMR |
RGB red light control signal, high level is effective |
PWMG |
RGB green light control signal, high level is effective |
PWMB |
RGB blue light control signal, high level is effective |
The timers and PWM channels corresponding to the 3 control pins are as follows:
PB15 --- timer11-ch1 pwmR
PB5 --- timer2-ch1 pwmB
PB0 --- timer2-ch2 pwmW
The API design of gd32 is much more comfortable to use than stm32, very concise and easy to use:
main.c test code
#include "gd32l23x.h"
#include "systick.h"
// PB15 --- timer11-ch1 pwmR
// PB5 --- timer2-ch1 pwmB
// PB0 --- timer2-ch2 pwmW
void gpio_config(void)
{
rcu_periph_clock_enable(RCU_GPIOB);
/* TIMER2 & TIMER11 GPIO */
gpio_mode_set(GPIOB, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_0 | GPIO_PIN_5 | GPIO_PIN_15);
gpio_output_options_set(GPIOB, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_0 | GPIO_PIN_5 | GPIO_PIN_15);
gpio_af_set(GPIOB, GPIO_AF_1, GPIO_PIN_0);
gpio_af_set(GPIOB, GPIO_AF_1, GPIO_PIN_5);
gpio_af_set(GPIOB, GPIO_AF_2, GPIO_PIN_15);
}
void timer2_config(void)
{
timer_oc_parameter_struct timer_ocinitpara;
timer_parameter_struct timer_initpara;
/* enable the peripherals clock */
rcu_periph_clock_enable(RCU_TIMER2);
/* deinit a TIMER */
timer_deinit(TIMER2);
/* initialize TIMER init parameter struct */
timer_struct_para_init(&timer_initpara);
/* TIMER2 configuration */
timer_initpara.prescaler = 63;
timer_initpara.alignedmode = TIMER_COUNTER_EDGE;
timer_initpara.counterdirection = TIMER_COUNTER_UP;
timer_initpara.period = 9999;
timer_initpara.clockdivision = TIMER_CKDIV_DIV1;
timer_init(TIMER2, &timer_initpara);
/* initialize TIMER channel output parameter struct */
timer_channel_output_struct_para_init(&timer_ocinitpara);
/* configure TIMER channel output function */
timer_ocinitpara.outputstate = TIMER_CCX_ENABLE;
timer_ocinitpara.ocpolarity = TIMER_OC_POLARITY_HIGH;
timer_channel_output_config(TIMER2, TIMER_CH_1, &timer_ocinitpara);
timer_channel_output_config(TIMER2, TIMER_CH_2, &timer_ocinitpara);
timer_channel_output_pulse_value_config(TIMER2, TIMER_CH_1, 0);
timer_channel_output_pulse_value_config(TIMER2, TIMER_CH_2, 0);
/* CH0 configuration in OC timing mode */
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);
}
void timer11_config(void)
{
timer_oc_parameter_struct timer_ocinitpara;
timer_parameter_struct timer_initpara;
/* enable the peripherals clock */
rcu_periph_clock_enable(RCU_TIMER11);
/* deinit a TIMER */
timer_deinit(TIMER11);
/* initialize TIMER init parameter struct */
timer_struct_para_init(&timer_initpara);
/* TIMER2 configuration */
timer_initpara.prescaler = 63;
timer_initpara.alignedmode = TIMER_COUNTER_EDGE;
timer_initpara.counterdirection = TIMER_COUNTER_UP;
timer_initpara.period = 9999;
timer_initpara.clockdivision = TIMER_CKDIV_DIV2;
timer_init(TIMER11, &timer_initpara);
/* initialize TIMER channel output parameter struct */
timer_channel_output_struct_para_init(&timer_ocinitpara);
/* configure TIMER channel output function */
timer_ocinitpara.outputstate = TIMER_CCX_ENABLE;
timer_ocinitpara.ocpolarity = TIMER_OC_POLARITY_HIGH;
timer_channel_output_config(TIMER11, TIMER_CH_1, &timer_ocinitpara);
timer_channel_output_pulse_value_config(TIMER11, TIMER_CH_1, 0);
/* CH0 configuration in OC timing mode */
timer_channel_output_mode_config(TIMER11, TIMER_CH_1, TIMER_OC_MODE_PWM0);
}
int main(void)
{
systick_config();
gpio_config();
timer2_config();
timer11_config();
while(1)
{
/* enable a TIMER */
timer_enable(TIMER11);
//pwmR test
for(int i =0;i<1000;i++)
{
delay_1ms(2);
timer_channel_output_pulse_value_config(TIMER11, TIMER_CH_1, i*10);
}
for(int i =999;i>0;i--)
{
delay_1ms(2);
timer_channel_output_pulse_value_config(TIMER11, TIMER_CH_1, i*10);
}
timer_channel_output_pulse_value_config(TIMER11, TIMER_CH_1, 0);
timer_disable(TIMER11);
//pwmR end
timer_enable(TIMER2);
//pwmB test
for(int i =0;i<1000;i++)
{
delay_1ms(2);
timer_channel_output_pulse_value_config(TIMER2, TIMER_CH_1, i*10);
}
for(int i =999;i>0;i--)
{
delay_1ms(2);
timer_channel_output_pulse_value_config(TIMER2, TIMER_CH_1, i*10);
}
timer_channel_output_pulse_value_config(TIMER2, TIMER_CH_1, 0);
//pwmB end
//pwmW test
for(int i =0;i<1000;i++)
{
delay_1ms(2);
timer_channel_output_pulse_value_config(TIMER2, TIMER_CH_2, i*10);
}
for(int i =999;i>0;i--)
{
delay_1ms(2);
timer_channel_output_pulse_value_config(TIMER2, TIMER_CH_2, i*10);
}
timer_channel_output_pulse_value_config(TIMER2, TIMER_CH_2, 0);
timer_disable(TIMER2);
//pwmW end
}
}
Driving effect:
|