【GD32L233C-START测评】WS2812B显示驱动
[复制链接]
本帖最后由 jinglixixi 于 2022-1-30 10:17 编辑
WS2812B彩色灯带和灯环是一种可以渲染环境氛围的器件,由于它是一种印制在软性材料上的串行器件,因此在不考虑信号损耗的情况下,可以视为不受长度的选择。
使用GD32L233C-START开发板按其时序要求即可驱动该器件的工作,并控制点亮灯位的个数及色彩等,见图1至图8所示。
图1 驱动单个灯位
图2 驱动7个灯位
图3 显示蓝色效果
图4 显示绿色效果
图5 显示粉色效果
图6显示白色效果
图7 显示亮彩效果
图8 显示重彩效果
由于WS2812B是一种单总线的串行器件,故除了2个电源引脚外,它只有一个信号输入引脚。
为此分配PB10来与该引脚连接,所作的定义如下:
#define WS2812B_GPIO_CLK RCU_GPIOB
#define WS2812B_GPIO_PORT GPIOB
#define WS2812B_GPIO_PIN GPIO_PIN_10
WS2812B的初始化函数则为:
void WS2812B_Init(void)
{
rcu_periph_clock_enable(WS2812B_GPIO_CLK);
gpio_mode_set(WS2812B_GPIO_PORT, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, WS2812B_GPIO_PIN);
gpio_output_options_set(WS2812B_GPIO_PORT, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, WS2812B_GPIO_PIN);
}
此外,WS2812B在传输数据时是按照电平信号与时序的长短来确定,依GD32L233C-START开发板的工作频率,其传输数据的相关函数为:
static void WS2812B_Write0(void)
{
GPIO_BOP(WS2812B_GPIO_PORT) = WS2812B_GPIO_PIN;
__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();
GPIO_BC(WS2812B_GPIO_PORT) = WS2812B_GPIO_PIN;
__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();
__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();
__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();
__nop();__nop();__nop();
}
static void WS2812B_Write1(void)
{
GPIO_BOP(WS2812B_GPIO_PORT) = WS2812B_GPIO_PIN;
__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();
__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();
__nop();__nop();__nop();__nop();__nop();
GPIO_BC(WS2812B_GPIO_PORT) = WS2812B_GPIO_PIN;
__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();
__nop();__nop();__nop();__nop();
}
按字节传输数据的函数则为:
static void WS2812B_WriteByte(uint8_t Data)
{
for(uint8_t i = 0; i < 8; i++)
{
if(Data & (0x80 >> i))
{
WS2812B_Write1();
}
else
{
WS2812B_Write0();
}
}
}
由于WS2812B是一个全彩的显示器件,故在一个灯位上包含有RGB这3种基本色彩,并有255等级的亮度,为此在控制一个灯位时,需要传输24位数据,相关的处理函数为:
static void WS2812B_Write24Bits(uint8_t R, uint8_t G, uint8_t B)
{
WS2812B_WriteByte(G);
WS2812B_WriteByte(R);
WS2812B_WriteByte(B);
}
以7个灯位的WS2812B为例,其全部显示函数的函数为:
static void WS2812B_DisplayAllRed(void)
{
uint8_t i = 0;
for(i = 0; i < 7; i++)
{
WS2812B_Write24Bits(255, 0, 0);
}
}
有了以上函数的支持,就不愁产生各种变化莫测的灯光效果了,实现红绿蓝3种色彩轮流切换的主程序为:
int main(void)
{
systick_config();
rcu_periph_clock_enable(RCU_GPIOB);
WS2812B_Init();
while(1)
{
WS2812B_DisplayAllRed();
delay_1ms(500);
WS2812B_DisplayAllGreen();
delay_1ms(500);
WS2812B_DisplayAllBlue();
delay_1ms(500);
WS2812B_DisplayAll();
delay_1ms(500);
}
}
春节即将到来,就让缤纷的色彩来伴随大家进入一个新的起点,也祝大家新春快乐,事事如意!
|