• 正文
  • 相关推荐
申请入驻 产业图谱

CW32L012/F030灵眸X1智能小车——板载WS2812驱动示例

2025/12/30
248
加入交流群
扫码加入
获取工程师必备礼包
参与热点资讯讨论

一、WS2812介绍

WS2812是一种广泛使用的地址可控制的RGB LED模块,其内置驱动电路控制芯片,允许用户通过单线信号控制多个LED的颜色和亮度。以下是WS2812模块的一些主要特点和应用:

主要特点

单线控制: WS2812模块通过单一数据线进行控制,简化了连接线的复杂度。

地址可控: 每个WS2812 LED都有独立的地址,这意味着你可以分别控制每个LED的颜色和亮度,适合制作动态效果。

多彩显示: 支持全彩显示,通常可以混合红色、绿色和蓝色三基色,产生多种颜色。

链式连接: 支持多颗WS2812 LED串联,可以方便地扩展LED的数量,只需将下一颗LED的数据线连接到前一颗LED上。

高亮度和高密度: WS2812 LED具有较高的亮度,可以在较大面积上提供均匀的光效,适合室内外装饰和显示。

控制精度: 通常提供256级亮度(8位)和1670万种颜色选择,确保丰富的视觉效果。

控制板上的WS2812部分如下图:

原理图

主控制板上WS2812模块的接线图如下:

可以看到一共有八个模块级联在一起,并且由PA12控制。

通信原理

WS2812的数据协议采用单线归零码的通讯方式,支持串行级联接口,能通过一根信号线完成数据的接收与解码。每个灯就是一个像素点,每个像素点的三基色颜色可实现256级亮度显示,完成16777216种颜色的全真色彩显示。

像素点在上电复位以后,DIN端接受从控制器传输过来的数据,首先送过来的24bit数据被第一个像素点提取后,送到像素点内部的数据锁存器,剩余的数据经过内部整形处理电路整 形放大后通过DO端口开始转发输出给下一个级联的像素点,每经过一个像素点的传输,信号减少24bit。像素点采用自动整形转发技术,使得该像素点的级联个数不受信号传送的限制,仅受限信号传输速度要求。

控制方式

因为使用的是单总线,一根线完成一个灯要显示的24位颜色数据,是通过高低电平的时间长度来确定发送的是什么数据。24位的数据结构见下图。

其中G代表三色中的绿色,R代表三色中的红色,B表示三色中的蓝色。例如想要只显示红色则发送 0X00FF00即可。

控制时序

发送24位颜色数据,是通过高低电平的时间长度来确定发送的是0还是1。

发送一位数据0,需要总线拉高T0H的时间再拉低T0L的时间,WS2812才会自动识别该数据是0。

发送一位数据1,需要总线拉高T1H的时间再拉低T1L的时间,WS2812才会自动识别该数据是1。

二、驱动代码编写

WS2812的驱动方法有很多种,定时器DMA,SPI+DMA,软件模拟等,我们这里选择软件模拟时序的方式来驱动。

首先初始化GPIO口,将PA12口配置为推挽输出。注意CW32F030和CW32L012的时钟配置区别。

 

void WS2812_Init(void){        __RCC_GPIOA_CLK_ENABLE();//开启时钟        GPIO_InitTypeDef GPIO_InitStruct;         GPIO_InitStruct.IT=GPIO_IT_NONE;        GPIO_InitStruct.Mode=GPIO_MODE_OUTPUT_PP;//推挽输出        GPIO_InitStruct.Pins=GPIO_PIN_12;        GPIO_InitStruct.Speed=GPIO_SPEED_HIGH;        GPIO_Init(CW_GPIOA, &GPIO_InitStruct);
        RGB_Color_Init();//初始化所有灯}

随后根据时序的高低电平要求,先编写一个ns延时,由于当前使用主频为64mhz,可以算出一个机器指令所需时间大概为1/64=15ns,然后加上GPIO电平翻转时间即可。

 

/**************************400ns延时**************************/void delay_400ns(void)//409{        __nop();__nop();__nop();__nop();__nop();//__nop();__nop();}/**************************800ns延时**************************/void delay_800ns(void)//800{        __nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();        __nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();//        __nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();//        __nop();__nop();}

然后根据时序所需的高低电平时间编写0,1指令

 

/**************************发送1**************************/void RGB_Send1(void){        RGB_H;        delay_800ns();        RGB_L;        delay_400ns();}/**************************发送0**************************/void RGB_Send0(void){        RGB_H;        delay_400ns();        RGB_L;        delay_800ns();}

然后就可以向芯片发送指令了,一个颜色分为RGB三个色域,一个色域为8位,所以我们需要八位数据一起发送,编写如下代码:

 

/**************************发送颜色数据,高位先行**************************/void RGB_send_Data(uint8_t Data){        uint8_t i;        for(i=0;i<8;i++)        {                if(Data & 0x80)                {                        RGB_Send1();                }                else                {                        RGB_Send0();                }                Data<<=1;        }}

这样就可以向芯片发送指定的颜色数据啦,最后在封装一下,我们想要的要求是指定某个灯亮某种颜色,或者指定某个灯熄灭,不能影响到其他灯,所以我们定义一个数组来装下所有灯的颜色数据,到时候只需要改变数组中固定位置的值就可以直接改变颜色了,代码如下:

 

/**************************显示颜色n:第几个灯R:红色G:绿色B:蓝色**************************/void Send_RGB(uint8_t n,uint8_t R,uint8_t G,uint8_t B){        uint8_t i;        RGB_Data[3*n-3]=G;        RGB_Data[3*n-2]=R;        RGB_Data[3*n-1]=B;        for(i=0;i<24;i++)        {                RGB_send_Data(RGB_Data[i]);        }        RGB_Reset();}

最后在main函数编写如下代码(OLED显示代码不在此处列出)

 

int main(void){        OLED_Init();//初始化        OLED_ShowString(1,1,"Hello");//OLED显示字符串        WS2812_Init();        while(1)        {                Send_RGB(1,255,0,0);//255,0,0对应红色                Delay_ms(500);                Send_RGB(1,0,255,0);//255,0,0对应绿色                Delay_ms(500);                Send_RGB(1,0,0,255);//255,0,0对应蓝色                Delay_ms(500);        }}

三、工作现象

在烧写代码之后,我们可以观察到以下现象,OLED第一行第一列显示HELLO,第一个RGB灯每隔500ms转换一次颜色,在红绿蓝三色之间反复切换。

扫码加入QQ群3群| 610403240

相关推荐

登录即可解锁
  • 海量技术文章
  • 设计资源下载
  • 产业链客户资源
  • 写文章/发需求
立即登录

以开放、共享、互助为理念,致力于构建武汉芯源半导体CW32系列MCU生态社区。无论是嵌入式MCU小自还是想要攻破技术难题的工程师,亦或是需求解决方案的产品经理都可在CW32生态社区汲取营养、共同成长。