- // 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

使用 GPIO 模拟时序驱动 WS2812B LED 灯带