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

[复制链接]
869|0
 楼主| 阿源玩电子 发表于 2024-12-26 22:23 | 显示全部楼层 |阅读模式
本帖最后由 阿源玩电子 于 2024-12-28 10:48 编辑

#申请原创# #有奖活动# #申请开发板#[url=home.php?mod=space&uid=760190]@21小跑堂 [/url] 一、硬件介绍
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时序,定义一个数组用来储存灯珠数据
  1. #define Flow_led_num 26 // 流动LED灯的数量
  2. #define led_data_lenght 24 // WS2812的数据长度
  3. uint8_t Flow_led_buffer[Flow_led_num * led_data_lenght] = {0};
2.初始化GPIOC_5
  1. void Flow_led_init(void)
  2. {
  3.           CLOCK_SYS_ConfigModuleClock(PMC_CLK, NULL);
  4.           PINS_SetMuxModeSel(PMC, 5U, PM_MUX_AS_GPIO);
  5.           PINS_SetPinIntSel(PMC, 5U, PM_DMA_INT_DISABLED);
  6.           PINS_SetPins(GPIOC, 1U << 5U);
  7.           PINS_SetPinDir(GPIOC, 5U, 1U);
  8. }
3.延时函数以及数据发送函数
  1. void delay(uint32_t time) {
  2.     // 精确延时函数,替代 __NOP(),根据系统时钟来控制延时
  3.     for (uint32_t i = 0; i < time; i++) {
  4.         __NOP();
  5.     }
  6. }

  7. void Flow_led_send(void) {
  8.     // 遍历 Flow_led_buffer
  9.     for (int i = 0; i < sizeof(Flow_led_buffer); i++) {
  10.         if (Flow_led_buffer[i]) {
  11.             // 发送 '1'
  12.             GPIOC->PLLOS.reg = 1U << 5U;  // 设置高电平
  13.             delay(9);  // 延时,调节延时以满足硬件时序要求
  14.             GPIOC->PLLOC.reg = 1U << 5U;  // 设置低电平
  15.             delay(3);  // 延时
  16.         } else {
  17.             // 发送 '0'
  18.             GPIOC->PLLOS.reg = 1U << 5U;  // 设置高电平
  19.             delay(3);  // 延时,调节延时以满足硬件时序要求
  20.             GPIOC->PLLOC.reg = 1U << 5U;  // 设置低电平
  21.             delay(9);  // 延时
  22.         }
  23.     }
  24. }

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

  5.     float r_prime, g_prime, b_prime;

  6.     if (hue >= 0 && hue < 60) {
  7.         r_prime = c, g_prime = x, b_prime = 0;
  8.     } else if (hue >= 60 && hue < 120) {
  9.         r_prime = x, g_prime = c, b_prime = 0;
  10.     } else if (hue >= 120 && hue < 180) {
  11.         r_prime = 0, g_prime = c, b_prime = x;
  12.     } else if (hue >= 180 && hue < 240) {
  13.         r_prime = 0, g_prime = x, b_prime = c;
  14.     } else if (hue >= 240 && hue < 300) {
  15.         r_prime = x, g_prime = 0, b_prime = c;
  16.     } else {
  17.         r_prime = c, g_prime = 0, b_prime = x;
  18.     }

  19.     *r = (uint8_t)((r_prime + m) * 255);
  20.     *g = (uint8_t)((g_prime + m) * 255);
  21.     *b = (uint8_t)((b_prime + m) * 255);
  22. }
5.色环驱动函数
  1. uint16_t i,j;
  2. uint8_t Colorful_gradient(uint8_t ledNum, uint8_t brightness, uint8_t speed_flow) {
  3.     static float Hue = 0;
  4.     static const float Saturation = 1.0f;
  5.     float Value = brightness / 255.0f;
  6.     static uint32_t time = 0;
  7.     static uint8_t R, G, B;
  8.     static uint32_t RGB;
  9.     static uint8_t num;
  10.         Hue += 0.1f;
  11.         if (Hue >= 360.0f) {
  12.             Hue -= 360.0f;
  13.         }
  14.         time+=100;
  15.         if (time >= 7000) {
  16.             time = 0;
  17.             Hue = 0;
  18.             num++;
  19.         }
  20.         for ( i = 0; i < ledNum; i++) {
  21.             float ledHue = Hue + (float)(i * 360.0f / ledNum) + (float)time / 20.0f;
  22.             if (ledHue >= 360.0f) {
  23.                 ledHue -= 360.0f;
  24.             }
  25.             hsv_to_rgb(ledHue, Saturation, Value, &R, &G, &B);
  26.             RGB = ((uint32_t)R << 16) | ((uint32_t)G << 8) | B;
  27.             ws2812_set_index_brightness(RGB, i);
  28.         }
  29.     return 0;
  30. }
6.主函数
  1. int main(void)
  2. {
  3.     SystemCoreClockConfigure(); /* Configure system core clock */
  4.     SystemCoreClockUpdate();    /* Update system core clock info */
  5.     SysTick_Init();
  6.      Flow_led_init();
  7.     while(1)
  8.     {
  9.           Flow_led_send();
  10.           Colorful_gradient(26,10,1);
  11.           SysTick_Delay(10);
  12.     }
  13. }
三、效果
Snipaste_2024-12-26_22-22-27.jpg
四、总结
     直接使用IO口驱动,本来效果是七彩旋转,结果视频放不上去,没办法展示。





您需要登录后才可以回帖 登录 | 注册

本版积分规则

13

主题

35

帖子

0

粉丝
快速回复 在线客服 返回列表 返回顶部