#include #ifdef __cplusplus extern "C" { #endif #include #include #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "led_strip.h" #include "esp_log.h" #include "esp_err.h" // 提前声明 ws2812_set_color,避免隐式声明 esp_err_t ws2812_set_color(uint8_t r, uint8_t g, uint8_t b); // 预设颜色枚举 typedef enum { WS2812_COLOR_RED = 0, WS2812_COLOR_GREEN, WS2812_COLOR_BLUE, WS2812_COLOR_YELLOW, WS2812_COLOR_CYAN, WS2812_COLOR_MAGENTA, WS2812_COLOR_WHITE, WS2812_COLOR_ORANGE, WS2812_COLOR_PURPLE, WS2812_COLOR_PINK, WS2812_COLOR_LIME, WS2812_COLOR_SKYBLUE, WS2812_COLOR_OFF, WS2812_COLOR_MAX } ws2812_color_t; // 预设颜色表(GRB 顺序) static const uint8_t ws2812_color_table[WS2812_COLOR_MAX][3] = { {0, 50, 0}, // RED (G,R,B) {50, 0, 0}, // GREEN {0, 0, 50}, // BLUE {50, 50, 0}, // YELLOW {50, 0, 50}, // CYAN {0, 50, 50}, // MAGENTA {50, 50, 50}, // WHITE {25, 50, 0}, // ORANGE {25, 0, 50}, // PURPLE {0, 25, 50}, // PINK {50, 25, 0}, // LIME {50, 0, 25}, // SKYBLUE {0, 0, 0}, // OFF }; // 快捷设置预设颜色接口 esp_err_t ws2812_set_preset_color(ws2812_color_t color) { if (color < 0 || color >= WS2812_COLOR_MAX) { return ESP_ERR_INVALID_ARG; } const uint8_t *grb = ws2812_color_table[color]; // 注意 GRB 顺序 return ws2812_set_color(grb[1], grb[0], grb[2]); } static const char *TAG = "led_strip"; // --- 针对 ESP32-C3 和单颗 LED 的配置 --- // 设置为 0 使用非 DMA 模式。 // 虽然 C3 支持 DMA,但单颗 LED 数据量极小,非 DMA 模式足够且更节省资源。 #define LED_STRIP_USE_DMA 0 // 只有 1 个灯 #define LED_STRIP_LED_COUNT 1 // GPIO 0 #define LED_STRIP_GPIO_PIN 0 // 10MHz 分辨率 (1 tick = 0.1us) #define LED_STRIP_RMT_RES_HZ (10 * 1000 * 1000) // 内存块大小:单颗 LED 需要的数据非常少,设为 0 让驱动自动分配最合适的内存 #define LED_STRIP_MEMORY_BLOCK_WORDS 0 static led_strip_handle_t s_led_strip = NULL; esp_err_t ws2812_init(void) { if (s_led_strip) { return ESP_OK; // 已初始化 } // 1. LED 灯带通用配置 led_strip_config_t strip_config = { .strip_gpio_num = LED_STRIP_GPIO_PIN, // GPIO 0 .max_leds = LED_STRIP_LED_COUNT, // 1 颗 LED .led_model = LED_MODEL_WS2812, // WS2812 型号 .color_component_format = LED_STRIP_COLOR_COMPONENT_FMT_GRB, // GRB 顺序 .flags = { .invert_out = false, // 不反转信号 } }; // 2. RMT 后端配置 led_strip_rmt_config_t rmt_config = { .clk_src = RMT_CLK_SRC_DEFAULT, // 默认时钟源 .resolution_hz = LED_STRIP_RMT_RES_HZ, // 10MHz 分辨率 .mem_block_symbols = LED_STRIP_MEMORY_BLOCK_WORDS, // 自动分配 .flags = { .with_dma = LED_STRIP_USE_DMA, // 不使用 DMA } }; // 3. 创建 LED 灯带对象 esp_err_t ret = led_strip_new_rmt_device(&strip_config, &rmt_config, &s_led_strip); if (ret != ESP_OK) { ESP_LOGE(TAG, "Failed to create LED strip object: %s", esp_err_to_name(ret)); s_led_strip = NULL; return ret; } ESP_LOGI(TAG, "Created LED strip object with RMT backend on GPIO %d", LED_STRIP_GPIO_PIN); return ESP_OK; } esp_err_t ws2812_set_color(uint8_t r, uint8_t g, uint8_t b) { if (!s_led_strip) { ESP_LOGE(TAG, "LED strip not initialized"); return ESP_ERR_INVALID_STATE; } esp_err_t ret = led_strip_set_pixel(s_led_strip, 0, r, g, b); if (ret != ESP_OK) { ESP_LOGE(TAG, "Failed to set pixel: %s", esp_err_to_name(ret)); return ret; } ret = led_strip_refresh(s_led_strip); if (ret != ESP_OK) { ESP_LOGE(TAG, "Failed to refresh strip: %s", esp_err_to_name(ret)); return ret; } return ESP_OK; } // 熄灭 LED(快捷接口) esp_err_t ws2812_off(void) { return ws2812_set_color(0, 0, 0); } #ifdef __cplusplus } #endif