TA的每日心情  | 奋斗 2025-7-11 08:33 | 
|---|
 
  签到天数: 2 天 连续签到: 1 天 [LV.1]初来乍到 
举人 
 
 
	- 积分
 - 511
 
 
 
 
 | 
 
 
| 
利用零知增强版的GPIO 模拟时序    在本教程中,我们将探讨如何使用 零知增强版的 GPIO 接口来模拟 WS2812B LED 灯带的信号传输时序,从而实现对单色或多彩 LED 灯带的控制。这种技术允许我们避开专用驱动库,直接与硬件进行交互,理解并掌握 WS2812B 的通信机制。  
一、工具原料电脑、Windows系统 零知增强版开发板 Micro-usb线 WS2812RGB灯 
    WS2812B 是一款内含控制器芯片的全彩 LED 灯珠,每个灯珠可以独立显示红、绿、蓝三色。它通过单一数据线接收命令,实现高精度颜色控制。  
二、硬件连接零知增强版  | WS2812B  |  5V  | VCC  |  GND  | GND  |  51  | Din  |   1、硬件连接示意图 
 
 
2、实际效果 
 
 
三、传输时序和颜色控制1、信号传输时序 
WS2812B 的数据传输遵循特定的时间序列: 
- 高电平持续时间决定比特值:T1H 和 T0H 分别代表比特 1 和比特 0 的高电平持续时间。
 - 低电平持续时间:T1L 和 T0L。
 
 
 注:T1H 为 800ns,T1L 为 450ns 表示 1 比特。 
  T0H 为 400ns,T0L 为 850ns 表示 0 比特。 
  
2、颜色控制控制全局亮度和遵循WS2812B发送的时序: 
- 通过brightness参数调节RGB灯的全局亮度
 - WS2812B协议发送时序为G -> R -> B
 
 
  
四、代码驱动1、相关定义和初始化 
- // WS2812B相关定义
 
 - #define WS2812B_PIN 51      // WS2812B数据引脚
 
 - #define NUM_LEDS 8          // 灯珠数量
 
 - #define MAX_BRIGHTNESS 0.5  // 全局亮度调节(范围:0.0 - 1.0)
 
 -  
 
 - // WS2812B控制协议时间(根据各自的时序进行修改该定义)
 
 - #define T1H 800
 
 - #define T1L 450
 
 - #define T0H 400
 
 - #define T0L 850
 
 -  
 
 - // 初始化WS2812B引脚
 
 - void setupWS2812B() {
 
 -     pinMode(WS2812B_PIN, OUTPUT);
 
 -     digitalWrite(WS2812B_PIN, LOW);
 
 - }
 
 -  
 
 - // 更精确的纳秒延时函数(这里只是示例,实际可能需要更复杂的实现)
 
 - // 假设使用了支持纳秒级延时的定时器库
 
 - // 这里暂时使用简单的微秒级延时近似
 
 - void delayNanoseconds(unsigned long ns) {
 
 -     delayMicroseconds(ns / 1000);
 
 - }
 
  复制代码 
 
2、控制颜色和发送相关数据 
- ?// 发送一个比特
 
 - void WS2812B_SendBit(bool bitVal) {
 
 -     if (bitVal) {
 
 -         // 发送逻辑1
 
 -         digitalWrite(WS2812B_PIN, HIGH);
 
 -         delayNanoseconds(T1H);
 
 -         digitalWrite(WS2812B_PIN, LOW);
 
 -         delayNanoseconds(T1L);
 
 -     } else {
 
 -         // 发送逻辑0
 
 -         digitalWrite(WS2812B_PIN, HIGH);
 
 -         delayNanoseconds(T0H);
 
 -         digitalWrite(WS2812B_PIN, LOW);
 
 -         delayNanoseconds(T0L);
 
 -     }
 
 - }
 
  
- // 发送一个字节
 
 - void WS2812B_SendByte(uint8_t byte) {
 
 -     for (int i = 7; i >= 0; i--) {
 
 -         WS2812B_SendBit(byte & (1 << i));
 
 -     }
 
 - }
 
  
- // 发送RGB颜色数据(带亮度调节)
 
 - void WS2812B_SendColor(uint8_t red, uint8_t green, uint8_t blue, float brightness) {
 
 -     // 应用全局亮度调节
 
 -     red = (uint8_t)(red * brightness * MAX_BRIGHTNESS);
 
 -     green = (uint8_t)(green * brightness * MAX_BRIGHTNESS);
 
 -     blue = (uint8_t)(blue * brightness * MAX_BRIGHTNESS);
 
  
-     // WS2812B协议发送顺序:G -> R -> B
 
 -     WS2812B_SendByte(green);
 
 -     WS2812B_SendByte(red);
 
 -     WS2812B_SendByte(blue);
 
 - }
 
  复制代码 
 
3、实现流水灯、呼吸灯等功能 
- ?// 效果:彩虹追逐
 
 - void rainbowChaseEffect(uint8_t wait) {
 
 -     for (int offset = 0; offset < 255; offset++) {
 
 -         for (int i = 0; i < NUM_LEDS; i++) {
 
 -             int hue = (i * 255 / NUM_LEDS + offset) % 255;
 
 -             uint8_t r = 0, g = 0, b = 0;
 
 -             if (hue < 85) {
 
 -                 r = 255 - hue * 3;
 
 -                 g = hue * 3;
 
 -                 b = 0;
 
 -             } else if (hue < 170) {
 
 -                 hue -= 85;
 
 -                 r = 0;
 
 -                 g = 255 - hue * 3;
 
 -                 b = hue * 3;
 
 -             } else {
 
 -                 hue -= 170;
 
 -                 r = hue * 3;
 
 -                 g = 0;
 
 -                 b = 255 - hue * 3;
 
 -             }
 
 -             WS2812B_SendColor(r, g, b, MAX_BRIGHTNESS);
 
 -         }
 
 -         delay(wait);
 
 -     }
 
 - }
 
  
- // 呼吸灯效果
 
 - void breathAndFlow(uint8_t red, uint8_t green, uint8_t blue, uint8_t steps, uint16_t period, uint8_t wait, uint8_t iterations) {
 
 -     int ledStep[NUM_LEDS]; // 为每个 LED 创建一个步骤计数器
 
 -     for (int i = 0; i < NUM_LEDS; i++) {
 
 -         ledStep[i] = 0; // 初始化每个LED的步进
 
 -     }
 
  
-     uint8_t cycleCounter = 0; // 添加循环计数器
 
  
-     while (cycleCounter < iterations) { // 有限循环,迭代指定次数
 
 -         for (int i = 0; i < NUM_LEDS; i++) {
 
 -             // 计算当前 LED 的亮度比例
 
 -             float brightness = (sin(ledStep[i] * (M_PI / (steps))) + 1) / 2;
 
 -             WS2812B_SendColor(red, green, blue, brightness); // 使用计算出的亮度
 
  
-             // 更新 LED 的步骤计数器,模拟呼吸效果
 
 -             ledStep[i] = (ledStep[i] + 1) % (steps * 2); // 确保计数器在达到两倍步骤后重置
 
  
-             // 计算每个步骤的时间间隔
 
 -             delayMicroseconds(period / steps);
 
 -         }
 
 -        
 
 -         // 在一轮呼吸之后关闭所有灯
 
 -         clearAllLeds();
 
  
-         // 增加循环计数器
 
 -         cycleCounter++;
 
  
-         // 根据需要添加延迟,虽然这不是必须的
 
 -         delay(wait);
 
 -     }
 
 - }
 
  
- // 增加一个状态变量来记录是否有颜色覆盖
 
 - bool isCovered = false;
 
  
- // 流水灯
 
 - void ShampEffect(uint8_t red, uint8_t green, uint8_t blue, uint8_t trailDecay, uint8_t wait) {
 
 -     // 特殊处理第一个灯
 
 -     WS2812B_SendColor(red, green, blue, MAX_BRIGHTNESS);
 
 -     // 从第二个灯开始的索引为1
 
 -     for (int i = 0; i < NUM_LEDS; i++) {
 
 -         for (int j = 0; j <= NUM_LEDS; j++) {
 
 -             if (i - j == 0) {
 
 -                 if (!isCovered) {
 
 -                     // 如果没有被覆盖,设置为绿色
 
 -                     WS2812B_SendColor(0, 0, 0, MAX_BRIGHTNESS);
 
 -                 } else {
 
 -                     WS2812B_SendColor(red, green, blue, MAX_BRIGHTNESS);
 
 -                 }
 
 -             } else {
 
 -                 WS2812B_SendColor(0, 0, 0, MAX_BRIGHTNESS * trailDecay / 255.0);
 
 -             }
 
 -         }
 
 -         if (i == NUM_LEDS - 1) {
 
 -             // 当到达最后一个灯时,标记为已覆盖
 
 -             isCovered = true;
 
 -         }
 
 -         delay(wait);
 
 -     }
 
 - }
 
  复制代码 
 
4、控制灯的状态 
- ?// 设置特定位置灯珠颜色
 
 - void setLedColor(uint8_t pos, uint8_t red, uint8_t green, uint8_t blue, float brightness) {
 
 -     if (pos < NUM_LEDS) {
 
 -         // 只发送前面灯珠的关闭信号,直到要设置颜色的灯珠位置
 
 -         for (int i = 0; i < pos; i++) {
 
 -             WS2812B_SendColor(0, 0, 0, 0);
 
 -         }
 
 -         // 设置目标灯珠颜色
 
 -         WS2812B_SendColor(red, green, blue, brightness);
 
 -         // 发送后面灯珠的关闭信号,从目标灯珠的下一个位置开始
 
 -         for (int i = pos + 1; i < NUM_LEDS; i++) {
 
 -             WS2812B_SendColor(0, 0, 0, 0);
 
 -         }
 
 -     }
 
 - }
 
  
- // 设置所有灯珠颜色
 
 - void setAllLeds(uint8_t red, uint8_t green, uint8_t blue, float brightness) {
 
 -     clearAllLeds();// 先清除所有灯珠,确保没有杂色
 
 -     for (int i = 0; i < NUM_LEDS; i++) {
 
 -         WS2812B_SendColor(red, green, blue, brightness);
 
 -     }
 
 - }
 
  
- // 清除所有灯珠
 
 - void clearAllLeds() {
 
 -     for (int i = 0; i < NUM_LEDS * 3; i++) {
 
 -         WS2812B_SendByte(0);
 
 -     }
 
 - }
 
  复制代码 
 
5、主循环 
- ?// 初始化
 
 - void setup() {
 
 -     setupWS2812B();
 
 -     clearAllLeds();  // 确保灯带初始状态关闭
 
 - }
 
  
- // 主循环
 
 - void loop() {
 
 -     uint8_t Count = 0;
 
 -     //clearAllLeds();
 
 -     // 设置第六个灯珠为蓝色
 
 -     //setLedColor(5, 0, 0, 255, MAX_BRIGHTNESS);
 
 -     //delay(500);
 
 -     while(Count < 10)
 
 -     {
 
 -       ShampEffect(0, 0, random(255), 256, 200);
 
 -       Count ++;
 
 -     }
 
 -    
 
 -     //rainbowChaseEffect(1000);
 
 -     breathAndFlow(0,255,0,5,50,100,100);
 
 - }
 
  复制代码 
 
五、成果展示将上诉代码验证后上传到零知板,可以看到以下流水灯、呼吸灯等测试结果。 
 
https://live.csdn.net/v/437153?spm=1001.2014.3001.5501 
 
  
 |   
 
  
  
  
 
 
 |