WS2812彩色灯驱动代码

·23·1 分钟阅读
嵌入式开发

ws2812.h

#ifndef __WS2812_H__
#define __WS2812_H__

#include "SYSCFG.h"
#include "utils.h"

#define WS2812_LED_NUM    1U

#define WS2812_PIN_HIGH   (RA2 = 1)
#define WS2812_PIN_LOW    (RA2 = 0)

void WS2812_Init(void);
void WS2812_Write_Byte(uint8_t byte);
void WS2812_Write_RGB(uint8_t r, uint8_t g, uint8_t b);
void WS2812_Reset(void);
void WS2812_Clear(void);
void WS2812_Manage(void);

#endif

ws2812.c

注意WS2812时序,不然WS2812很有可能一直显示白色

#include "ws2812.h"

uint8_t led_color_index = 0;

/*-------------------------------------------------
 * 函数名:WS2812_Init
 * 功能:  WS2812初始化,配置PA2为输出引脚
 * 输入:  无
 * 输出:  无
 --------------------------------------------------*/
void WS2812_Init(void)
{
    TRISA &= ~(1 << 2);
    WS2812_PIN_LOW;
}

/*-------------------------------------------------
 * 函数名:WS2812_Write_Byte
 * 功能:  向WS2812写入一个字节数据
 *         WS2812时序:T0H≈0.35us, T1H≈0.9us, T0L≈0.9us, T1L≈0.35us
 *         高位在前,GRB顺序
 *         系统时钟16MHz / 2T
 * 输入:  byte - 要写入的字节数据
 * 输出:  无
 --------------------------------------------------*/
void WS2812_Write_Byte(uint8_t byte)
{
    uint8_t i;
    for (i = 0; i < 8; i++)
    {
        if (byte & 0x80)
        {
            WS2812_PIN_HIGH;
            NOP();
            NOP();
            NOP();
            NOP();
            NOP();
            NOP();
            WS2812_PIN_LOW;
            NOP();
            NOP();
        }
        else
        {
            WS2812_PIN_HIGH;
            NOP();
            WS2812_PIN_LOW;
            NOP();
            NOP();
            NOP();
            NOP();
            NOP();
            NOP();
        }
        byte <<= 1;
    }
}

/*-------------------------------------------------
 * 函数名:WS2812_Write_RGB
 * 功能:  向WS2812写入RGB颜色数据
 *         WS2812数据格式:GRB(绿、红、蓝)
 * 输入:  r - 红色分量 (0-255)
 *         g - 绿色分量 (0-255)
 *         b - 蓝色分量 (0-255)
 * 输出:  无
 --------------------------------------------------*/
void WS2812_Write_RGB(uint8_t r, uint8_t g, uint8_t b)
{
    uint8_t gie;

    gie = GIE;
    GIE = 0;

    WS2812_Write_Byte(g);
    WS2812_Write_Byte(r);
    WS2812_Write_Byte(b);

    GIE = gie;
}

/*-------------------------------------------------
 * 函数名:WS2812_Reset
 * 功能:  发送WS2812复位信号(低电平>50us)
 * 输入:  无
 * 输出:  无
 --------------------------------------------------*/
void WS2812_Reset(void)
{
    WS2812_PIN_LOW;
    Delay_Us(100);
}

/*-------------------------------------------------
 * 函数名:WS2812_Clear
 * 功能:  清除所有LED(设置为全黑)
 * 输入:  无
 * 输出:  无
 --------------------------------------------------*/
void WS2812_Clear(void)
{
    WS2812_Write_RGB(0, 0, 0);
    WS2812_Reset();
}

void WS2812_Manage(void)
{
    switch (led_color_index)
    {
    case 0:
        WS2812_Write_RGB(255, 0, 0);
        WS2812_Reset();
        break;
    case 1:
        WS2812_Write_RGB(0, 255, 0);
        WS2812_Reset();
        break;
    case 2:
        WS2812_Write_RGB(0, 0, 255);
        WS2812_Reset();
        break;
    default:
        break;
    }
    led_color_index = (led_color_index + 1) % 3;
}