WS2812B 驱动程序

关键词:WS2812 ,STM32G030F6

说 明:本代码用于驱动 16 个RGB LED(WS2812 )模块,可以按16个预定颜色的流水显示,

使用RT-Thread RTOS 基于STM32G030F6 最小系统板的 ws2812 驱动工程。

        WS2812是一个集控制电路与发光电路于一体的外控LED光源,外形一般为5050封装,每个LED灯珠为一个像素点,支持RGB无极调色,同时每颗灯珠内部集成有数字接口数据锁存信号整形放大驱动电路,还包含有高精度的内部振荡器和可编程定电流控制部分,整个 LED 模组只需要3条线即可驱动,VCC,GND,DATA, LED 模组上的所有LED都串在一条数据线上,所以只需要使用1条IO即可驱动。

驱动效果,彩色渐变循环显示

WS2812B 驱动程序_第1张图片

1.开发板图片

WS2812B 驱动程序_第2张图片

2.开发板与WS2812B 连接图

16位 WS2812 5050 RGB LED 智能全彩RGB灯环开发板

3.附带工程的编译器 RT-Thread Studio

WS2812B 驱动程序_第3张图片

4.驱动代码

/*
 * Copyright (c) 2006-2020, RT-Thread Development Team
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * Change Logs:
 * IO 直接数据输出模式控制 ws2812B
 * 说明:本代码用于驱动 16 个RGB LED模块,可以按16个预定颜色的流水显示
 */

#include "user_cfg.h"
#define RGBLED_GPIOX             GPIOA         /* LED驱动IO */
#define RGBLED_PIN               GPIO_PIN_3    /* LED驱动IO */
#define LED_NUM                  16            /* LED数量 */
//#define RGBLED     GET_PIN(A, 3)

/* STM32F103 系列 IO 输出控制,采用直接寄存器操作方法,这样可以做到IO的控制速度最大化 */

/*方式1:(72M主频)BSRR 只写寄存器:既能控制管脚为高电平,也能控制管脚为低电平。对寄存器高 16bit 写1 对应管脚为低电平,对寄存器低16bit写1对应管脚为高电平。写 0 ,无动作*/
//#define LED1(X) X? (GPIOB->BSRR |= (0X00000001<<7)):(GPIOB->BSRR |= (0X00000001<<23))  /* 控制 PB7 输出1 或者 0  ,最小脉宽 250ns*/

/*方式2:(72M主频)ODR寄存器可读可写:既能控制管脚为高电平,也能控制管脚为低电平。管脚对应位写1 gpio 管脚为高电平,写 0 为低电平*/
//#define LED1(X) X? (GPIOB->ODR |= (0X01<<7)):(GPIOB->ODR &=~ (0X01<<7))         /* 控制 PB7 输出1 或者 0 ,最小脉宽 250ns */
//#define LED1(X) X? (GPIOA->ODR |= (0X0001<<12)):(GPIOA->ODR &=~ (0X0001<<12))   /* 控制 PA12 输出1 或者 0 ,最小脉宽 250ns */

/* 方式2.1:(72M主频)以下是在方式2的基础上,直接用移位和取反的结果,省去了移位和取反的操作时间,示波器测量对比,IO的翻转时间和方式2没有明显变化 */
//#define RGBLED_1  GPIOA->ODR |= 0X08  /*  控制 PB3 输出1 或者 0 ,最小脉宽 243.6ns */
//#define RGBLED_0  GPIOA->ODR &= 0XF7

#define RGBLED_1  HAL_GPIO_WritePin(RGBLED_GPIOX,RGBLED_PIN, 1)
#define RGBLED_0  HAL_GPIO_WritePin(RGBLED_GPIOX,RGBLED_PIN, 0)

//#define RGBLED_1   LED1(1)
//#define RGBLED_0   LED1(0)


/*方式3:(72M主频)使用RT Thread 的 IO 控制函数,控制IO翻转的时间*/
//#define RGBLED_1   rt_pin_write(RGBLED, 1)  /* 最小脉宽 3.1us */
//#define RGBLED_0   rt_pin_write(RGBLED, 0)


/* 定义LED要显示的16个颜色 */
char count = 0;  /* 计数变量,用于旋转跑马灯计数用 */
char color_rgb[16][3] = {{255,182,193},\
                         {255, 20,147},\
                         {255,  0,255},\
                         {  0,  0,255},\
                         { 30,144,255},\
                         {  0,255,255},\
                         {  0,250,154},\
                         { 50,205,50 },\
                         {255,255,0  },\
                         {255,165,0  },\
                         {255,140,0  },\
                         {255, 69,0  },\
                         {250,128,114},\
                         {255,  0,0  },\
                         {128,  0,0  },\
                         {255,255,255},\
                                        };


void RGB_Init(void)
{
    GPIO_InitTypeDef GPIO_InitStruct = {0};

    /* GPIO Ports Clock Enable */
    __HAL_RCC_GPIOA_CLK_ENABLE();


    /*Configure GPIO pin Output Level */
    HAL_GPIO_WritePin(RGBLED_GPIOX,RGBLED_PIN, GPIO_PIN_RESET);

    /*Configure GPIO pin : PB0 */
    GPIO_InitStruct.Pin = RGBLED_PIN;
    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
    HAL_GPIO_Init(RGBLED_GPIOX, &GPIO_InitStruct);

}


/* 复位   80us低电平 */
void RGB_LEDReset()
{
    RGBLED_0;
    rt_hw_us_delay(80);
}


/* RGB写一个字节 */
void RGB_WriteByte(char dat)
{
  char i;
    for(i= 0;i<8;i++)
    {
        dat <<= i;
      if(dat & 0x80) // 判断最高位
        {
          RGBLED_1;
          RGBLED_1;
          RGBLED_0;
        }
        else
        {
          RGBLED_1;
          RGBLED_0;
          RGBLED_0;
        }
    }

}

/* 输出LED数据 */
void RGB_ColorSet(char red,char green,char blue)
{
    RGB_WriteByte(green);
    RGB_WriteByte(red);
    RGB_WriteByte(blue);
}


/* 设置 并输出 LED 数据*/
void RGB_RandomColor(uint8_t i)
{
     char red,green,blue;
     uint8_t j = 0;

     j = count + i;
     if (j >= LED_NUM)
     {
        j = j - (LED_NUM - 1);
     }

     red   = color_rgb[j][0];
     green = color_rgb[j][1];
     blue  = color_rgb[j][2];

     RGB_ColorSet(red,green,blue); /*输出LED数据*/

}
/* 关闭 i 个 LED */
void RGB_RandomColor_off(void)
{
     char red,green,blue;

     red = 0;
     green = 0;
     blue = 0;

     RGB_ColorSet(red,green,blue);

}

/* 点亮 i 个 LED */
void RGB_RandomColor4(uint8_t i)
{
    for (uint8_t var = 0; var < i; ++var)
    {
        if (i)
        {
            RGB_RandomColor(var);
        }
        else
        {
            RGB_RandomColor_off();
        }

    }

    RGB_LEDReset();
    if (count < LED_NUM -1)
    {
        ++count;
    }
    else
    {
        count = 0;
    }
}


/* 线程 rgbled_test 的入口函数 */

static void rgbled_entry(void *param)
{
    RGB_Init();
    RGBLED_0;

    while (1)
    {
       RGB_RandomColor4(LED_NUM);
       rt_thread_mdelay(1000);
    }
}

/*线程创建函数*/
int rgbled_test(void)
{
    rt_thread_t tid1;                                    /*创建线程控制块指针来接收线程创建函数的返回值,目的是通过返回值判断线程是否创建ok*/

    /* 创建线程 1,名称是 rgbled_test,入口是 rgbled_entry*/

    tid1 = rt_thread_create("rgbled_test",              /*线程名称,系统打印线程时会显示这个线程的名字*/
                            rgbled_entry,               /*线程入口函数,入口函数函数名*/
                            RT_NULL,                    /*入口参数*/
                            500,                        /*设置内存堆栈大小*/
                            9,                          /*设置优先级*/
                            500);                       /*时间片参数,时间片是在有多个相同优先级线程时,这个线程每次被执行多少个时间片*/


    /* 如果获得线程控制块,启动这个线程 */
    if (tid1 != RT_NULL)
        rt_thread_startup(tid1);
    return RT_EOK;
}
//INIT_APP_EXPORT(rgbled_test);

5.测试工程链接点击下载

测试工程

你可能感兴趣的:(驱动调试,单片机,嵌入式硬件)