WS2812灯带
主控芯片GD32F303
一、ws2812灯带
1、产品特点
- 数据发送速度可达800Kbps
- 串行级联接口, 能通过一根信号线完成数据的接收与解码
- 任意两点传传输距离在不超过3米时无需增加任何电路。
- 内置信号整形电路, 任何一个像素点收到信号后经过波形整形再输出, 保证线路波形畸变不会累加
- 内置上电复位和掉电复位电路
2、确定编码格式
1)BIT0
周期 :T0H + T0L = 1/800k = 1.25μs
波形占空比 :T0H /1.25 *100% = 32%
2)BIT1
周期 : T1H + T1L = 1/800k = 1.25μs ,
波形占空比 : T1L / 1.25 * 100% = 1-32% = 78%
3、数据传输
二、采用DMA+PWM的方式驱动
1、timer配置
-
根据定时器的时钟频率,设置相应的预分频系数及重装载值
本文定时器时钟频率:112M、预分频系数:1、自动重装载值:69 ;
频率 = 时钟频率/(预分频系数+1)/(自动重装载值+1) = 112/2/70 =0.8M = 800K
周期 = 1/频率 = 1.25μs
-
周期为1.25μs 的PWM输出,开启DMA
/********************************************************************************************
* Function Name : bsp_timerPwm_led_init
* Description : 定时器pwm timer4_ch1
* Input : void
* Output : void
* Return : none
********************************************************************************************/
void bsp_timerPwm_lights(void)
{
#define TIM_PWM TIMER4
timer_oc_parameter_struct timer_ocintpara;
timer_parameter_struct timer_initpara;
//clock
rcu_periph_clock_enable(RCU_GPIOA);
rcu_periph_clock_enable(RCU_TIMER4);
rcu_periph_clock_enable(RCU_AF);
//GPIO
gpio_init(GPIOA,GPIO_MODE_AF_PP,GPIO_OSPEED_50MHZ,GPIO_PIN_1);
// gpio_init(GPIOA,GPIO_MODE_AF_PP,GPIO_OSPEED_50MHZ,GPIO_PIN_2);
// gpio_init(GPIOA,GPIO_MODE_AF_PP,GPIO_OSPEED_50MHZ,GPIO_PIN_3);
//TIMER
timer_deinit(TIM_PWM);
timer_initpara.prescaler = 1;
timer_initpara.alignedmode = TIMER_COUNTER_EDGE;
timer_initpara.counterdirection = TIMER_COUNTER_UP;
timer_initpara.period = 69;
timer_initpara.clockdivision = TIMER_CKDIV_DIV1;
timer_initpara.repetitioncounter = 0;
timer_init(TIM_PWM, &timer_initpara);
timer_ocintpara.outputstate = TIMER_CCX_ENABLE;
timer_ocintpara.outputnstate = TIMER_CCXN_DISABLE;
timer_ocintpara.ocpolarity = TIMER_OC_POLARITY_HIGH;
timer_ocintpara.ocnpolarity = TIMER_OCN_POLARITY_HIGH;
timer_ocintpara.ocidlestate = TIMER_OC_IDLE_STATE_HIGH;
timer_ocintpara.ocnidlestate = TIMER_OCN_IDLE_STATE_LOW;
timer_channel_output_config(TIM_PWM, TIMER_CH_1, &timer_ocintpara);
timer_channel_output_pulse_value_config(TIM_PWM, TIMER_CH_1, 0);
timer_channel_output_mode_config(TIM_PWM, TIMER_CH_1, TIMER_OC_MODE_PWM0);
timer_channel_output_shadow_config(TIM_PWM, TIMER_CH_1, TIMER_OC_SHADOW_DISABLE);
timer_dma_enable(TIM_PWM,TIMER_DMA_CH1D);
timer_channel_dma_request_source_select( TIMER4,TIMER_DMAREQUEST_UPDATEEVENT);
/* auto-reload preload enable */
timer_auto_reload_shadow_enable(TIM_PWM);
/* auto-reload preload enable */
timer_enable(TIM_PWM);
}
2、DMA配置
/********************************************************************************************
* Function Name : dma1_ch3_config
* Description : DMA1_CH3 配置---Timer4_ch1
* Input : void
* Output : void
* Return : none
********************************************************************************************/
void dma1_ch3_config(void)
{
dma_parameter_struct dma_init_struct;
//clock
rcu_periph_clock_enable(RCU_DMA1);
//DMA
dma_deinit(DMA1, DMA_CH3);
dma_init_struct.direction = DMA_MEMORY_TO_PERIPHERAL;
dma_init_struct.memory_addr = (uint32_t)(ws2812_rgb_buf);
dma_init_struct.memory_inc = DMA_MEMORY_INCREASE_ENABLE;
dma_init_struct.memory_width = DMA_MEMORY_WIDTH_8BIT;
dma_init_struct.number = (WS2812_NUM+20)*24;
dma_init_struct.periph_addr = (uint32_t)(&TIMER_CH1CV(TIMER4));
dma_init_struct.periph_inc = DMA_PERIPH_INCREASE_DISABLE;
dma_init_struct.periph_width = DMA_PERIPHERAL_WIDTH_16BIT;
dma_init_struct.priority = DMA_PRIORITY_ULTRA_HIGH;
dma_init(DMA1, DMA_CH3, &dma_init_struct);
/* configure DMA mode */
dma_circulation_enable(DMA1, DMA_CH3);
/* enable DMA channel */
dma_channel_enable(DMA1, DMA_CH3);
}
三、灯效
1、点亮
#define WS2812_NUM (100)
#define BIT0 23 /*23/70 = 32.86%*/
#define BIT1 47 /*47/70 = 67.14%*/
uint8_t ws2812_rgb_buf[WS2812_NUM+20][24]; //后10个二维数组用于更新锁存器,1.25μs*10*24 = 300μs
/**/
/********************************************************************************************
* Function Name : clean_all_color
* Description : 清除所有灯珠的颜色(关闭灯珠)
* Input : None
* Output : void
* Return : none
********************************************************************************************/
static void clean_all_color(void)
{
uint8_t i = 0, j = 0;
for (i = 0; i < WS2812_NUM; i++) {
for (j = 0; j < 8; j++)
ws2812_rgb_buf[i+10][j] = (0x00 & (0x01 << (7 - j))) ? BIT_1 : BIT_0;
}
for (i = 0; i < WS2812_NUM; i++) {
for (j = 0; j < 8; j++)
ws2812_rgb_buf[i+10][j+8] = (0x00 & (0x01 << (7 - j))) ? BIT_1 : BIT_0;
}
for (i = 0; i < WS2812_NUM; i++) {
for (j = 0; j < 8; j++)
ws2812_rgb_buf[i+10][j+16] = (0x00 & (0x01 << (7 - j))) ? BIT_1 : BIT_0;
}
}
/********************************************************************************************
* Function Name : clean_one_color
* Description : 清除某个灯珠的颜色(关闭灯珠)
* Input : which 选择第几个灯珠
* Output : void
* Return : none
********************************************************************************************/
static void clean_one_color(uint8_t which)
{
uint8_t i = 0;
for (i = 0; i < 8; i++)
ws2812_rgb_buf[which+10][i] = (0x00 & (0x01 << (7 - i))) ? BIT_1 : BIT_0;
for (i = 0; i < 8; i++)
ws2812_rgb_buf[which+10][i+8] = (0x00 & (0x01 << (7 - i))) ? BIT_1 : BIT_0;
for (i = 0; i < 8; i++)
ws2812_rgb_buf[which+10][i+16] = (0x00 & (0x01 << (7 - i))) ? BIT_1 : BIT_0;
}
* Function Name : set_ws2812_single_color
* Description : 将所有灯珠设置为同一种颜色
* Input :
uint8_t red
uint8_t green
uint8_t blue
* Output : void
* Return : none
********************************************************************************************/
static void set_ws2812_single_color( uint8_t red, uint8_t green, uint8_t blue)
{
uint8_t i = 0, j = 0;
memset(ws2812_rgb_buf, 0, sizeof(ws2812_rgb_buf));
for (i = 0; i < WS2812_NUM ; i++) {
for (j = 0; j < 8; j++)
ws2812_rgb_buf[i+10][j] = (green & (0x01 << (7 - j))) ? BIT_1 : BIT_0;
}
for (i = 0; i < WS2812_NUM ; i++) {
for (j = 0; j < 8; j++)
ws2812_rgb_buf[i+10][j+8] = (red & (0x01 << (7 - j))) ? BIT_1 : BIT_0;
}
for (i = 0; i < WS2812_NUM ; i++) {
for (j = 0; j < 8; j++)
ws2812_rgb_buf[i+10][j+16] = (blue & (0x01 << (7 - j))) ? BIT_1 : BIT_0;
}
// ws2812_enable();
}
/********************************************************************************************
* Function Name : ws2812_process
* Description : ws2812模块处理函数
* Input : void
* Output : void
* Return : none
********************************************************************************************/
void ws2812_process(void)
{
static uint8_t firstFlag = 0;
if(!firstFlag)
{
/******** 定时器配置PWM********/
bsp_timerPwm_lights();
/********DMA_CH3配置及使能********/
dma1_ch3_config();
}
set_ws2812_single_color(255,255,255);
}