Files
esp32c3-smart-scale/components/ws2812/ws2812.c

155 lines
4.1 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#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