当前位置: 首页 > web >正文

ESP-ADF外设子系统深度解析:esp_peripherals组件架构与核心设计(显示输出类外设之AW2013)

目录

  • ESP-ADF外设子系统深度解析:esp_peripherals组件架构与核心设计(显示输出类外设之AW2013)
    • 简介
    • 模块概述
      • 功能定义
      • 架构位置
      • 核心特性
    • AW2013外设分析
      • AW2013外设概述
        • AW2013外设层次架构图
      • API与数据结构
        • 外设层API
          • 公共API
          • 内部数据结构
        • 底层驱动API
          • 公共API
        • 内部宏定义
      • AW2013 外设初始化流程
        • 外设层初始化过程(periph_aw2013.c)
        • 底层驱动初始化过程(aw2013.c)
        • 辅助函数详解
          • aw2013_reset
          • aw2013_set_time
          • aw2013_set_repeat_time
          • aw2013_set_brightness
          • aw2013_set_pwm_value
          • aw2013_enable_auto_flash
          • aw2013_enable_fade_mode
          • _aw2013_set_mode
        • AW2013 外设完整初始化时序图
        • 总结
      • AW2013 外设销毁流程
        • 外设层销毁过程(periph_aw2013.c)
        • 底层驱动销毁过程(aw2013.c)
        • AW2013 外设完整销毁时序图
        • 总结
      • AW2013 外设事件处理
        • AW2013 外设控制接口
      • AW2013 外设典型使用示例
        • 总结

ESP-ADF外设子系统深度解析:esp_peripherals组件架构与核心设计(显示输出类外设之AW2013)

版本信息: ESP-ADF v2.7-65-gcf908721

简介

本文档详细分析ESP-ADF中的显示/输出类外设实现机制,包括LCD、LED、WS2812、IS31FL3216和AW2013等外设的设计模式、接口规范、初始化流程和事件处理机制。ESP-ADF显示/输出类外设基于统一的外设框架设计,通过事件驱动模型实现显示和指示功能,为音频应用提供了丰富的视觉反馈能力和用户界面支持。

模块概述

功能定义

ESP-ADF显示/输出类外设主要负责提供视觉反馈和用户界面显示功能,将应用程序的状态和数据以可视化方式呈现给用户。主要功能包括:

  • 状态指示(LED指示灯、状态灯等)
  • 用户界面显示(LCD屏幕显示文本、图形等)
  • 视觉效果(WS2812彩色灯带、IS31FL3216和AW2013 LED矩阵等)
  • 音频可视化(音频频谱显示、节奏灯光效果等)

架构位置

显示/输出类外设是ESP-ADF外设子系统的重要组成部分,位于硬件驱动层和应用层之间:

应用程序
ESP外设子系统
显示/输出类外设
LCD外设
LED外设
WS2812外设
IS31FL3216外设
AW2013外设
SPI/I2C驱动
GPIO驱动
RMT驱动
I2C驱动
I2C驱动

核心特性

  • 多种显示设备支持:支持LCD、LED、WS2812、IS31FL3216和AW2013等多种显示和指示设备
  • 统一控制接口:所有显示/输出外设使用统一的初始化和控制接口
  • 丰富的显示效果:支持开关控制、亮度调节、颜色变化、动画效果等多种显示功能
  • 与音频处理集成:可与音频处理模块协同工作,实现音频可视化效果
  • 低功耗设计:支持设备休眠和唤醒管理,优化功耗表现
  • 事件驱动模型:通过事件机制实现显示状态变化的通知和处理

AW2013外设分析

AW2013外设概述

AW2013是一款3通道RGB LED驱动芯片,通过I2C总线控制,支持多种LED效果,包括常亮、呼吸灯和自动闪烁等模式。在ESP-ADF框架中,AW2013外设被封装为三个层次:

  1. 外设层:负责将AW2013集成到ESP-ADF外设系统中,处理事件分发和生命周期管理。

    • 头文件:components/esp_peripherals/include/periph_aw2013.h
    • 实现文件:components/esp_peripherals/periph_aw2013.c
  2. 底层驱动层:提供底层AW2013驱动,负责I2C通信、寄存器配置和LED控制。

    • 头文件:components/esp_peripherals/lib/aw2013/aw2013.h
    • 实现文件:components/esp_peripherals/lib/aw2013/aw2013.c
  3. 总线层:底层驱动通过I2C总线层与硬件通信,提供统一的总线访问接口。

    • 头文件:components/esp_peripherals/driver/i2c_bus/i2c_bus.h
    • 实现文件:components/esp_peripherals/driver/i2c_bus/i2c_bus.c(ESP-IDF 5.3.0- 实现)
    • 实现文件:components/esp_peripherals/driver/i2c_bus/i2c_bus_v2.c(ESP-IDF 5.3.0+ 实现)

AW2013芯片具有以下主要特性:

  • 3通道RGB LED驱动
  • 每通道最大电流可达15mA
  • 支持常亮、呼吸灯和自动闪烁模式
  • 可配置的闪烁周期和亮度
  • 通过I2C总线控制
AW2013外设层次架构图
底层驱动层 aw2013.c
外设层 periph_aw2013.c
调用
调用
设置
设置
调用
调用
调用
调用
调用
初始化
设置
设置
设置
调用
调用
调用
调用
初始化
写入
写入
写入
访问
访问
寄存器配置
aw2013_init
时间寄存器
aw2013_set_time
亮度寄存器
aw2013_set_brightness
PWM寄存器
aw2013_set_pwm_value
i2c_bus_create
i2c_bus_write_bytes
i2c_bus_write_bytes
i2c_bus_write_bytes
_aw2013_init
periph_aw2013_init
_aw2013_destroy
ESP-ADF应用
esp_periph_create
aw2013_deinit
I2C总线初始化
I2C总线传输
ESP32 I2C硬件

API与数据结构

外设层API

源文件components/esp_peripherals/include/periph_aw2013.hcomponents/esp_peripherals/periph_aw2013.c

公共API
// AW2013工作模式枚举
typedef enum {AW2013_MODE_LED,   // 常亮模式AW2013_MODE_FADE,  // 呼吸灯模式AW2013_MODE_AUTO   // 自动闪烁模式
} periph_aw2013_mode_t;// AW2013配置结构体
typedef struct {periph_aw2013_mode_t mode;  // 工作模式aw2013_brightness_t bright; // 亮度设置uint32_t rgb_value;         // RGB颜色值
} periph_aw2013_cfg_t;// 初始化AW2013外设
esp_periph_handle_t periph_aw2013_init(periph_aw2013_cfg_t *aw2013_cfg);// 设置亮度
esp_err_t periph_aw2013_set_brightless(esp_periph_handle_t periph, aw2013_brightness_t bright);// 设置时间周期
esp_err_t periph_aw2013_set_time(esp_periph_handle_t periph, aw2013_time_t time, aw2013_time_level_t level);// 设置工作模式
esp_err_t periph_aw2013_set_mode(esp_periph_handle_t periph, periph_aw2013_mode_t mode);// 设置RGB颜色值
esp_err_t periph_aw2013_set_rgb_value(esp_periph_handle_t periph, uint32_t value);// 设置重复次数
esp_err_t periph_aw2013_set_repeat_time(esp_periph_handle_t periph, uint8_t cnt);
内部数据结构
// AW2013外设内部结构体
typedef struct {aw2013_time_level_t time[5];   // 5个时间段的设置aw2013_brightness_t bright;    // 亮度设置periph_aw2013_mode_t mode;     // 工作模式uint32_t rgb_value;            // RGB颜色值uint8_t rpt_time;              // 重复次数
} periph_aw2013_t;
底层驱动API

源文件components/esp_peripherals/lib/aw2013/aw2013.hcomponents/esp_peripherals/lib/aw2013/aw2013.c

公共API
// 亮度级别枚举
typedef enum {AW2013_BRIGHT_0,    // 关闭LED,电流为0mAAW2013_BRIGHT_1,    // 5mAAW2013_BRIGHT_2,    // 10mAAW2013_BRIGHT_3,    // 15mA
} aw2013_brightness_t;// 自动闪烁周期的时间段
/*-------------------------------------------*\
|                 __________                  |
|                /|        |\                 |
|               / |        | \                |
|              /  |        |  \               |
|     ________/   |        |   \__________    |
|     |       |   |        |   |        |     |
|     |<--t0->|t1 |<--t2-->|t3 |<--t4-->|     |
\*-------------------------------------------*/
typedef enum {AW2013_TIME_0, // T0AW2013_TIME_1, // T1AW2013_TIME_2, // T2AW2013_TIME_3, // T3AW2013_TIME_4  // T4
} aw2013_time_t;// 时间级别枚举
typedef enum {             // T1-T4     T0AW2013_TIME_LEVEL_0,   // 0.13s  (T0 0s)AW2013_TIME_LEVEL_1,   // 0.26s  (T0 0.13s)AW2013_TIME_LEVEL_2,   // 0.52s  (T0 0.26s)AW2013_TIME_LEVEL_3,   // 1.04s  (T0 0.52s)AW2013_TIME_LEVEL_4,   // 2.08s  (T0 1.04s)AW2013_TIME_LEVEL_5,   // 4.16s  (T0 2.08s)AW2013_TIME_LEVEL_6,   // 8.32s  (T0 4.16s)AW2013_TIME_LEVEL_7,   // 16.64s (T0 8.32s)AW2013_TIME_LEVEL_8,   //        (T0 16.64s)
} aw2013_time_level_t;// 初始化AW2013芯片
esp_err_t aw2013_init(void);// 重置AW2013芯片
esp_err_t aw2013_reset(void);// 设置RGB值
esp_err_t aw2013_set_pwm_value(uint32_t value);// 设置自动闪烁的重复次数
esp_err_t aw2013_set_repeat_time(uint8_t cnt);// 设置各时间段的时长
esp_err_t aw2013_set_time(aw2013_time_t time, aw2013_time_level_t level);// 设置亮度
esp_err_t aw2013_set_brightness(aw2013_brightness_t bright);// 启用/禁用自动闪烁功能
esp_err_t aw2013_enable_auto_flash(bool en);// 启用/禁用呼吸灯功能
esp_err_t aw2013_enable_fade_mode(bool en);// 释放AW2013芯片资源
esp_err_t aw2013_deinit(void);
内部宏定义
#define AW2013_ADDR 0x8a // AW2013芯片地址
#define AW2013_MAX_LED_NUM 3 // 最大LED数量
#define AW2013_MAX_REPEAT_TIME 15 // 最大重复次数

AW2013 外设初始化流程

AW2013 外设的初始化流程涉及两个层次:外设层(Peripheral Layer)和底层驱动层(Driver Layer)。下面分别介绍这两个层次的初始化过程。

外设层初始化过程(periph_aw2013.c)

外设层初始化主要通过 periph_aw2013_init 函数(位于 periph_aw2013.c)完成,主要包括以下步骤:

  1. 创建外设句柄:调用 esp_periph_create 函数创建外设句柄。
  2. 分配内部数据结构:分配 periph_aw2013_t 结构体内存,用于存储 AW2013 配置参数。
  3. 设置配置参数:根据传入的配置结构体 aw2013_cfg 设置工作模式、亮度和 RGB 值。
  4. 注册回调函数:设置初始化和销毁回调函数 _aw2013_init_aw2013_destroy
// 文件:components/esp_peripherals/periph_aw2013.c
// 初始化 AW2013 外设,返回外设句柄以供后续操作
esp_periph_handle_t periph_aw2013_init(periph_aw2013_cfg_t *aw2013_cfg)
{// 1. 创建外设句柄,指定外设 ID 和名称esp_periph_handle_t periph = esp_periph_create(PERIPH_ID_AW2013, "periph_aw2013");AUDIO_MEM_CHECK(TAG, periph, return NULL); // 内存检查,确保句柄创建成功// 2. 分配内部数据结构,用于存储 AW2013 配置和状态periph_aw2013_t *aw2013 = audio_calloc(1, sizeof(periph_aw2013_t));AUDIO_MEM_CHECK(TAG, aw2013, {audio_free(periph);return NULL;});// 3. 设置配置参数,从传入的配置结构体中获取aw2013->mode = aw2013_cfg->mode; // 设置工作模式aw2013->bright = aw2013_cfg->bright; // 设置亮度级别aw2013->rgb_value = aw2013_cfg->rgb_value; // 设置 RGB 颜色值// 设置默认时间段值,用于自动闪烁模式aw2013->time[AW2013_TIME_0] = AW2013_TIME_LEVEL_1;aw2013->time[AW2013_TIME_1] = AW2013_TIME_LEVEL_2;aw2013->time[AW2013_TIME_2] = AW2013_TIME_LEVEL_2;aw2013->time[AW2013_TIME_3] = AW2013_TIME_LEVEL_2;aw2013->time[AW2013_TIME_4] = AW2013_TIME_LEVEL_2;aw2013->rpt_time = 0; // 默认重复次数为 0// 4. 注册回调函数,设置初始化和销毁函数esp_periph_set_data(periph, aw2013); // 关联数据到句柄esp_periph_set_function(periph, _aw2013_init, NULL, _aw2013_destroy); // 设置回调return periph; // 返回外设句柄
}

当外设被添加到外设集合并启动时,会调用 _aw2013_init 函数(位于 periph_aw2013.c),该函数负责调用底层驱动初始化函数并设置 AW2013 参数:

// 文件:components/esp_peripherals/periph_aw2013.c
// 外设初始化回调函数,在外设启动时调用
static esp_err_t _aw2013_init(esp_periph_handle_t self)
{esp_err_t ret = ESP_OK;periph_aw2013_t *aw2013 = esp_periph_get_data(self); // 获取外设数据ret |= aw2013_init(); // 调用底层驱动初始化函数,初始化 I2C 和芯片for (int i = 0; i <= AW2013_TIME_4; i++) {ret |= aw2013_set_time(i, aw2013->time[i]); // 设置每个时间段的时长}ret |= aw2013_set_repeat_time(aw2013->rpt_time); // 设置自动闪烁重复次数ret |= aw2013_set_brightness(aw2013->bright); // 设置亮度级别ret |= _aw2013_set_mode(aw2013->mode); // 设置工作模式(常亮、呼吸灯、自动闪烁)ret |= aw2013_set_pwm_value(aw2013->rgb_value); // 设置 RGB 颜色值return ret; // 返回操作结果
}

_aw2013_init 函数中,调用了以下底层驱动函数来完成 AW2013 的配置:

  • aw2013_set_time:设置自动闪烁周期中各个时间段(T0~T4)的时长。参数 time 指定时间段,level 指定时长级别。
  • aw2013_set_repeat_time:设置自动闪烁的重复次数。参数 cnt 指定重复次数,需小于最大值 AW2013_MAX_REPEAT_TIME
  • aw2013_set_brightness:设置 LED 亮度级别。参数 bright 指定亮度级别枚举值。
  • aw2013_set_pwm_value:设置 RGB 颜色值,通过 PWM 控制 LED 输出。参数 value 是一个 32 位值,每个字节分别表示 R、G、B 通道的 PWM 值。
  • _aw2013_set_mode:内部辅助函数,根据指定的工作模式启用或禁用自动闪烁和呼吸灯功能。参数 mode 指定工作模式枚举值。
底层驱动初始化过程(aw2013.c)

底层驱动初始化通过 aw2013_init 函数(位于 aw2013.c)完成,主要包括以下步骤:

  1. I2C 配置:将 I2C 配置设置为主机模式,时钟速度为 100000 Hz。
  2. 获取 I2C 引脚:调用 get_i2c_pins 函数为指定端口配置 I2C 引脚。
  3. 创建 I2C 总线:使用指定的端口和配置创建 I2C 总线。
  4. 复位 AW2013:调用 aw2013_reset 函数将 AW2013 芯片复位到默认状态。
  5. 错误处理:如果上述任何步骤失败,则使用 ESP_LOGE 记录错误消息。
  6. 返回结果:函数返回初始化过程的结果。
// 文件:components/esp_peripherals/lib/aw2013/aw2013.c
// 初始化 AW2013 芯片,配置 I2C 总线并启用芯片
esp_err_t aw2013_init(void)
{esp_err_t ret = ESP_OK;i2c_config_t config = {.mode = I2C_MODE_MASTER,        // 设置 I2C 为主机模式.master.clk_speed = 100000      // 设置时钟速度为 100kHz};ret |= get_i2c_pins(AW2013_I2C_PORT, &config);  // 获取 I2C 引脚配置i2c_handle = i2c_bus_create(AW2013_I2C_PORT, &config);  // 创建 I2C 总线ret |= aw2013_reset();  // 复位 AW2013 芯片if (ret != ESP_OK) {ESP_LOGE(TAG, "Fail to init aw2013");  // 如果初始化失败,记录错误日志}return ret;  // 返回初始化结果
}

aw2013_init 函数中,调用了以下辅助函数:

  • aw2013_reset:复位 AW2013 芯片,将所有寄存器恢复到默认值,确保芯片处于已知状态。
辅助函数详解

初始化过程中涉及以下辅助函数,用于支持 AW2013 外设的配置和操作。下面是这些函数的详细说明和代码片段:

aw2013_reset
// 文件:components/esp_peripherals/lib/aw2013/aw2013.c
// 复位 AW2013 芯片,将所有寄存器恢复到默认值
esp_err_t aw2013_reset(void)
{esp_err_t ret = ESP_OK;uint8_t reg_val = 0;uint8_t reg_addr = 0x0;AUDIO_NULL_CHECK(TAG, i2c_handle, return ESP_FAIL);  // 检查 I2C 句柄是否有效reg_addr = AW2013_REG_RESET;  // 复位寄存器地址reg_addr = AW2013_RESET_VALUE;  // 设置复位值ret |= i2c_bus_write_bytes(i2c_handle, AW2013_ADDR, &reg_addr, 1, &reg_val, 1);  // 写入复位命令reg_addr = AW2013_REG_GCR;  // 全局控制寄存器地址reg_val = 0x01;  // 启用芯片ret |= i2c_bus_write_bytes(i2c_handle, AW2013_ADDR, &reg_addr, 1, &reg_val, 1);  // 写入寄存器reg_addr = AW2013_REG_LCTR;  // LED 控制寄存器地址reg_val = 0x07;  // 启用所有 LED 通道ret |= i2c_bus_write_bytes(i2c_handle, AW2013_ADDR, &reg_addr, 1, &reg_val, 1);  // 写入寄存器ret |= aw2013_set_brightness(1);  // 设置默认亮度return ret;  // 返回操作结果
}

该函数用于复位 AW2013 芯片,通过向复位寄存器 AW2013_REG_RESET 写入特定值 AW2013_RESET_VALUE 来触发复位操作。复位后,函数还会配置全局控制寄存器启用芯片,设置 LED 控制寄存器启用所有 LED 通道,并设置默认亮度,确保芯片处于已知且可用的状态。

以下是 aw2013_reset 函数的执行时序图:

应用程序 aw2013_reset I2C 总线 AW2013 芯片 aw2013_set_brightness 调用 aw2013_reset() 检查 I2C 句柄是否有效 写入复位寄存器 (AW2013_REG_RESET) 发送复位命令 确认复位 返回操作结果 写入全局控制寄存器 (AW2013_REG_GCR) 设置值 0x01 (启用芯片) 确认写入 返回操作结果 写入 LED 控制寄存器 (AW2013_REG_LCTR) 设置值 0x07 (启用所有 LED 通道) 确认写入 返回操作结果 调用 aw2013_set_brightness(1) 为所有 LED 通道设置默认亮度 写入亮度配置 确认写入 返回操作结果 返回操作结果 返回复位结果 应用程序 aw2013_reset I2C 总线 AW2013 芯片 aw2013_set_brightness

这个时序图展示了 aw2013_reset 函数的执行流程,包括检查 I2C 句柄、复位芯片、配置全局控制寄存器、设置 LED 控制寄存器以及设置默认亮度等步骤,以及与 I2C 总线和 AW2013 芯片的交互过程。

aw2013_set_time
// 文件:components/esp_peripherals/lib/aw2013/aw2013.c
// 设置自动闪烁周期中各个时间段的时长
esp_err_t aw2013_set_time(aw2013_time_t time, aw2013_time_level_t level)
{if (level > AW2013_TIME_LEVEL_8 || time > AW2013_TIME_4) {ESP_LOGE(TAG, "Invalid parameters, time: %d, level: %d", time, level);return ESP_FAIL;}uint8_t reg_val = 0;uint8_t reg_addr = 0x0;esp_err_t ret = ESP_OK;AUDIO_NULL_CHECK(TAG, i2c_handle, return ESP_FAIL);  // 检查 I2C 句柄是否有效for (int i = 0; i < AW2013_MAX_LED_NUM; i++) {  // 为所有 LED 通道设置时间switch (time) {case AW2013_TIME_0: {reg_addr = AW2013_REG_LED0T0CNT + AW2013_MAX_LED_NUM * i;ret |= i2c_bus_read_bytes(i2c_handle, AW2013_ADDR, &reg_addr, 1, &reg_val, 1);reg_val &= 0x0f;reg_val |= (level << 4);ret |= i2c_bus_write_bytes(i2c_handle, AW2013_ADDR, &reg_addr, 1, &reg_val, 1);break;}case AW2013_TIME_1: {if (level > AW2013_TIME_LEVEL_7) {level = AW2013_TIME_LEVEL_7;  // 限制级别最大值}reg_addr = AW2013_REG_LED0T1T2 + AW2013_MAX_LED_NUM * i;ret |= i2c_bus_read_bytes(i2c_handle, AW2013_ADDR, &reg_addr, 1, &reg_val, 1);reg_val &= 0x8f;reg_val |= (level << 4);ret |= i2c_bus_write_bytes(i2c_handle, AW2013_ADDR, &reg_addr, 1, &reg_val, 1);break;}case AW2013_TIME_2: {if (level > AW2013_TIME_LEVEL_5) {level = AW2013_TIME_LEVEL_5;  // 限制级别最大值}reg_addr = AW2013_REG_LED0T1T2 + AW2013_MAX_LED_NUM * i;ret |= i2c_bus_read_bytes(i2c_handle, AW2013_ADDR, &reg_addr, 1, &reg_val, 1);reg_val &= 0xf8;reg_val |= level;ret |= i2c_bus_write_bytes(i2c_handle, AW2013_ADDR, &reg_addr, 1, &reg_val, 1);break;}case AW2013_TIME_3: {if (level > 7) {level = 7;  // 限制级别最大值}reg_addr = AW2013_REG_LED0T3T4 + AW2013_MAX_LED_NUM * i;ret |= i2c_bus_read_bytes(i2c_handle, AW2013_ADDR, &reg_addr, 1, &reg_val, 1);reg_val &= 0x8f;reg_val |= (level << 4);ret |= i2c_bus_write_bytes(i2c_handle, AW2013_ADDR, &reg_addr, 1, &reg_val, 1);break;}case AW2013_TIME_4: {if (level > 7) {level = 7;  // 限制级别最大值}reg_addr = AW2013_REG_LED0T3T4 + AW2013_MAX_LED_NUM * i;ret |= i2c_bus_read_bytes(i2c_handle, AW2013_ADDR, &reg_addr, 1, &reg_val, 1);reg_val &= 0xf8;reg_val |= level;ret |= i2c_bus_write_bytes(i2c_handle, AW2013_ADDR, &reg_addr, 1, &reg_val, 1);break;}default: {return ESP_FAIL;}}}return ret;  // 返回操作结果
}

该函数用于设置自动闪烁周期中各个时间段(T0~T4)的时长。参数 time 指定时间段,level 指定时长级别。函数会验证参数的有效性,并为所有 LED 通道配置相应的时间寄存器。根据不同的时间段,函数会操作不同的寄存器并应用适当的位掩码,确保正确配置每个时间段的持续时间。每个时间段还有其特定的级别限制,函数会确保不超过这些限制。

以下是 aw2013_set_time 函数的执行时序图:

应用程序 aw2013_set_time I2C 总线 AW2013 芯片 调用 aw2013_set_time(time, level) 检查参数有效性 返回 ESP_FAIL 检查 I2C 句柄是否有效 读取 LED0T0CNT 寄存器 读取请求 返回当前值 返回寄存器值 修改高 4 位为 level 写回修改后的值 写入请求 确认写入 返回操作结果 限制 level 最大值为 7 读取 LED0T1T2 寄存器 读取请求 返回当前值 返回寄存器值 修改中间 3 位为 level 写回修改后的值 写入请求 确认写入 返回操作结果 限制 level 最大值为 5 读取 LED0T1T2 寄存器 读取请求 返回当前值 返回寄存器值 修改低 3 位为 level 写回修改后的值 写入请求 确认写入 返回操作结果 限制 level 最大值为 7 读取 LED0T3T4 寄存器 读取请求 返回当前值 返回寄存器值 修改中间 3 位为 level 写回修改后的值 写入请求 确认写入 返回操作结果 限制 level 最大值为 7 读取 LED0T3T4 寄存器 读取请求 返回当前值 返回寄存器值 修改低 3 位为 level 写回修改后的值 写入请求 确认写入 返回操作结果 返回 ESP_FAIL alt [time = AW2013_TIME_0] [time = AW2013_TIME_1] [time = AW2013_TIME_2] [time = AW2013_TIME_3] [time = AW2013_TIME_4] [其他时间段] loop [对每个 LED 通道] 返回操作结果 alt [参数无效] [参数有效] 应用程序 aw2013_set_time I2C 总线 AW2013 芯片

这个时序图展示了 aw2013_set_time 函数的执行流程,包括参数验证、对不同时间段的处理逻辑以及与 I2C 总线和 AW2013 芯片的交互过程。根据不同的时间段参数,函数会操作不同的寄存器并应用适当的位掩码,确保正确配置每个时间段的持续时间。

aw2013_set_repeat_time
// 文件:components/esp_peripherals/lib/aw2013/aw2013.c
// 设置自动闪烁的重复次数
esp_err_t aw2013_set_repeat_time(uint8_t cnt)
{esp_err_t ret = ESP_OK;AUDIO_NULL_CHECK(TAG, i2c_handle, return ESP_FAIL);  // 检查 I2C 句柄是否有效uint8_t reg_val = 0;uint8_t reg_addr = 0x0;cnt %= AW2013_MAX_REPEAT_TIME;  // 确保重复次数不超过最大值for (int i = 0; i < AW2013_MAX_LED_NUM; i++) {  // 为所有 LED 通道设置重复次数reg_addr = AW2013_REG_LED0T0CNT + AW2013_MAX_LED_NUM * i;ret |= i2c_bus_read_bytes(i2c_handle, AW2013_ADDR, &reg_addr, 1, &reg_val, 1);reg_val &= 0xf0;reg_val |= cnt;ret |= i2c_bus_write_bytes(i2c_handle, AW2013_ADDR, &reg_addr, 1, &reg_val, 1);}return ret;  // 返回操作结果
}

该函数用于设置自动闪烁模式的重复次数。参数 cnt 指定重复次数,函数会确保其不超过最大值 AW2013_MAX_REPEAT_TIME。函数为所有 LED 通道配置重复次数,通过读取当前寄存器值,修改相应位,然后写回寄存器。

aw2013_set_brightness
// 文件:components/esp_peripherals/lib/aw2013/aw2013.c
// 设置 LED 亮度级别
esp_err_t aw2013_set_brightness(aw2013_brightness_t bright)
{esp_err_t ret = ESP_OK;uint8_t reg_val = 0;uint8_t reg_addr = 0x0;AUDIO_NULL_CHECK(TAG, i2c_handle, return ESP_FAIL);  // 检查 I2C 句柄是否有效if (bright > AW2013_BRIGHT_3) {bright = AW2013_BRIGHT_3;  // 限制亮度级别最大值}for (int i = 0; i < AW2013_MAX_LED_NUM; i++) {  // 为所有 LED 通道设置亮度reg_addr = AW2013_REG_LCFG0 + i;ret |= i2c_bus_read_bytes(i2c_handle, AW2013_ADDR, &reg_addr, 1, &reg_val, 1);reg_val &= 0xfc;reg_val |= bright;ret |= i2c_bus_write_bytes(i2c_handle, AW2013_ADDR, &reg_addr, 1, &reg_val, 1);}return ret;  // 返回操作结果
}

该函数用于设置 LED 的亮度级别。参数 bright 指定亮度级别枚举值。函数会确保亮度级别不超过最大值,并为所有 LED 通道配置亮度。通过读取当前寄存器值,修改相应位,然后写回寄存器。

aw2013_set_pwm_value
// 文件:components/esp_peripherals/lib/aw2013/aw2013.c
// 设置 RGB 颜色值,通过 PWM 控制 LED 输出
esp_err_t aw2013_set_pwm_value(uint32_t value)
{esp_err_t ret = ESP_OK;uint8_t reg_val = 0;uint8_t reg_addr = 0x0;AUDIO_NULL_CHECK(TAG, i2c_handle, return ESP_FAIL);  // 检查 I2C 句柄是否有效reg_addr = AW2013_REG_PWM0;reg_val = (value >> 16) & 0xff;  // 提取 R 通道 PWM 值ret |= i2c_bus_write_bytes(i2c_handle, AW2013_ADDR, &reg_addr, 1, &reg_val, 1);reg_addr = AW2013_REG_PWM1;reg_val = (value >> 8) & 0xff;  // 提取 G 通道 PWM 值ret |= i2c_bus_write_bytes(i2c_handle, AW2013_ADDR, &reg_addr, 1, &reg_val, 1);reg_addr = AW2013_REG_PWM2;reg_val = value & 0xff;  // 提取 B 通道 PWM 值ret |= i2c_bus_write_bytes(i2c_handle, AW2013_ADDR, &reg_addr, 1, &reg_val, 1);return ret;  // 返回操作结果
}

该函数用于设置 RGB 颜色值,通过 PWM 控制 LED 的输出。参数 value 是一个 32 位值,其中每个字节分别表示 R、G、B 通道的 PWM 值。函数分别将这些值写入对应的 PWM 寄存器以控制 LED 颜色。

aw2013_enable_auto_flash
// 文件:components/esp_peripherals/lib/aw2013/aw2013.c
// 启用或禁用自动闪烁功能
esp_err_t aw2013_enable_auto_flash(bool en)
{esp_err_t ret = ESP_OK;uint8_t reg_val = 0;uint8_t reg_addr = 0x0;AUDIO_NULL_CHECK(TAG, i2c_handle, return ESP_FAIL);  // 检查 I2C 句柄是否有效if (en) {  // 启用自动闪烁for (int i = 0; i < AW2013_MAX_LED_NUM; i++) {reg_addr = AW2013_REG_LCFG0 + i;ret |= i2c_bus_read_bytes(i2c_handle, AW2013_ADDR, &reg_addr, 1, &reg_val, 1);reg_val |= (0x01 << 4);  // 设置自动闪烁位ret |= i2c_bus_write_bytes(i2c_handle, AW2013_ADDR, &reg_addr, 1, &reg_val, 1);}} else {  // 禁用自动闪烁for (int i = 0; i < AW2013_MAX_LED_NUM; i++) {reg_addr = AW2013_REG_LCFG0 + i;ret |= i2c_bus_read_bytes(i2c_handle, AW2013_ADDR, &reg_addr, 1, &reg_val, 1);reg_val &= ~(0x01 << 4);  // 清除自动闪烁位ret |= i2c_bus_write_bytes(i2c_handle, AW2013_ADDR, &reg_addr, 1, &reg_val, 1);}}return ret;  // 返回操作结果
}

该函数用于启用或禁用自动闪烁功能。参数 en 为布尔值,决定是否启用该功能。函数为所有 LED 通道配置自动闪烁功能,通过读取当前寄存器值,设置或清除相应位,然后写回寄存器。

aw2013_enable_fade_mode
// 文件:components/esp_peripherals/lib/aw2013/aw2013.c
// 启用或禁用呼吸灯模式
esp_err_t aw2013_enable_fade_mode(bool en)
{esp_err_t ret = ESP_OK;uint8_t reg_val = 0;uint8_t reg_addr = 0x0;AUDIO_NULL_CHECK(TAG, i2c_handle, return ESP_FAIL);  // 检查 I2C 句柄是否有效if (en) {  // 启用呼吸灯模式for (int i = 0; i < AW2013_MAX_LED_NUM; i++) {reg_addr = AW2013_REG_LCFG0 + i;ret |= i2c_bus_read_bytes(i2c_handle, AW2013_ADDR, &reg_addr, 1, &reg_val, 1);reg_val &= ~(0x01 << 4);  // 清除自动闪烁位reg_val |=  (0x03 << 5);  // 设置呼吸灯模式位ret |= i2c_bus_write_bytes(i2c_handle, AW2013_ADDR, &reg_addr, 1, &reg_val, 1);}} else {  // 禁用呼吸灯模式for (int i = 0; i < AW2013_MAX_LED_NUM; i++) {reg_addr = AW2013_REG_LCFG0 + i;ret |= i2c_bus_read_bytes(i2c_handle, AW2013_ADDR, &reg_addr, 1, &reg_val, 1);reg_val &= ~(0x03 << 5);  // 清除呼吸灯模式位ret |= i2c_bus_write_bytes(i2c_handle, AW2013_ADDR, &reg_addr, 1, &reg_val, 1);}}return ret;  // 返回操作结果
}

该函数用于启用或禁用呼吸灯模式。参数 en 为布尔值,决定是否启用该功能。函数为所有 LED 通道配置呼吸灯模式,通过读取当前寄存器值,设置或清除相应位,然后写回寄存器。启用呼吸灯模式时,会同时禁用自动闪烁功能。

_aw2013_set_mode
// 文件:components/esp_peripherals/periph_aw2013.c
// 设置 AW2013 工作模式(常亮、呼吸灯、自动闪烁)
static esp_err_t _aw2013_set_mode(periph_aw2013_mode_t mode)
{esp_err_t ret = ESP_OK;switch (mode) {case PERIPH_AW2013_MODE_NORMAL: // 常亮模式ret |= aw2013_enable_auto_flash(false); // 禁用自动闪烁ret |= aw2013_enable_fade_mode(false); // 禁用呼吸灯break;case PERIPH_AW2013_MODE_FADE: // 呼吸灯模式ret |= aw2013_enable_auto_flash(false); // 禁用自动闪烁ret |= aw2013_enable_fade_mode(true); // 启用呼吸灯break;case PERIPH_AW2013_MODE_AUTO_FLASH: // 自动闪烁模式ret |= aw2013_enable_auto_flash(true); // 启用自动闪烁ret |= aw2013_enable_fade_mode(false); // 禁用呼吸灯break;default:ESP_LOGE(TAG, "Unsupported mode: %d", mode); // 不支持的模式ret = ESP_FAIL;break;}return ret; // 返回操作结果
}

该函数是一个内部辅助函数,用于设置 AW2013 的工作模式。根据指定的模式枚举值,函数会调用相应的函数来启用或禁用自动闪烁和呼吸灯功能,从而实现常亮、呼吸灯或自动闪烁模式。

AW2013 外设完整初始化时序图

下图展示了 AW2013 外设从应用程序调用到底层驱动完成初始化的完整流程:

应用程序 periph_aw2013_init (periph_aw2013.c) esp_periph库 _aw2013_init (periph_aw2013.c) aw2013_init (aw2013.c) aw2013_reset (aw2013.c) I2C总线 AW2013芯片 periph_aw2013_init(aw2013_cfg) esp_periph_create(PERIPH_ID_AW2013, "periph_aw2013") periph 分配 periph_aw2013_t 结构体 设置 mode、bright、rgb_value 等参数 esp_periph_set_data(periph, aw2013) esp_periph_set_function(periph, _aw2013_init, NULL, _aw2013_destroy) periph 当外设被添加到外设集合并启动时 _aw2013_init(self) esp_periph_get_data(self) aw2013 aw2013_init() 初始化 I2C 配置 get_i2c_pins(AW2013_I2C_PORT, &config) i2c_bus_create(AW2013_I2C_PORT, &config) i2c_handle aw2013_reset() 检查 I2C 句柄是否有效 写入复位寄存器 (AW2013_REG_RESET) 发送复位命令 确认复位 写入全局控制寄存器 (AW2013_REG_GCR) 设置值 0x01 (启用芯片) 确认写入 写入 LED 控制寄存器 (AW2013_REG_LCTR) 设置值 0x07 (启用所有 LED 通道) 确认写入 aw2013_set_brightness(1) 返回复位结果 错误处理 返回初始化结果 aw2013_ch_disable(aw2013->>handle, AW2013_CH_ALL) aw2013_leds_duty(aw2013->>handle, 0, AW2013_CH_ALL) aw2013_set_time(i, time[i]) (循环) aw2013_set_repeat_time(rpt_time) aw2013_set_brightness(bright) _aw2013_set_mode(mode) aw2013_set_pwm_value(rgb_value) 返回初始化结果 应用程序 periph_aw2013_init (periph_aw2013.c) esp_periph库 _aw2013_init (periph_aw2013.c) aw2013_init (aw2013.c) aw2013_reset (aw2013.c) I2C总线 AW2013芯片
总结

AW2013 外设的初始化过程涉及多个层次的组件交互,包括外设层和底层驱动层。初始化完成后,AW2013 外设可以通过不同的工作模式实现 LED 的常亮、呼吸灯和自动闪烁效果。整个初始化流程设计合理,各组件职责明确,便于维护和扩展。

AW2013 外设销毁流程

AW2013 外设的销毁流程同样涉及外设层(Peripheral Layer)和底层驱动层(Driver Layer)两个层次。销毁过程主要负责释放资源和清理内存。下面分别介绍这两个层次的销毁过程。

外设层销毁过程(periph_aw2013.c)

外设层销毁主要通过 _aw2013_destroy 函数(位于 periph_aw2013.c)完成,这个函数在外设被移除或者被停止时由 ESP 外设框架调用。根据实际源码,该函数主要包括以下步骤:

  1. 获取外设数据:从外设句柄中获取之前存储的 periph_aw2013_t 结构体。
  2. 调用底层驱动销毁:调用 aw2013_deinit 函数释放底层资源。
  3. 释放内存:释放 periph_aw2013_t 结构体占用的内存。
// 文件:components/esp_peripherals/periph_aw2013.c
// 销毁 AW2013 外设,释放资源
static esp_err_t _aw2013_destroy(esp_periph_handle_t self)
{esp_err_t ret = ESP_OK;periph_aw2013_t *aw2013 = esp_periph_get_data(self);  // 获取外设数据ret |= aw2013_deinit();  // 调用底层驱动销毁函数,释放底层资源audio_free(aw2013);  // 释放 aw2013 结构体内存return ret;  // 返回操作结果
}

该函数首先通过 esp_periph_get_data 获取之前在初始化阶段存储的外设数据结构。然后直接调用底层驱动的 aw2013_deinit 函数进行硬件资源的释放。最后,释放分配给 periph_aw2013_t 结构体的内存空间。这简化的销毁过程依赖于 aw2013_deinit 函数来正确地清理芯片和总线资源。

底层驱动销毁过程(aw2013.c)

底层驱动销毁通过 aw2013_deinit 函数(位于 aw2013.c)完成,主要包括以下步骤:

  1. 复位芯片:向 AW2013 芯片的复位寄存器写入复位值,使其回到默认状态。
  2. 释放 I2C 总线:调用 i2c_bus_delete 函数删除 I2C 总线实例,释放相关资源。
// 文件:components/esp_peripherals/lib/aw2013/aw2013.c
// 反初始化 AW2013 芯片,释放资源
esp_err_t aw2013_deinit(void)
{esp_err_t ret = ESP_OK;uint8_t reg_addr = AW2013_REG_RESET;uint8_t reg_val = AW2013_RESET_VALUE;AUDIO_NULL_CHECK(TAG, i2c_handle, return ESP_FAIL);  // 检查 I2C 句柄是否有效ret |= i2c_bus_write_bytes(i2c_handle, AW2013_ADDR, &reg_addr, 1, &reg_val, 1);  // 复位芯片ret |= i2c_bus_delete(i2c_handle);  // 删除 I2C 总线实例return ret;  // 返回操作结果
}

该函数首先检查 I2C 句柄是否有效,然后通过 I2C 总线向 AW2013 芯片的复位寄存器(AW2013_REG_RESET)写入复位值(AW2013_RESET_VALUE),使芯片恢复到初始状态。接着调用 i2c_bus_delete 函数删除之前创建的 I2C 总线实例,释放相关资源。这样可以确保 AW2013 外设完全释放所有占用的硬件和软件资源。

AW2013 外设完整销毁时序图

下图展示了 AW2013 外设从停止到完全释放资源的销毁流程:

esp_periph库 _aw2013_destroy (periph_aw2013.c) aw2013_deinit (aw2013.c) I2C总线 AW2013芯片 外设被停止或移除 _aw2013_destroy(self) esp_periph_get_data(self) aw2013 aw2013_deinit() 检查 I2C 句柄是否有效 写入复位寄存器 (AW2013_REG_RESET) 发送复位命令 确认复位 返回操作结果 i2c_bus_delete(i2c_handle) 释放 I2C 总线资源 返回操作结果 返回操作结果 audio_free(aw2013) 释放外设数据结构内存 返回销毁结果 esp_periph库 _aw2013_destroy (periph_aw2013.c) aw2013_deinit (aw2013.c) I2C总线 AW2013芯片

这个时序图展示了 AW2013 外设销毁的完整流程,从外设框架调用 _aw2013_destroy 开始,到最终释放所有资源结束。该流程反映了实际源码中的简洁设计,直接调用 aw2013_deinit 函数复位芯片并释放 I2C 总线资源,然后释放外设数据结构内存。

总结

AW2013 外设的销毁流程设计简洁且合理,能够有效释放所有占用的资源,包括硬件资源(I2C 总线和 AW2013 芯片)和软件资源(内存空间)。销毁流程采用了最小化设计,直接复位芯片并释放 I2C 总线和内存资源,遵循了资源管理的最佳实践,确保系统运行稳定且无资源泄漏。

AW2013 外设事件处理

AW2013 外设是一款 LED 驱动芯片,主要用于控制 RGB LED 灯的亮度、闪烁和呼吸效果等。与其他一些需要处理用户输入的外设不同,AW2013 主要是一个输出型外设,它本身不会产生需要由应用程序处理的事件。

在 ESP-ADF 的外设框架中,AW2013 外设没有特定的事件处理函数(如 _aw2013_event_handler),这是因为它不需要响应或处理来自硬件的事件通知。应用程序通过调用 AW2013 外设提供的 API 函数来控制 LED 的显示效果,而不是通过事件机制与 AW2013 外设交互。

虽然 AW2013 外设没有专门的事件处理,但它仍然遵循 ESP-ADF 外设框架的生命周期管理,包括初始化和销毁过程。应用程序可以通过框架提供的通用接口(如 esp_periph_startesp_periph_stop 等)来管理 AW2013 外设的生命周期。

AW2013 外设控制接口

虽然没有事件处理机制,但 AW2013 外设提供了丰富的控制接口,允许应用程序灵活地控制 LED 显示效果:

  1. 设置 RGB 值:通过 periph_aw2013_set_rgb_value 函数设置 LED 的颜色。

    esp_err_t periph_aw2013_set_rgb_value(esp_periph_handle_t periph, uint32_t value);
    
  2. 设置工作模式:通过 periph_aw2013_set_mode 函数设置 LED 的工作模式(常亮、呼吸或闪烁)。

    esp_err_t periph_aw2013_set_mode(esp_periph_handle_t periph, periph_aw2013_mode_t mode);
    
  3. 设置亮度:通过 periph_aw2013_set_brightless 函数设置 LED 的亮度级别。

    esp_err_t periph_aw2013_set_brightless(esp_periph_handle_t periph, aw2013_brightness_t bright);
    
  4. 设置时间参数:通过 periph_aw2013_set_time 函数设置呼吸灯或闪烁效果的时间参数。

    esp_err_t periph_aw2013_set_time(esp_periph_handle_t periph, aw2013_time_t time, aw2013_time_level_t level);
    
  5. 设置重复次数:通过 periph_aw2013_set_repeat_time 函数设置闪烁效果的重复次数。

    esp_err_t periph_aw2013_set_repeat_time(esp_periph_handle_t periph, uint8_t cnt);
    

这些接口提供了全面的 LED 控制能力,使应用程序可以根据需要实现各种视觉效果。

AW2013 外设典型使用示例

以下是 AW2013 外设的典型使用示例,展示了如何在实际应用中控制 RGB LED。

#include "esp_peripherals.h"
#include "periph_aw2013.h"
#include "board.h"void app_main()
{// 初始化外设管理器esp_periph_config_t periph_cfg = DEFAULT_ESP_PERIPH_SET_CONFIG();esp_periph_set_handle_t set = esp_periph_set_init(&periph_cfg);// 配置 AW2013 外设 - 设置为呼吸灯模式periph_aw2013_cfg_t aw2013_cfg = {.mode = PERIPH_AW2013_MODE_BREATHE,  // 呼吸灯模式.rgb_value = 0x0000FF,  // 蓝色.bright = AW2013_BRIGHTNESS_025,  // 亮度级别};// 初始化并启动 AW2013 外设esp_periph_handle_t aw2013_handle = periph_aw2013_init(&aw2013_cfg);esp_periph_start(set, aw2013_handle);// 配置呼吸灯参数periph_aw2013_set_time(aw2013_handle, AW2013_TIME_FADE_IN, AW2013_TIME_1S3_1S9);periph_aw2013_set_time(aw2013_handle, AW2013_TIME_FADE_OUT, AW2013_TIME_1S3_1S9);// 切换到其他模式示例// periph_aw2013_set_mode(aw2013_handle, PERIPH_AW2013_MODE_ALWAYS_ON);  // 常亮模式// periph_aw2013_set_rgb_value(aw2013_handle, 0x00FF00);  // 改变颜色为绿色// 与事件系统结合的示例// esp_periph_set_callback(set, event_handler, aw2013_handle);  // 注册事件回调// 主循环while (1) {vTaskDelay(pdMS_TO_TICKS(1000));}
}// 事件回调函数示例 - 与其他外设(如按键、Wi-Fi等)交互
static esp_err_t event_handler(esp_periph_handle_t self, esp_periph_event_t *event, void *ctx)
{esp_periph_handle_t aw2013 = (esp_periph_handle_t)ctx;// 根据不同事件设置不同LED效果switch(event->type) {case PERIPH_WIFI_CONNECTED:  // Wi-Fi连接成功periph_aw2013_set_rgb_value(aw2013, 0x00FF00);  // 绿色periph_aw2013_set_mode(aw2013, PERIPH_AW2013_MODE_ALWAYS_ON);  // 常亮break;case PERIPH_WIFI_DISCONNECTED:  // Wi-Fi断开连接periph_aw2013_set_rgb_value(aw2013, 0xFF0000);  // 红色periph_aw2013_set_mode(aw2013, PERIPH_AW2013_MODE_AUTO_FLASH);  // 闪烁break;}return ESP_OK;
}
总结

AW2013 外设提供了丰富的 API 来控制 RGB LED 的显示效果,可以实现常亮、呼吸灯和闪烁等多种模式。通过这些 API,开发者可以根据应用程序需求和系统状态,动态调整 LED 的显示效果,提供直观的视觉反馈。

虽然 AW2013 外设本身不产生事件,但它可以与其他产生事件的外设(如 Wi-Fi、按键等)结合使用,根据这些事件动态改变 LED 显示,从而提升用户体验。AW2013 外设的简单易用性和灵活性使其成为 ESP-ADF 应用中实现视觉反馈的理想选择。

http://www.xdnf.cn/news/803.html

相关文章:

  • Django 入门指南:构建强大的 Web 应用程序
  • compat-openssl10和libnsl下载安装
  • 从 TinyZero 到 APR:语言模型推理能力的探索与自适应并行化
  • JBoss 项目修复笔记:绕开 iframe 安全问题,JSF 与 Angular 最小代价共存方案
  • 高防IP能抵御哪些类型的网络攻击?
  • 【Linux】多线程任务模块
  • 【TeamFlow】4.2 Yew库详细介绍
  • 基础版-图书管理系统
  • AOSP Android14 Launcher3——点击桌面图标启动应用动画流程
  • url和http
  • 海外服务器安装Ubuntu 22.04图形界面并配置VNC远程访问指南
  • AI 速读 SpecReason:让思考又快又准!
  • opencv 图像矫正的原理
  • 小刚说C语言刷题——1039 求三个数的最大数
  • PyTorch与TensorFlow模型全方位解析:保存、加载与结构可视化
  • 明心见性与真如三昧
  • CTF web入门之SQL注入使用工具sqlmap
  • 网页下载的m3u8格式文件使用FFmpeg转为MP4
  • C#常用LINQ
  • 快速搭建 Cpolar 内网穿透(Mac 系统)
  • 嵌入式开发板调试方式完全指南:串口/SSH/Telnet及其他方式对比
  • 深度学习框架PyTorch——从入门到精通(3.3)YouTube系列——自动求导基础
  • 【每天一个知识点】主题建模(Topic Modeling)
  • 浙江大学DeepSeek 公开课 第三季 第1期讲座 - 马东方教授 (附PPT下载) by突破信息差
  • 【25软考网工笔记】第三章 局域网(1)CSMA/CD、二进制指数退避算法、最小帧长计算
  • 高品质性价比之王-特伦斯便携钢琴V10
  • 海外版高端Apple科技汽车共享投资理财系统
  • Spark-SQL编程
  • 【第十六届 蓝桥杯 省 C/Python A/Java C 登山】题解
  • 《Java工程师面试核心突破》专栏简介