155 lines
4.1 KiB
C
155 lines
4.1 KiB
C
#include <string.h>
|
||
|
||
#ifdef __cplusplus
|
||
extern "C" {
|
||
#endif
|
||
|
||
#include <stdio.h>
|
||
#include <stdbool.h>
|
||
#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 |