打印
[活动]

【G32A1465开发板测评】2.驱动WS2812B色环

[复制链接]
34|0
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
本帖最后由 阿源玩电子 于 2024-12-27 10:30 编辑

#申请原创# #有奖活动# #申请开发板# 一、硬件介绍
1.  WS2812B通常由多个LED组成,每个LED都可以独立控制,常见的连接方式如下:
  • 电源(VCC和GND):WS2812B需要一个稳定的5V电源供电。为了保证色环稳定运行,电源应该足够强大,这里我使用额外的电源对色环进行供电。
  • 控制线:根据开发板的I/O资源,可以选择任意一个GPIO口来控制WS2812B。
2. WS2812B 使用一种基于时间的协议来传输数据。数据通过单线传输,每个数据包包含一个 LED 的颜色信息,数据格式是逐位传输,每个 LED 需要 24 位数据。
  • 每个 LED:需要 24 位数据,分为 3 个字节(8 位每个),对应颜色通道:红色 (R)、绿色 (G)、蓝色 (B),数据顺序为:GRB。
  • 1 个 LED 数据格式:G:8 bits (字节) R:8 bits (字节) B:8 bits (字节)

3. 数据位:WS2812B 的每个数据位都有严格的时序要求,特别是高电平和低电平的时间。
数据的传输基于如下的时序规则

  • 逻辑 1 (高电平)
  • 高电平持续约 0.65 微秒
  • 低电平持续约 1.15 微秒
  • 逻辑 0 (低电平)
  • 高电平持续约 0.20 微秒
  • 低电平持续约 0.55 微秒

通过这种方式,控制信号可以传递 0 和 1,1 和 0 的组合来表示数据。
二、驱动介绍
1. 我准备直接使用PC5,进行翻转来模拟WS2812B时序,定义一个数组用来储存灯珠数据
#define Flow_led_num 26 // 流动LED灯的数量
#define led_data_lenght 24 // WS2812的数据长度
uint8_t Flow_led_buffer[Flow_led_num * led_data_lenght] = {0};
2.初始化GPIOC_5
void Flow_led_init(void)
{
          CLOCK_SYS_ConfigModuleClock(PMC_CLK, NULL);
          PINS_SetMuxModeSel(PMC, 5U, PM_MUX_AS_GPIO);
          PINS_SetPinIntSel(PMC, 5U, PM_DMA_INT_DISABLED);
          PINS_SetPins(GPIOC, 1U << 5U);
          PINS_SetPinDir(GPIOC, 5U, 1U);
}
3.延时函数以及数据发送函数
void delay(uint32_t time) {
    // 精确延时函数,替代 __NOP(),根据系统时钟来控制延时
    for (uint32_t i = 0; i < time; i++) {
        __NOP();
    }
}

void Flow_led_send(void) {
    // 遍历 Flow_led_buffer
    for (int i = 0; i < sizeof(Flow_led_buffer); i++) {
        if (Flow_led_buffer[i]) {
            // 发送 '1'
            GPIOC->PLLOS.reg = 1U << 5U;  // 设置高电平
            delay(9);  // 延时,调节延时以满足硬件时序要求
            GPIOC->PLLOC.reg = 1U << 5U;  // 设置低电平
            delay(3);  // 延时
        } else {
            // 发送 '0'
            GPIOC->PLLOS.reg = 1U << 5U;  // 设置高电平
            delay(3);  // 延时,调节延时以满足硬件时序要求
            GPIOC->PLLOC.reg = 1U << 5U;  // 设置低电平
            delay(9);  // 延时
        }
    }
}

4.HSV转RGB算法
void hsv_to_rgb(float hue, float saturation, float value, uint8_t *r, uint8_t *g, uint8_t *b) {
    float c = value * saturation;  // Chroma
    float x = c * (1 - fabs(fmod(hue / 60.0, 2) - 1));
    float m = value - c;

    float r_prime, g_prime, b_prime;

    if (hue >= 0 && hue < 60) {
        r_prime = c, g_prime = x, b_prime = 0;
    } else if (hue >= 60 && hue < 120) {
        r_prime = x, g_prime = c, b_prime = 0;
    } else if (hue >= 120 && hue < 180) {
        r_prime = 0, g_prime = c, b_prime = x;
    } else if (hue >= 180 && hue < 240) {
        r_prime = 0, g_prime = x, b_prime = c;
    } else if (hue >= 240 && hue < 300) {
        r_prime = x, g_prime = 0, b_prime = c;
    } else {
        r_prime = c, g_prime = 0, b_prime = x;
    }

    *r = (uint8_t)((r_prime + m) * 255);
    *g = (uint8_t)((g_prime + m) * 255);
    *b = (uint8_t)((b_prime + m) * 255);
}
5.色环驱动函数
uint16_t i,j;
uint8_t Colorful_gradient(uint8_t ledNum, uint8_t brightness, uint8_t speed_flow) {
    static float Hue = 0;
    static const float Saturation = 1.0f;
    float Value = brightness / 255.0f;
    static uint32_t time = 0;
    static uint8_t R, G, B;
    static uint32_t RGB;
    static uint8_t num;
        Hue += 0.1f;
        if (Hue >= 360.0f) {
            Hue -= 360.0f;
        }
        time+=100;
        if (time >= 7000) {
            time = 0;
            Hue = 0;
            num++;
        }
        for ( i = 0; i < ledNum; i++) {
            float ledHue = Hue + (float)(i * 360.0f / ledNum) + (float)time / 20.0f;
            if (ledHue >= 360.0f) {
                ledHue -= 360.0f;
            }
            hsv_to_rgb(ledHue, Saturation, Value, &R, &G, &B);
            RGB = ((uint32_t)R << 16) | ((uint32_t)G << 8) | B;
            ws2812_set_index_brightness(RGB, i);
        }
    return 0;
}
6.主函数
int main(void)
{
    SystemCoreClockConfigure(); /* Configure system core clock */
    SystemCoreClockUpdate();    /* Update system core clock info */
    SysTick_Init();
     Flow_led_init();
    while(1)
    {
          Flow_led_send();
          Colorful_gradient(26,10,1);
          SysTick_Delay(10);
    }
}
三、效果

四、总结
     直接使用IO口驱动,本来效果是七彩旋转,结果视频放不上去,没办法展示。





使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

2

主题

8

帖子

0

粉丝