Add initial board, HAL, and executor modules
This commit is contained in:
1 parent
3b9e129c88
commit
0b2eebe76d
82 files changed
+20611
No files matched your search
@@ -0,0 +1,25 @@
|
||||
#ifndef BOARD_SELECTION_H
|
||||
#define BOARD_SELECTION_H
|
||||
|
||||
#include "sdkconfig.h"
|
||||
|
||||
// 根据menuconfig的配置选择不同的board版本
|
||||
#ifdef CONFIG_BOARD_VERSION_V1_1_11
|
||||
#include "02_physical/boards/board_v1_1_11/board_sweekar.h"
|
||||
#elif defined(CONFIG_BOARD_VERSION_V1_1_12)
|
||||
#include "02_physical/boards/board_v1_1_12/board_sweekar.h"
|
||||
#elif defined(CONFIG_BOARD_VERSION_V1_1_13)
|
||||
#include "02_physical/boards/board_v1_1_13/board_sweekar.h"
|
||||
#elif defined(CONFIG_BOARD_VERSION_V1_1_14)
|
||||
#include "02_physical/boards/board_v1_1_14/board_sweekar.h"
|
||||
#elif defined(CONFIG_BOARD_VERSION_V1_1_16)
|
||||
#include "02_physical/boards/board_v1_1_16/board_sweekar.h"
|
||||
#elif defined(CONFIG_BOARD_VERSION_V1_1_17)
|
||||
#include "02_physical/boards/board_v1_1_17/board_sweekar.h"
|
||||
#elif defined(CONFIG_BOARD_VERSION_V1_1_18)
|
||||
#include "02_physical/boards/board_v1_1_18/board_sweekar.h"
|
||||
#else
|
||||
#include "02_physical/boards/board_v1_1_11/board_sweekar.h"
|
||||
#endif
|
||||
|
||||
#endif // BOARD_SELECTION_H
|
||||
@@ -0,0 +1,261 @@
|
||||
/**
|
||||
* @file board.cc
|
||||
* @brief 板级外设初始化类,包含步进电机、毫米波雷达、I2C总线等外设的初始化函数。
|
||||
* @author zouyuhua
|
||||
* @date 2025年8月7日
|
||||
*
|
||||
*/
|
||||
|
||||
extern "C" {
|
||||
#include "esp_log.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "driver/uart.h"
|
||||
#include "driver/ledc.h"
|
||||
#include "esp_err.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "hal/gpio_types.h"
|
||||
#include "hal/uart_types.h"
|
||||
#include "esp_check.h"
|
||||
#include "sdkconfig.h"
|
||||
#include "i2c_bus.h"
|
||||
}
|
||||
|
||||
#include "board_sweekar.h"
|
||||
#include "config.h"
|
||||
#include "drv8428.h"
|
||||
#include "aw8646.h"
|
||||
|
||||
#define TAG "board_sweekar"
|
||||
|
||||
BoardSweekar::BoardSweekar()
|
||||
{
|
||||
#ifdef CONFIG_STEPPER_DRIVER_AW8646
|
||||
stepper_driver_ = new Aw8646Driver(io_expansion_);
|
||||
#else
|
||||
stepper_driver_ = new Drv8428Driver(io_expansion_);
|
||||
#endif
|
||||
}
|
||||
|
||||
BoardSweekar::~BoardSweekar()
|
||||
{
|
||||
if (stepper_driver_) {
|
||||
delete stepper_driver_;
|
||||
stepper_driver_ = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @file board.h
|
||||
* @brief 板级外设初始化类
|
||||
*/
|
||||
/**
|
||||
* @brief 步进电机初始化函数
|
||||
*
|
||||
* 配置LEDC定时器和通道用于PWM输出,设置步进电机的工作模式、使能状态、细分模式和方向,
|
||||
* 并初始化PWM占空比为50%。初始化过程中若出现错误,会通过ESP_LOGE输出错误信息及错误码。
|
||||
*/
|
||||
void BoardSweekar::StepperMotorInit(void)
|
||||
{
|
||||
esp_err_t err = ESP_OK;
|
||||
|
||||
// 1) STEP 引脚改为普通 GPIO
|
||||
gpio_config_t io_cfg;
|
||||
io_cfg.pin_bit_mask = 1ULL << STEPPER_STEP_IO;
|
||||
io_cfg.mode = GPIO_MODE_OUTPUT;
|
||||
io_cfg.pull_up_en = GPIO_PULLUP_DISABLE;
|
||||
io_cfg.pull_down_en = GPIO_PULLDOWN_DISABLE;
|
||||
io_cfg.intr_type = GPIO_INTR_DISABLE;
|
||||
err = gpio_config(&io_cfg);
|
||||
if (err != ESP_OK)
|
||||
{
|
||||
ESP_LOGE(TAG_BOARD, "步进电机 STEP GPIO 配置失败, 错误码: 0x%x", err);
|
||||
}
|
||||
|
||||
// 初始电平拉低
|
||||
gpio_set_level(STEPPER_STEP_IO, 0);
|
||||
|
||||
// 2) 检查 I2C 总线是否已初始化
|
||||
if (bus_handle_ == nullptr)
|
||||
{
|
||||
ESP_LOGE(TAG_BOARD, "I2C总线未初始化,请先调用I2CMasterInit()");
|
||||
return;
|
||||
}
|
||||
|
||||
// 3) 初始化驱动对象并初始化
|
||||
if (stepper_driver_) {
|
||||
err = stepper_driver_->Init();
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG_BOARD, "步进电机驱动初始化失败, 错误码: 0x%x", err);
|
||||
}
|
||||
} else {
|
||||
ESP_LOGE(TAG_BOARD, "步进电机驱动创建失败");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 毫米波雷达串口初始化函数
|
||||
*
|
||||
* 配置毫米波雷达所使用的串口参数(波特率、数据位、校验位、停止位等),设置串口引脚,
|
||||
* 并安装串口驱动。采用较大的RX/TX FIFO深度以处理突发数据,禁用驱动自带事件队列以避免
|
||||
* 与自定义中断冲突。
|
||||
*/
|
||||
void BoardSweekar::MillimeterWaveRadarUartInit(void)
|
||||
{
|
||||
uart_config_t uart_config = {
|
||||
.baud_rate = BAUD_RATE,
|
||||
.data_bits = UART_DATA_8_BITS,
|
||||
.parity = UART_PARITY_DISABLE,
|
||||
.stop_bits = UART_STOP_BITS_1,
|
||||
.flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
|
||||
.source_clk = UART_SCLK_DEFAULT,
|
||||
};
|
||||
|
||||
// 1. 设置串口参数
|
||||
ESP_ERROR_CHECK(uart_param_config(RADAR_UART_NUM, &uart_config));
|
||||
|
||||
// 2. 设置 UART 引脚
|
||||
ESP_ERROR_CHECK(uart_set_pin(RADAR_UART_NUM, UART_TX_PIN, UART_RX_PIN,
|
||||
UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE));
|
||||
|
||||
// 3. 安装 UART 驱动(禁用驱动自带事件队列,避免与自定义中断冲突)
|
||||
// 增加 RX/TX FIFO 深度以处理突发数据
|
||||
ESP_ERROR_CHECK(uart_driver_install(RADAR_UART_NUM, RADAR_BUF_SIZE * 4, RADAR_BUF_SIZE * 4,
|
||||
0, NULL, 0));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 毫米波雷达中断引脚初始化函数
|
||||
*
|
||||
* 配置毫米波雷达中断引脚为输入模式,禁用上拉电阻,使能下拉电阻,初始禁用中断功能
|
||||
* (如需使用中断需单独进行配置)。
|
||||
*/
|
||||
void BoardSweekar::MillimeterWaveRadarGpioInit(void)
|
||||
{
|
||||
// GPIO配置结构体
|
||||
gpio_config_t io_conf = {
|
||||
.pin_bit_mask = (1ULL << MILLIMETER_WAVE_RADAR_PIN), // 选择GPIO引脚
|
||||
.mode = GPIO_MODE_INPUT, // 设置为输入模式
|
||||
.pull_up_en = GPIO_PULLUP_DISABLE,
|
||||
.pull_down_en = GPIO_PULLDOWN_ENABLE, // 使能下拉
|
||||
.intr_type = GPIO_INTR_DISABLE // 禁用中断(如需中断需单独配置)
|
||||
};
|
||||
|
||||
// 配置GPIO
|
||||
gpio_config(&io_conf);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief I2C总线及从机设备初始化函数
|
||||
*
|
||||
* 首先配置并创建I2C主机总线,然后依次添加IO扩展板和线性马达作为I2C从机设备到总线上。
|
||||
* 若总线创建或设备添加失败,会输出错误信息并进行相应的资源清理(删除已创建的总线)。
|
||||
* 初始化成功后,会通过ESP_LOGI输出IO扩展板和线性马达的从机地址信息。
|
||||
*
|
||||
* @return esp_err_t 初始化结果,ESP_OK表示成功,其他错误码表示相应的失败原因
|
||||
*/
|
||||
esp_err_t BoardSweekar::I2CMasterInit(void)
|
||||
{
|
||||
static const char *I2C_INIT = "I2C_INIT";
|
||||
|
||||
// 初始化IO扩展板复位引脚
|
||||
gpio_config_t reset_io_conf = {
|
||||
.pin_bit_mask = (1ULL << IO_EXPAND_RSTN),
|
||||
.mode = GPIO_MODE_OUTPUT,
|
||||
.pull_up_en = GPIO_PULLUP_ENABLE, // 使能上拉
|
||||
.pull_down_en = GPIO_PULLDOWN_DISABLE,
|
||||
.intr_type = GPIO_INTR_DISABLE
|
||||
};
|
||||
gpio_config(&reset_io_conf);
|
||||
|
||||
// 执行复位时序:先拉低100ms,再拉高并等待100ms
|
||||
gpio_set_level(IO_EXPAND_RSTN, 0); // 拉低复位
|
||||
vTaskDelay(pdMS_TO_TICKS(100)); // 等待100ms
|
||||
gpio_set_level(IO_EXPAND_RSTN, 1); // 释放复位
|
||||
vTaskDelay(pdMS_TO_TICKS(100)); // 等待设备启动
|
||||
|
||||
ESP_LOGI(I2C_INIT, "IO扩展板复位完成");
|
||||
|
||||
// 创建统一的I2C总线(使用ESP-ADF的i2c_bus)
|
||||
i2c_config_t i2c_cfg = {
|
||||
.mode = I2C_MODE_MASTER,
|
||||
.sda_io_num = I2C0_MASTER_SDA_IO,
|
||||
.scl_io_num = I2C0_MASTER_SCL_IO,
|
||||
.sda_pullup_en = GPIO_PULLUP_ENABLE,
|
||||
.scl_pullup_en = GPIO_PULLUP_ENABLE,
|
||||
.master = {
|
||||
.clk_speed = 100000,
|
||||
},
|
||||
};
|
||||
|
||||
// 创建I2C总线(ESP-ADF的audio_board_init会复用这个总线)
|
||||
bus_handle_ = i2c_bus_create(I2C0_MASTER_PORT, &i2c_cfg);
|
||||
if (bus_handle_ == NULL) {
|
||||
ESP_LOGE(TAG, "Failed to create I2C bus");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
vTaskDelay(pdMS_TO_TICKS(100)); // 等待设备启动
|
||||
// ESP-ADF的i2c_bus不需要单独添加设备,直接通过总线句柄和设备地址进行通信
|
||||
|
||||
// 验证线性马达设备是否存在
|
||||
esp_err_t err = i2c_bus_probe_addr(bus_handle_, LINEAR_MOTOR_I2C_SLAVE_ADDR << 1);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(I2C_INIT, "线性马达设备未找到(地址:0x%02X),错误码: 0x%x", LINEAR_MOTOR_I2C_SLAVE_ADDR, err);
|
||||
// 不返回错误,继续初始化
|
||||
} else {
|
||||
ESP_LOGI(I2C_INIT, "线性马达设备检测成功(地址:0x%02X)", LINEAR_MOTOR_I2C_SLAVE_ADDR);
|
||||
}
|
||||
// 验证IO扩展板设备是否存在
|
||||
err = i2c_bus_probe_addr(bus_handle_, I2C_IO_EXPAND_SLAVE_ADDR << 1);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(I2C_INIT, "IO扩展板设备未找到(地址:0x%02X),错误码: 0x%x", I2C_IO_EXPAND_SLAVE_ADDR, err);
|
||||
// 不返回错误,继续初始化其他设备
|
||||
} else {
|
||||
ESP_LOGI(I2C_INIT, "IO扩展板设备检测成功(地址:0x%02X)", I2C_IO_EXPAND_SLAVE_ADDR);
|
||||
}
|
||||
// 验证陀螺仪设备是否存在
|
||||
err = i2c_bus_probe_addr(bus_handle_, GYROSCOPE_I2C_SLAVE_ADDR << 1);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(I2C_INIT, "陀螺仪设备未找到(地址:0x%02X),错误码: 0x%x", GYROSCOPE_I2C_SLAVE_ADDR, err);
|
||||
// 不返回错误,继续初始化
|
||||
} else {
|
||||
ESP_LOGI(I2C_INIT, "陀螺仪设备检测成功(地址:0x%02X)", GYROSCOPE_I2C_SLAVE_ADDR);
|
||||
}
|
||||
|
||||
// 为IO扩展板设置总线句柄和设备地址(使用7位地址)
|
||||
io_expansion_.bus_handle_ = bus_handle_;
|
||||
io_expansion_.device_addr_ = I2C_IO_EXPAND_SLAVE_ADDR << 1;
|
||||
|
||||
// 为线性马达设置总线句柄和设备地址(使用7位地址)
|
||||
linear_motor_.bus_handle_ = bus_handle_;
|
||||
linear_motor_.device_addr_ = LINEAR_MOTOR_I2C_SLAVE_ADDR << 1;
|
||||
|
||||
ESP_LOGI(I2C_INIT, "I2C总线初始化完成");
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 开启VBAT to VBAT_5V
|
||||
*
|
||||
* 创建开启升压的电源管理单元
|
||||
*
|
||||
*/
|
||||
void BoardSweekar::VbatToVbat5vInit(void)
|
||||
{
|
||||
// 配置VBAT_5V引脚为输出模式
|
||||
gpio_config_t io_conf = {
|
||||
.pin_bit_mask = (1ULL << VBAT_5V_PIN),
|
||||
.mode = GPIO_MODE_OUTPUT,
|
||||
.pull_up_en = GPIO_PULLUP_DISABLE,
|
||||
.pull_down_en = GPIO_PULLDOWN_DISABLE,
|
||||
.intr_type = GPIO_INTR_DISABLE
|
||||
};
|
||||
gpio_config(&io_conf);
|
||||
// 使能VBAT_5V
|
||||
gpio_set_level(VBAT_5V_PIN, 1);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
#ifndef __BOARD_H__
|
||||
#define __BOARD_H__
|
||||
#include "config.h"
|
||||
#include "io_expansion_board.h"
|
||||
#include "stepper_motor.h"
|
||||
#include "stepper_driver.h"
|
||||
#include "i2c_bus.h"
|
||||
#include "gyroscope.h"
|
||||
#include "touch_sensor.h"
|
||||
|
||||
class BoardSweekar
|
||||
{
|
||||
private:
|
||||
i2c_bus_handle_t bus_handle_ = nullptr; // 使用ESP-ADF的I2C总线句柄
|
||||
|
||||
public:
|
||||
BoardSweekar();
|
||||
~BoardSweekar();
|
||||
|
||||
IOExpansionBoard io_expansion_; // IO扩展板对象
|
||||
LinearMotor linear_motor_; // 线性马达对象
|
||||
Gyroscope gyroscope_; // 陀螺仪对象
|
||||
TouchSensor touch_sensor_; // 触摸传感器对象
|
||||
StepperDriver* stepper_driver_ = nullptr; // 步进电机驱动对象
|
||||
|
||||
StepperDriver* GetStepperDriver() const { return stepper_driver_; }
|
||||
|
||||
// 初始化步进电机
|
||||
void StepperMotorInit(void);
|
||||
|
||||
// 初始化串口
|
||||
void MillimeterWaveRadarUartInit(void);
|
||||
|
||||
//初始化毫米波雷达的中断引脚
|
||||
void MillimeterWaveRadarGpioInit(void);
|
||||
|
||||
// 初始化I2C总线
|
||||
esp_err_t I2CMasterInit(void);
|
||||
|
||||
// 初始化VBAT toVBAT_5V引脚
|
||||
void VbatToVbat5vInit(void);
|
||||
|
||||
// 获取I2C总线句柄
|
||||
i2c_bus_handle_t GetBusHandle() const { return bus_handle_; }
|
||||
};
|
||||
#endif
|
||||
@@ -0,0 +1,138 @@
|
||||
/* 定义引脚分配 */
|
||||
#ifndef _BOARD_CONFIG_H_
|
||||
#define _BOARD_CONFIG_H_
|
||||
|
||||
/**
|
||||
* @file config.h
|
||||
* @brief 定义了引脚的分配。
|
||||
* @author zouyuhua
|
||||
* @date 2025年8月7日
|
||||
*
|
||||
*/
|
||||
|
||||
#include "driver/gpio.h"
|
||||
#include "driver/i2c_master.h"
|
||||
#include "driver/i2s.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_rom_sys.h" // 用于 esp_rom_delay_us
|
||||
#include "esp_timer.h"
|
||||
#include "esp_mac.h"
|
||||
#include "driver/ledc.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "esp_log.h"
|
||||
#include "driver/timer.h"
|
||||
#include "esp_intr_alloc.h"
|
||||
#include "soc/timer_group_struct.h" // 包含TIMERG0、TIMERG1的结构体定义
|
||||
#include "soc/timer_group_reg.h" // 包含定时器相关寄存器宏定义
|
||||
#include "driver/uart.h"
|
||||
#include "esp_err.h"
|
||||
#include "freertos/queue.h"
|
||||
#include "soc/uart_reg.h"
|
||||
#include "linear_motor.h"
|
||||
#include "gyroscope.h"
|
||||
|
||||
#define TAG_BOARD "SWEEKAR_ESP32"
|
||||
/*I2C总线引脚定义*/
|
||||
#define I2C0_MASTER_PORT I2C_NUM_0
|
||||
#define I2C0_MASTER_SDA_IO GPIO_NUM_2
|
||||
#define I2C0_MASTER_SCL_IO GPIO_NUM_3
|
||||
|
||||
/* 步进电机引脚设置 */
|
||||
#define LEDC_OUTPUT_IO GPIO_NUM_42 // 步进电机LEDC引脚输入
|
||||
|
||||
/* 定义屏幕驱动控制引脚 */
|
||||
#define ST7789_PIN_CLK GPIO_NUM_48 // SPI时钟引脚
|
||||
#define ST7789_PIN_DC GPIO_NUM_38 // 数据/命令选择引脚RSEL
|
||||
#define ST7789_PIN_MOSI GPIO_NUM_47 // SPI数据输出引脚
|
||||
#define ST7789_PIN_CS GPIO_NUM_40 // SPI片选引脚
|
||||
#define ST7789_PIN_BL GPIO_NUM_NC // 背光引脚
|
||||
#define ST7789_PIN_RST GPIO_NUM_NC // 复位引脚
|
||||
#define LCD_BL_ACTIVE_LEVEL 0 // 背光有效电平:1=高电平有效(NMOS),0=低电平有效(PMOS)
|
||||
|
||||
#define LCD_WIDTH 172 // 屏幕宽度(水平方向像素数)
|
||||
#define LCD_HEIGHT 320 // 屏幕高度(垂直方向像素数)
|
||||
|
||||
/* 毫米波雷达配置参数 */
|
||||
/* 定义毫米波雷达的中断引脚 */
|
||||
#define MILLIMETER_WAVE_RADAR_PIN GPIO_NUM_35
|
||||
// UART 配置参数
|
||||
#define RADAR_UART_NUM UART_NUM_1 // 使用 UART0
|
||||
#define UART_TX_PIN GPIO_NUM_NC // GPIO43 作为 TX(根据实际硬件连接调整)
|
||||
#define UART_RX_PIN GPIO_NUM_39 // GPIO44 作为 RX
|
||||
#define BAUD_RATE 9600 // 波特率
|
||||
#define RADAR_BUF_SIZE 100 // 雷达接收缓冲区大小
|
||||
|
||||
/* IO扩展硬件配置常量 */
|
||||
#define I2C_MASTER_FREQ_HZ 100000 // I2C通信频率(100kHz)(可更改至400000)
|
||||
#define I2C_IO_EXPAND_SLAVE_ADDR 0x5B // AW9523BTQR器件地址
|
||||
#define GPIO_INPUT_PIN_SEL GPIO_NUM_10 // 中断检测引脚
|
||||
#define ESP_INTR_FLAG_DEFAULT 0 // 中断标志默认值
|
||||
#define IO_EXPAND_RSTN GPIO_NUM_45 // IO扩展板复位引脚
|
||||
|
||||
/* 定义线性马达的I2C从机配置常量 */
|
||||
#define LINEAR_MOTOR_I2C_SLAVE_ADDR 0x5A // 线性马达的I2C从机地址
|
||||
|
||||
/* 定义陀螺仪的I2C从机配置常量 */
|
||||
#define GYROSCOPE_I2C_SLAVE_ADDR 0x6A // 陀螺仪的I2C从机地址
|
||||
#define GYROSCOPE_INPUT_PIN_SEL GPIO_NUM_21 // 陀螺仪中断引脚
|
||||
|
||||
/* 原生触摸引脚配置 */
|
||||
// 触摸按键数量配置
|
||||
// #define TOUCH_BUTTON_NUM 4
|
||||
#define TOUCH_BUTTON_NUM 3
|
||||
// 触摸通道定义
|
||||
#define TOUCH_PAD_CHANNEL_1 TOUCH_PAD_NUM11 // GPIO11
|
||||
#define TOUCH_PAD_CHANNEL_2 TOUCH_PAD_NUM12 // GPIO12
|
||||
#define TOUCH_PAD_CHANNEL_3 TOUCH_PAD_NUM13 // GPIO13
|
||||
// #define TOUCH_PAD_CHANNEL_4 TOUCH_PAD_NUM14 // GPIO14
|
||||
|
||||
/* ES8311音频编解码器配置 (ESP-ADF兼容) */
|
||||
#define AUDIO_INPUT_SAMPLE_RATE 24000
|
||||
#define AUDIO_OUTPUT_SAMPLE_RATE 24000
|
||||
#define AUDIO_INPUT_REFERENCE true
|
||||
|
||||
/* I2S GPIO定义 */
|
||||
#define AUDIO_I2S_GPIO_MCLK GPIO_NUM_15
|
||||
#define AUDIO_I2S_GPIO_WS GPIO_NUM_4
|
||||
#define AUDIO_I2S_GPIO_BCLK GPIO_NUM_5
|
||||
#define AUDIO_I2S_GPIO_DIN GPIO_NUM_6
|
||||
#define AUDIO_I2S_GPIO_DOUT GPIO_NUM_7
|
||||
|
||||
/* PA引脚定义 */
|
||||
#define AUDIO_CODEC_PA_PIN GPIO_NUM_8
|
||||
|
||||
/* I2C配置 */
|
||||
#define AUDIO_CODEC_I2C_SDA_PIN GPIO_NUM_2
|
||||
#define AUDIO_CODEC_I2C_SCL_PIN GPIO_NUM_3
|
||||
#define AUDIO_CODEC_ES8311_ADDR 0x18
|
||||
#define AUDIO_CODEC_ES7210_ADDR 0x40
|
||||
|
||||
/* WS2812 RGB LED配置 */
|
||||
#define WS2812_PIN GPIO_NUM_41 // WS2812数据引脚
|
||||
#define WS2812_NUM_LEDS 2 // WS2812 LED数量
|
||||
|
||||
/* 创建VBAT to VBAT_5V */
|
||||
#define VBAT_5V_PIN GPIO_NUM_8 // VBAT_5V引脚
|
||||
|
||||
/* 定义按键的中断引脚 */
|
||||
#define BUTTON_PIN GPIO_NUM_0 // 按键中断引脚
|
||||
|
||||
#endif // _BOARD_CONFIG_H_
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,732 @@
|
||||
#include "io_expansion_board.h"
|
||||
#include "millimeter_wave_radar.h"
|
||||
#include "esp_heap_caps.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_check.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/idf_additions.h"
|
||||
#include "freertos/portable.h"
|
||||
#include "freertos/task.h"
|
||||
#include "freertos/event_groups.h"
|
||||
#include "esp_rom_sys.h"
|
||||
/**
|
||||
* @file io_expansion_board.cc
|
||||
* @brief IO扩展板功能实现类,包含I2C通信、GPIO中断配置、外设控制等功能
|
||||
* @details 实现了IO扩展板的初始化(中断引脚、复位引脚)、寄存器读写、步进电机控制(细分模式、使能、方向、睡眠状态)、
|
||||
* LCD相关引脚控制(背光、复位、片选)、毫米波雷达中断引脚配置等功能,并提供I2C数据读取任务的创建与管理
|
||||
* @author zouyuhua
|
||||
* @date 2025年8月7日
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief 构造函数
|
||||
*/
|
||||
IOExpansionBoard::IOExpansionBoard()
|
||||
: bus_handle_(nullptr),
|
||||
device_addr_(0),
|
||||
i2c_task_event_group_(nullptr),
|
||||
xI2CReadTaskHandle_(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 析构函数
|
||||
*/
|
||||
IOExpansionBoard::~IOExpansionBoard()
|
||||
{
|
||||
// 删除任务
|
||||
if (xI2CReadTaskHandle_) {
|
||||
vTaskDelete(xI2CReadTaskHandle_);
|
||||
}
|
||||
|
||||
// if(pI2CReadTaskStackBuffer) {
|
||||
// heap_caps_free(pI2CReadTaskStackBuffer);
|
||||
// pI2CReadTaskStackBuffer = nullptr;
|
||||
// }
|
||||
|
||||
// if(pxI2CReadTaskBuffer) {
|
||||
// vPortFree(pxI2CReadTaskBuffer);
|
||||
// pxI2CReadTaskBuffer = nullptr;
|
||||
// }
|
||||
|
||||
// 删除事件组
|
||||
if (i2c_task_event_group_) {
|
||||
vEventGroupDelete(i2c_task_event_group_);
|
||||
}
|
||||
|
||||
// 移除中断处理
|
||||
if (interrupt_gpio_ != GPIO_NUM_NC) {
|
||||
gpio_isr_handler_remove(interrupt_gpio_);
|
||||
}
|
||||
|
||||
// 删除IO扩展板设备
|
||||
// 使用i2c_bus API时不需要手动删除设备句柄
|
||||
// bus_handle_由board_sweekar统一管理
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 静态中断处理函数
|
||||
*/
|
||||
void IRAM_ATTR IOExpansionBoard::GpioIsrHandler(void* arg)
|
||||
{
|
||||
IOExpansionBoard* instance = static_cast<IOExpansionBoard*>(arg);
|
||||
if (!instance) return;
|
||||
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
|
||||
// 设置事件标志位
|
||||
if (instance->i2c_task_event_group_) {
|
||||
xEventGroupSetBitsFromISR(
|
||||
instance->i2c_task_event_group_,
|
||||
BIT0,
|
||||
&xHigherPriorityTaskWoken
|
||||
);
|
||||
}
|
||||
|
||||
// // 唤醒挂起的I2C任务
|
||||
// if (instance->xI2CReadTaskHandle_) {
|
||||
// if (xTaskResumeFromISR(instance->xI2CReadTaskHandle_) == pdTRUE) {
|
||||
// xHigherPriorityTaskWoken = pdTRUE;
|
||||
// }
|
||||
// }
|
||||
|
||||
// 触发上下文切换
|
||||
if (xHigherPriorityTaskWoken) {
|
||||
portYIELD_FROM_ISR();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 初始化GPIO中断检测
|
||||
*/
|
||||
esp_err_t IOExpansionBoard::InterruptGpioInit(gpio_num_t gpio_num)
|
||||
{
|
||||
// 配置IO扩展板中断引脚
|
||||
gpio_config_t io_conf = {};
|
||||
io_conf.intr_type = GPIO_INTR_NEGEDGE;
|
||||
io_conf.pin_bit_mask = 1ULL << gpio_num;
|
||||
io_conf.mode = GPIO_MODE_INPUT;
|
||||
io_conf.pull_up_en = GPIO_PULLUP_ENABLE;
|
||||
io_conf.pull_down_en = GPIO_PULLDOWN_DISABLE;
|
||||
|
||||
esp_err_t err = gpio_config(&io_conf);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG_GPIO_IO_EXPAND_DETECT, "GPIO配置失败,错误码: 0x%x", err);
|
||||
return err;
|
||||
}
|
||||
// 配置中断服务
|
||||
err = gpio_install_isr_service(ESP_INTR_FLAG_LEVEL3);
|
||||
if (err != ESP_OK && err != ESP_ERR_INVALID_STATE) {
|
||||
ESP_LOGE(TAG_GPIO_IO_EXPAND_DETECT, "GPIO中断服务安装失败,错误码: 0x%x", err);
|
||||
return err;
|
||||
}
|
||||
// 注册中断处理函数
|
||||
err = gpio_isr_handler_add(gpio_num, GpioIsrHandler, this);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG_GPIO_IO_EXPAND_DETECT, "GPIO中断处理函数添加失败,错误码: 0x%x", err);
|
||||
return err;
|
||||
}
|
||||
// 创建事件组
|
||||
i2c_task_event_group_ = xEventGroupCreate();
|
||||
if (!i2c_task_event_group_) {
|
||||
ESP_LOGE(TAG_GPIO_IO_EXPAND_DETECT, "事件组创建失败");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
ESP_LOGI(TAG_GPIO_IO_EXPAND_DETECT, "GPIO%d中断初始化完成", gpio_num);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 初始化硬件复位引脚
|
||||
* 设置为上拉,需要复位,需要输出低电平为20us的脉冲信号
|
||||
*/
|
||||
esp_err_t IOExpansionBoard::ResetGpioInit(gpio_num_t gpio_num)
|
||||
{
|
||||
reset_gpio_ = gpio_num;
|
||||
|
||||
// 配置复位引脚
|
||||
gpio_config_t io_conf = {};
|
||||
io_conf.intr_type = GPIO_INTR_DISABLE;
|
||||
io_conf.pin_bit_mask = 1ULL << gpio_num;
|
||||
io_conf.mode = GPIO_MODE_OUTPUT;
|
||||
io_conf.pull_up_en = GPIO_PULLUP_ENABLE;
|
||||
io_conf.pull_down_en = GPIO_PULLDOWN_DISABLE;
|
||||
esp_err_t err = gpio_config(&io_conf);
|
||||
gpio_set_level(gpio_num, 1); // 复位引脚拉高
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG_GPIO_IO_EXPAND_DETECT, "GPIO配置失败,错误码: 0x%x", err);
|
||||
return err;
|
||||
}
|
||||
else{
|
||||
ESP_LOGI(TAG_GPIO_IO_EXPAND_DETECT, "GPIO%d复位引脚初始化完成", gpio_num);
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 复位IO扩展板
|
||||
*/
|
||||
esp_err_t IOExpansionBoard::ResetIoExpand()
|
||||
{
|
||||
if (reset_gpio_ == GPIO_NUM_NC) {
|
||||
ESP_LOGE(TAG_I2C_IO_EXPAND_TASK, "复位引脚未初始化");
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
|
||||
// 复位IO扩展板
|
||||
gpio_set_level(reset_gpio_, 0);
|
||||
esp_rom_delay_us(30);
|
||||
gpio_set_level(reset_gpio_, 1);
|
||||
uint8_t ctl_val;
|
||||
//配置P0_0-P0_7的端口为推挽输出模式
|
||||
esp_err_t err = IoexpandReadReg(CTL, &ctl_val);
|
||||
ctl_val |= (1 << 4); // 设置D[4]位为1(GPOMD=1),切换P0为推挽模式
|
||||
err = IoexpandWriteReg(CTL, ctl_val);
|
||||
if(err != ESP_OK){
|
||||
ESP_LOGE(TAG_I2C_IO_EXPAND_TASK, "复位失败,错误码:0x%x", err);
|
||||
return err;
|
||||
}
|
||||
else{
|
||||
ESP_LOGI(TAG_I2C_IO_EXPAND_TASK, "复位成功");
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 写寄存器数据
|
||||
* @param reg_addr 寄存器地址
|
||||
* @param data 要写入的数据
|
||||
* @return esp_err_t 操作结果
|
||||
*/
|
||||
esp_err_t IOExpansionBoard::IoexpandWriteReg(uint8_t reg_addr, uint8_t data)
|
||||
{
|
||||
return i2c_bus_write_bytes(bus_handle_, device_addr_, ®_addr, 1, &data, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 从寄存器读取数据
|
||||
* @param reg_addr 寄存器地址(如INPUT_PORT0、ID等)
|
||||
* @param data 输出参数,用于存储读取到的数据
|
||||
* @return esp_err_t 操作结果(ESP_OK为成功)
|
||||
*/
|
||||
esp_err_t IOExpansionBoard::IoexpandReadReg(uint8_t reg_addr, uint8_t* data)
|
||||
{
|
||||
if (data == nullptr){ // 检查输入参数有效性
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
// 使用i2c_bus_read_bytes进行寄存器读取
|
||||
esp_err_t err = i2c_bus_read_bytes(bus_handle_, device_addr_, ®_addr, 1, data, 1);
|
||||
if (err != ESP_OK){
|
||||
ESP_LOGE(TAG_I2C_IO_EXPAND_TASK, "读取寄存器失败,错误码:0x%x", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
//设置IO扩展板为输入模式或是输出模式
|
||||
/*
|
||||
* 这里需要根据实际情况设置IO扩展板的模式,比如输入模式还是输出模式,以及各个引脚的配置。
|
||||
* P0_0 对应NFC_RST引脚,需要设置为输出模式,低电平有效。(待测)
|
||||
* P0_1 对应USB_VBUS引脚,需要设置为输出模式,低电平有效。(待测)
|
||||
* P0_2 对应BTN_RIGHT_EAR引脚,需要设置为输出模式,低电平有效。(待测)
|
||||
* P0_3 暂时未使用。
|
||||
* P0_4 对应步进电机方向引脚,需要设置为输出模式,根据需求设置。(待测)
|
||||
* P0_5 对应CHRG引脚(待测)
|
||||
* P0_6 LCD_DC引脚,需要设置为输出模式,根据需求设置电平。(待测)
|
||||
* P0_7 对应步进电机的使能引脚,需要设置为输出模式,根据需求设置。(待测)
|
||||
*
|
||||
*
|
||||
* P1_0 对应EG800K_PWR。(待测)
|
||||
* P1_1 对应LCD_RST,需要设置为输出模式,低电平有效。(待测)
|
||||
* P1_2 对应LCD_CS,需要设置为输出模式,低电平有效。(待测)
|
||||
* P1_3 暂时未使用。
|
||||
* P1_4 对应步进电机的细分模式M1引脚。(待测)
|
||||
* P1_5 对应步进电机的细分模式M0引脚。(待测)
|
||||
* P1_6 对应步进电机的睡眠引脚。(待测)
|
||||
* P1_7 对应RADAR_O雷达的输出引脚。(待测)
|
||||
* */
|
||||
esp_err_t IOExpansionBoard::IoexpandSetMode(void)
|
||||
{
|
||||
uint8_t ctl_val;
|
||||
//配置P0_0-P0_7的端口为推挽输出模式
|
||||
esp_err_t err = IoexpandReadReg(CTL, &ctl_val);
|
||||
ctl_val |= (1 << 4); // 设置D[4]位为1(GPOMD=1),切换P0为推挽模式
|
||||
err = IoexpandWriteReg(CTL, ctl_val);
|
||||
if(err != ESP_OK){
|
||||
ESP_LOGE(TAG_I2C_IO_EXPAND_TASK, "配置P0端口失败,错误码:0x%x", err);
|
||||
return err;
|
||||
}
|
||||
else{
|
||||
ESP_LOGI(TAG_I2C_IO_EXPAND_TASK, "配置P0端口成功");
|
||||
}
|
||||
// 配置P0_0-P0_7的端口为输入还是输出:0-输出;1-输入
|
||||
// err = IoexpandWriteReg(CONFIG_PORT0, 0x04); // 0000 0100
|
||||
err = IoexpandWriteReg(CONFIG_PORT0, 0x24); // 0010 0100
|
||||
// err = IoexpandWriteReg(CONFIG_PORT0, 0x2C); // 0010 1100 0-2,0-3,0-5都是输入
|
||||
|
||||
// D 1101
|
||||
// 9 1001
|
||||
|
||||
if(err != ESP_OK){
|
||||
ESP_LOGE(TAG_I2C_IO_EXPAND_TASK, "配置P0端口失败,错误码:0x%x", err);
|
||||
return err;
|
||||
}
|
||||
else{
|
||||
ESP_LOGI(TAG_I2C_IO_EXPAND_TASK, "配置P0端口成功");
|
||||
}
|
||||
// 配置P1_0-P1_7的端口输出:0-输出;1-输入
|
||||
// err = IoexpandWriteReg(CONFIG_PORT1, 0x84);
|
||||
err = IoexpandWriteReg(CONFIG_PORT1, 0x80); // 1000 0000
|
||||
if(err != ESP_OK){
|
||||
ESP_LOGE(TAG_I2C_IO_EXPAND_TASK, "配置P1端口失败,错误码:0x%x", err);
|
||||
return err;
|
||||
}
|
||||
else{
|
||||
ESP_LOGI(TAG_I2C_IO_EXPAND_TASK, "配置P1端口成功");
|
||||
}
|
||||
// 配置P0_0-P0_7的初始为高电平
|
||||
// 配置P1_0-P1_7的初始为高电平
|
||||
err = IoexpandWriteReg(OUTPUT_PORT0, 0xFD); // 1111 1101
|
||||
if(err != ESP_OK){
|
||||
ESP_LOGE(TAG_I2C_IO_EXPAND_TASK, "配置P0端口初始值失败,错误码:0x%x", err);
|
||||
return err;
|
||||
}
|
||||
else{
|
||||
ESP_LOGI(TAG_I2C_IO_EXPAND_TASK, "配置P0端口初始值成功");
|
||||
}
|
||||
err = IoexpandWriteReg(OUTPUT_PORT1, 0x7E); // 0111 1110
|
||||
if(err != ESP_OK){
|
||||
ESP_LOGE(TAG_I2C_IO_EXPAND_TASK, "配置P1端口初始值失败,错误码:0x%x", err);
|
||||
return err;
|
||||
}
|
||||
else{
|
||||
ESP_LOGI(TAG_I2C_IO_EXPAND_TASK, "配置P1端口初始值成功");
|
||||
}
|
||||
|
||||
err = IoexpandWriteReg(INT_PORT1, 0x7F); // 0111 1111
|
||||
if(err != ESP_OK){
|
||||
ESP_LOGE(TAG_I2C_IO_EXPAND_TASK, "配置P1端口中断使能失败,错误码:0x%x", err);
|
||||
return err;
|
||||
}
|
||||
else{
|
||||
ESP_LOGI(TAG_I2C_IO_EXPAND_TASK, "配置P1端口中断使能成功");
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 设置步进电机的细分模式
|
||||
*/
|
||||
void IOExpansionBoard::SetStepperMicrostepMode(uint8_t mode, uint8_t OUTPUT_PORT, uint8_t m0_pin, uint8_t m1_pin)
|
||||
{
|
||||
uint8_t current_val;
|
||||
switch (mode) {
|
||||
case 1: //全步输出模式 低低电平
|
||||
/* code */
|
||||
printf("设置步进电机为全步模式\n");
|
||||
IoexpandReadReg(OUTPUT_PORT, ¤t_val);
|
||||
ESP_LOGW(TAG_I2C_IO_EXPAND_TASK, "0x%x", current_val);
|
||||
current_val &= ~(1 << m0_pin);
|
||||
ESP_LOGW(TAG_I2C_IO_EXPAND_TASK, "!!!!!!!!!0x%x", current_val);
|
||||
if(IoexpandWriteReg(OUTPUT_PORT, current_val) != ESP_OK){
|
||||
ESP_LOGE(TAG_I2C_IO_EXPAND_TASK, "设置步进电机细分模式失败");
|
||||
}
|
||||
IoexpandReadReg(OUTPUT_PORT, ¤t_val);
|
||||
ESP_LOGW(TAG_I2C_IO_EXPAND_TASK, "0x%x", current_val);
|
||||
current_val &= ~(1 << m1_pin);
|
||||
ESP_LOGW(TAG_I2C_IO_EXPAND_TASK, "!!!!!!!!!0x%x", current_val);
|
||||
if(IoexpandWriteReg(OUTPUT_PORT, current_val) != ESP_OK){
|
||||
ESP_LOGE(TAG_I2C_IO_EXPAND_TASK, "设置步进电机细分模式失败");
|
||||
}
|
||||
break;
|
||||
case 2: //非圆 1/2 高低电平
|
||||
/* code */
|
||||
IoexpandReadReg(OUTPUT_PORT, ¤t_val);
|
||||
ESP_LOGW(TAG_I2C_IO_EXPAND_TASK, "0x%x", current_val);
|
||||
current_val |= (1 << m0_pin);
|
||||
ESP_LOGW(TAG_I2C_IO_EXPAND_TASK, "!!!!!!!!!0x%x", current_val);
|
||||
if(IoexpandWriteReg(OUTPUT_PORT, current_val) != ESP_OK){
|
||||
ESP_LOGE(TAG_I2C_IO_EXPAND_TASK, "设置步进电机细分模式失败");
|
||||
}
|
||||
IoexpandReadReg(OUTPUT_PORT, ¤t_val);
|
||||
ESP_LOGW(TAG_I2C_IO_EXPAND_TASK, "0x%x", current_val);
|
||||
current_val &= ~(1 << m1_pin);
|
||||
ESP_LOGW(TAG_I2C_IO_EXPAND_TASK, "!!!!!!!!!0x%x", current_val);
|
||||
if(IoexpandWriteReg(OUTPUT_PORT, current_val) != ESP_OK){
|
||||
ESP_LOGE(TAG_I2C_IO_EXPAND_TASK, "设置步进电机细分模式失败");
|
||||
}
|
||||
break;
|
||||
case 3: //1/4 步 低高电平
|
||||
/* code */
|
||||
IoexpandReadReg(OUTPUT_PORT, ¤t_val);
|
||||
ESP_LOGW(TAG_I2C_IO_EXPAND_TASK, "0x%x", current_val);
|
||||
current_val &= ~(1 << m0_pin);
|
||||
ESP_LOGW(TAG_I2C_IO_EXPAND_TASK, "!!!!!!!!!0x%x", current_val);
|
||||
if(IoexpandWriteReg(OUTPUT_PORT, current_val) != ESP_OK){
|
||||
ESP_LOGE(TAG_I2C_IO_EXPAND_TASK, "设置步进电机细分模式失败");
|
||||
}
|
||||
IoexpandReadReg(OUTPUT_PORT, ¤t_val);
|
||||
ESP_LOGW(TAG_I2C_IO_EXPAND_TASK, "0x%x", current_val);
|
||||
current_val |= (1 << m1_pin);
|
||||
ESP_LOGW(TAG_I2C_IO_EXPAND_TASK, "!!!!!!!!!0x%x", current_val);
|
||||
if(IoexpandWriteReg(OUTPUT_PORT, current_val) != ESP_OK){
|
||||
ESP_LOGE(TAG_I2C_IO_EXPAND_TASK, "设置步进电机细分模式失败");
|
||||
}
|
||||
break;
|
||||
case 4: //1/8 步 高高电平
|
||||
/* code */
|
||||
printf("设置步进电机为1/8步模式\n");
|
||||
IoexpandReadReg(OUTPUT_PORT, ¤t_val);
|
||||
ESP_LOGW(TAG_I2C_IO_EXPAND_TASK, "0x%x", current_val);
|
||||
current_val |= (1 << m0_pin);
|
||||
ESP_LOGW(TAG_I2C_IO_EXPAND_TASK, "!!!!!!!!!0x%x", current_val);
|
||||
if(IoexpandWriteReg(OUTPUT_PORT, current_val) != ESP_OK){
|
||||
ESP_LOGE(TAG_I2C_IO_EXPAND_TASK, "设置步进电机细分模式失败");
|
||||
}
|
||||
IoexpandReadReg(OUTPUT_PORT, ¤t_val);
|
||||
ESP_LOGW(TAG_I2C_IO_EXPAND_TASK, "0x%x", current_val);
|
||||
current_val |= (1 << m1_pin);
|
||||
ESP_LOGW(TAG_I2C_IO_EXPAND_TASK, "!!!!!!!!!0x%x", current_val);
|
||||
if(IoexpandWriteReg(OUTPUT_PORT, current_val) != ESP_OK){
|
||||
ESP_LOGE(TAG_I2C_IO_EXPAND_TASK, "设置步进电机细分模式失败");
|
||||
}
|
||||
break;
|
||||
default: //全步输入模式 低低电平
|
||||
/* code */
|
||||
IoexpandReadReg(OUTPUT_PORT, ¤t_val);
|
||||
ESP_LOGW(TAG_I2C_IO_EXPAND_TASK, "0x%x", current_val);
|
||||
current_val &= ~(1 << m0_pin);
|
||||
ESP_LOGW(TAG_I2C_IO_EXPAND_TASK, "!!!!!!!!!0x%x", current_val);
|
||||
if(IoexpandWriteReg(OUTPUT_PORT, current_val) != ESP_OK){
|
||||
ESP_LOGE(TAG_I2C_IO_EXPAND_TASK, "设置步进电机细分模式失败");
|
||||
}
|
||||
IoexpandReadReg(OUTPUT_PORT, ¤t_val);
|
||||
ESP_LOGW(TAG_I2C_IO_EXPAND_TASK, "0x%x", current_val);
|
||||
current_val &= ~(1 << m1_pin);
|
||||
ESP_LOGW(TAG_I2C_IO_EXPAND_TASK, "!!!!!!!!!0x%x", current_val);
|
||||
if(IoexpandWriteReg(OUTPUT_PORT, current_val) != ESP_OK){
|
||||
ESP_LOGE(TAG_I2C_IO_EXPAND_TASK, "设置步进电机细分模式失败");
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 设置步进电机的使能
|
||||
*/
|
||||
esp_err_t IOExpansionBoard::SetMotorEnableMode(bool enable, uint8_t OUTPUT_PORT, uint8_t enable_pin)
|
||||
{
|
||||
uint8_t current_val;
|
||||
if(enable){
|
||||
// 进入工作状态mode
|
||||
IoexpandReadReg(OUTPUT_PORT, ¤t_val);
|
||||
ESP_LOGW(TAG_I2C_IO_EXPAND_TASK, "0x%x", current_val);
|
||||
current_val |= (1 << enable_pin);
|
||||
// ESP_LOGE(TAG_I2C_IO_EXPAND_TASK, "!!!!!!!!!0x%x", current_val);
|
||||
return IoexpandWriteReg(OUTPUT_PORT, current_val);
|
||||
}
|
||||
else{
|
||||
// 进入睡眠状态
|
||||
IoexpandReadReg(OUTPUT_PORT, ¤t_val);
|
||||
ESP_LOGW(TAG_I2C_IO_EXPAND_TASK, "0x%x", current_val);
|
||||
current_val &= ~(1 << enable_pin);
|
||||
// ESP_LOGE(TAG_I2C_IO_EXPAND_TASK, "!!!!!!!!!0x%x", current_val);
|
||||
return IoexpandWriteReg(OUTPUT_PORT, current_val);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @brief 设置步进电机运行方向
|
||||
*/
|
||||
esp_err_t IOExpansionBoard::StepperMotorSetDir(bool dir, uint8_t OUTPUT_PORT, uint8_t pin)
|
||||
{
|
||||
uint8_t current_val;
|
||||
if(dir){
|
||||
// 方向为正转
|
||||
IoexpandReadReg(OUTPUT_PORT, ¤t_val);
|
||||
ESP_LOGW(TAG_I2C_IO_EXPAND_TASK, "0x%x", current_val);
|
||||
current_val |= (1 << pin);
|
||||
// ESP_LOGE(TAG_I2C_IO_EXPAND_TASK, "!!!!!!!!!0x%x", current_val);
|
||||
return IoexpandWriteReg(OUTPUT_PORT, current_val);
|
||||
}
|
||||
else{
|
||||
IoexpandReadReg(OUTPUT_PORT, ¤t_val);
|
||||
ESP_LOGW(TAG_I2C_IO_EXPAND_TASK, "0x%x", current_val);
|
||||
current_val &= ~(1 << pin);
|
||||
// ESP_LOGE(TAG_I2C_IO_EXPAND_TASK, "!!!!!!!!!0x%x", current_val);
|
||||
return IoexpandWriteReg(OUTPUT_PORT, current_val);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief 设置步进电机是否进入睡眠或者工作状态(高电平进入工作状态,低电平进入睡眠状态)
|
||||
*/
|
||||
esp_err_t IOExpansionBoard::SetMotorSleepMode(bool mode, uint8_t OUTPUT_PORT, uint8_t nsleep_pin)
|
||||
{
|
||||
uint8_t current_val;
|
||||
if(mode){
|
||||
// 进入工作状态mode
|
||||
IoexpandReadReg(OUTPUT_PORT, ¤t_val);
|
||||
ESP_LOGW(TAG_I2C_IO_EXPAND_TASK, "0x%x", current_val);
|
||||
current_val |= (1 << nsleep_pin);
|
||||
// ESP_LOGE(TAG_I2C_IO_EXPAND_TASK, "!!!!!!!!!0x%x", current_val);
|
||||
return IoexpandWriteReg(OUTPUT_PORT, current_val);
|
||||
}
|
||||
else{
|
||||
// 进入睡眠状态
|
||||
IoexpandReadReg(OUTPUT_PORT, ¤t_val);
|
||||
ESP_LOGW(TAG_I2C_IO_EXPAND_TASK, "0x%x", current_val);
|
||||
current_val &= ~(1 << nsleep_pin);
|
||||
// ESP_LOGE(TAG_I2C_IO_EXPAND_TASK, "!!!!!!!!!0x%x", current_val);
|
||||
return IoexpandWriteReg(OUTPUT_PORT, current_val);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*********************************************IO扩展板LCD引脚配置参数***********************************************/
|
||||
/**
|
||||
* @brief 设置 LCD_BL引脚电平(高电平为命令模式,低电平为数据模式)
|
||||
*/
|
||||
esp_err_t IOExpansionBoard::SetLcdBlMode(bool mode, uint8_t OUTPUT_PORT, uint8_t bl_pin)
|
||||
{
|
||||
uint8_t current_val;
|
||||
if(mode){
|
||||
// 进入命令模式
|
||||
IoexpandReadReg(OUTPUT_PORT, ¤t_val);
|
||||
ESP_LOGW(TAG_I2C_IO_EXPAND_TASK, "0x%x", current_val);
|
||||
current_val |= (1 << bl_pin);
|
||||
// ESP_LOGE(TAG_I2C_IO_EXPAND_TASK, "!!!!!!!!!0x%x", current_val);
|
||||
return IoexpandWriteReg(OUTPUT_PORT, current_val);
|
||||
}
|
||||
else{
|
||||
// 进入数据模式
|
||||
IoexpandReadReg(OUTPUT_PORT, ¤t_val);
|
||||
ESP_LOGW(TAG_I2C_IO_EXPAND_TASK, "0x%x", current_val);
|
||||
current_val &= ~(1 << bl_pin);
|
||||
// ESP_LOGE(TAG_I2C_IO_EXPAND_TASK, "!!!!!!!!!0x%x", current_val);
|
||||
return IoexpandWriteReg(OUTPUT_PORT, current_val);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 设置 LCD_RST引脚电平(高电平为复位模式,低电平为工作模式)
|
||||
*/
|
||||
esp_err_t IOExpansionBoard::SetLcdResetMode(bool mode, uint8_t OUTPUT_PORT, uint8_t reset_pin)
|
||||
{
|
||||
uint8_t current_val;
|
||||
if(mode){
|
||||
// 进入复位模式
|
||||
IoexpandReadReg(OUTPUT_PORT, ¤t_val);
|
||||
ESP_LOGW(TAG_I2C_IO_EXPAND_TASK, "0x%x", current_val);
|
||||
current_val |= (1 << reset_pin);
|
||||
// ESP_LOGE(TAG_I2C_IO_EXPAND_TASK, "!!!!!!!!!0x%x", current_val);
|
||||
return IoexpandWriteReg(OUTPUT_PORT, current_val);
|
||||
}
|
||||
else{
|
||||
// 进入工作模式
|
||||
IoexpandReadReg(OUTPUT_PORT, ¤t_val);
|
||||
ESP_LOGW(TAG_I2C_IO_EXPAND_TASK, "0x%x", current_val);
|
||||
current_val &= ~(1 << reset_pin);
|
||||
// ESP_LOGE(TAG_I2C_IO_EXPAND_TASK, "!!!!!!!!!0x%x", current_val);
|
||||
return IoexpandWriteReg(OUTPUT_PORT, current_val);
|
||||
}
|
||||
}
|
||||
|
||||
/*********************************************IO扩展板的输入引脚配置以及中断引脚定义***********************************************/
|
||||
/**
|
||||
* @brief 设置 毫米波雷达的中断引脚
|
||||
*/
|
||||
esp_err_t IOExpansionBoard::SetRadarInterruptPin(bool mode, uint8_t INPUT_PORT, uint8_t interrupt_pin)
|
||||
{
|
||||
uint8_t current_val;
|
||||
if(mode){
|
||||
// 进入输入模式
|
||||
IoexpandReadReg(INPUT_PORT, ¤t_val);
|
||||
ESP_LOGW(TAG_I2C_IO_EXPAND_TASK, "0x%x", current_val);
|
||||
current_val |= (1 << interrupt_pin);
|
||||
// ESP_LOGE(TAG_I2C_IO_EXPAND_TASK, "!!!!!!!!!0x%x", current_val);
|
||||
return IoexpandWriteReg(INPUT_PORT, current_val);
|
||||
}
|
||||
else{
|
||||
// 进入输出模式
|
||||
IoexpandReadReg(INPUT_PORT, ¤t_val);
|
||||
ESP_LOGW(TAG_I2C_IO_EXPAND_TASK, "0x%x", current_val);
|
||||
current_val &= ~(1 << interrupt_pin);
|
||||
// ESP_LOGE(TAG_I2C_IO_EXPAND_TASK, "!!!!!!!!!0x%x", current_val);
|
||||
return IoexpandWriteReg(INPUT_PORT, current_val);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 设置 LCD_CS引脚电平(低电平为选中状态,高电平为不选中状态)
|
||||
*/
|
||||
esp_err_t IOExpansionBoard::SetLcdCsMode(bool mode, uint8_t OUTPUT_PORT, uint8_t cs_pin)
|
||||
{
|
||||
uint8_t current_val;
|
||||
if(mode){
|
||||
// 进入选中状态
|
||||
IoexpandReadReg(OUTPUT_PORT, ¤t_val);
|
||||
ESP_LOGW(TAG_I2C_IO_EXPAND_TASK, "0x%x", current_val);
|
||||
current_val &= ~(1 << cs_pin);
|
||||
// ESP_LOGE(TAG_I2C_IO_EXPAND_TASK, "!!!!!!!!!0x%x", current_val);
|
||||
return IoexpandWriteReg(OUTPUT_PORT, current_val);
|
||||
}
|
||||
else{
|
||||
// 进入不选中状态
|
||||
IoexpandReadReg(OUTPUT_PORT, ¤t_val);
|
||||
ESP_LOGW(TAG_I2C_IO_EXPAND_TASK, "0x%x", current_val);
|
||||
current_val |= (1 << cs_pin);
|
||||
// ESP_LOGE(TAG_I2C_IO_EXPAND_TASK, "!!!!!!!!!0x%x", current_val);
|
||||
return IoexpandWriteReg(OUTPUT_PORT, current_val);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @brief I2C数据读取任务主体
|
||||
*/
|
||||
void IOExpansionBoard::I2cReadTask(void* pvParameters)
|
||||
{
|
||||
IOExpansionBoard* instance = static_cast<IOExpansionBoard*>(pvParameters);
|
||||
if (!instance) {
|
||||
vTaskDelete(nullptr);
|
||||
return;
|
||||
}
|
||||
// 初始化复位引脚
|
||||
esp_err_t err = instance->ResetGpioInit(IO_EXPAND_RSTN);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG_GPIO_IO_EXPAND_DETECT, "GPIO复位初始化失败");
|
||||
}
|
||||
// 初始化IO扩展板子的中断引脚
|
||||
err = instance->InterruptGpioInit(GPIO_INPUT_PIN_SEL);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG_GPIO_IO_EXPAND_DETECT, "GPIO中断初始化失败");
|
||||
}
|
||||
// 设置IO扩展板模式
|
||||
instance->IoexpandSetMode();
|
||||
// 设置LCD屏幕背光引脚(初始为关闭)
|
||||
err = instance->SetLcdBlMode(LCD_BL_HIGH, LCD_BL_PORT, LCD_BL_PIN);
|
||||
if(err != ESP_OK){
|
||||
ESP_LOGE(TAG_GPIO_IO_EXPAND_DETECT, "设置LCD屏幕背光引脚失败");
|
||||
}
|
||||
else{
|
||||
ESP_LOGI(TAG_GPIO_IO_EXPAND_DETECT, "设置LCD屏幕背光引脚成功");
|
||||
}
|
||||
// 设置LCD屏幕复位引脚
|
||||
err = instance->SetLcdResetMode(LCD_RST_HIGH, LCD_RST_PORT, LCD_RST_PIN);
|
||||
if(err != ESP_OK){
|
||||
ESP_LOGE(TAG_GPIO_IO_EXPAND_DETECT, "设置LCD屏幕复位引脚失败");
|
||||
}
|
||||
else{
|
||||
ESP_LOGI(TAG_GPIO_IO_EXPAND_DETECT, "设置LCD屏幕复位引脚成功");
|
||||
}
|
||||
uint8_t current_val;
|
||||
for (;;) {
|
||||
// 等待中断事件触发
|
||||
if (instance->i2c_task_event_group_) {
|
||||
xEventGroupWaitBits(instance->i2c_task_event_group_, BIT0, pdTRUE, pdFALSE, portMAX_DELAY);
|
||||
}
|
||||
// 读取I2C数据
|
||||
instance->IoexpandReadReg(INPUT_PORT1,¤t_val);
|
||||
ESP_LOGI(TAG_I2C_IO_EXPAND_TASK, "读取数据: 0x%0X", current_val);
|
||||
if(current_val & (1 << 7)){
|
||||
ESP_LOGI(TAG_GPIO_IO_EXPAND_DETECT, "检测到中断来自雷达引脚(P1_7)\n");
|
||||
// 调用毫米波雷达回调函数
|
||||
if (instance->radar_) {
|
||||
instance->radar_->TriggerRadarDetectCallback();
|
||||
}
|
||||
}
|
||||
|
||||
// vTaskSuspend(nullptr); // 挂起任务等待下次唤醒
|
||||
}
|
||||
}
|
||||
|
||||
// bool IOExpansionBoard::AllocateStaticTaskMemory()
|
||||
// {
|
||||
// printf("IO拓展芯片创建任务前:Internal Free: %d bytes\n", heap_caps_get_free_size(MALLOC_CAP_INTERNAL));
|
||||
// printf("IO拓展芯片创建任务前 Free: %d bytes\n", heap_caps_get_free_size(MALLOC_CAP_SPIRAM));
|
||||
// // 分配任务栈(PSRAM)
|
||||
// const size_t TASK_STACK_SIZE = 4096;
|
||||
// pI2CReadTaskStackBuffer = (StackType_t*)heap_caps_malloc(
|
||||
// TASK_STACK_SIZE * sizeof(StackType_t),
|
||||
// MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT
|
||||
// );
|
||||
|
||||
// if (!pI2CReadTaskStackBuffer) {
|
||||
// ESP_LOGE(TAG_I2C_IO_EXPAND_TASK, "Failed to allocate task stack from PSRAM");
|
||||
// return false;
|
||||
// }
|
||||
|
||||
// // 分配任务控制块(内部RAM)
|
||||
// pxI2CReadTaskBuffer = (StaticTask_t*)pvPortMalloc(sizeof(StaticTask_t));
|
||||
// if (!pxI2CReadTaskBuffer) {
|
||||
// ESP_LOGE(TAG_I2C_IO_EXPAND_TASK, "Failed to allocate task TCB from internal RAM");
|
||||
// heap_caps_free(pI2CReadTaskStackBuffer);
|
||||
// pI2CReadTaskStackBuffer = nullptr;
|
||||
// return false;
|
||||
// }
|
||||
|
||||
// ESP_LOGI(TAG_I2C_IO_EXPAND_TASK, "Static task memory allocated successfully");
|
||||
// printf("IO拓展芯片创建任务后:Internal Free: %d bytes\n", heap_caps_get_free_size(MALLOC_CAP_INTERNAL));
|
||||
// printf("IO拓展芯片创建任务后 Free: %d bytes\n", heap_caps_get_free_size(MALLOC_CAP_SPIRAM));
|
||||
// return true;
|
||||
// }
|
||||
|
||||
// void IOExpansionBoard::FreeStaticTaskMemory()
|
||||
// {
|
||||
// if (pI2CReadTaskStackBuffer != nullptr) {
|
||||
// heap_caps_free(pI2CReadTaskStackBuffer);
|
||||
// pI2CReadTaskStackBuffer = nullptr;
|
||||
// }
|
||||
|
||||
// if (pxI2CReadTaskBuffer != nullptr) {
|
||||
// vPortFree(pxI2CReadTaskBuffer);
|
||||
// pxI2CReadTaskBuffer = nullptr;
|
||||
// }
|
||||
|
||||
// ESP_LOGI(TAG_I2C_IO_EXPAND_TASK, "Static task memory freed");
|
||||
// }
|
||||
|
||||
/**
|
||||
* @brief 创建I2C数据读取任务
|
||||
*/
|
||||
void IOExpansionBoard::CreateI2cReadTask()
|
||||
{
|
||||
printf("创建I2C读取任务之前:Internal Free: %d bytes\n", heap_caps_get_free_size(MALLOC_CAP_INTERNAL));
|
||||
printf("创建I2C读取任务之前:PSRAM Free: %d bytes\n", heap_caps_get_free_size(MALLOC_CAP_SPIRAM));
|
||||
if (xI2CReadTaskHandle_) {
|
||||
return; // 任务已创建
|
||||
}
|
||||
|
||||
xTaskCreateWithCaps(
|
||||
I2cReadTask,
|
||||
"i2c_read_task",
|
||||
I2C_TASK_STACK,
|
||||
this,
|
||||
I2C_TASK_PRIORITY,
|
||||
&xI2CReadTaskHandle_,
|
||||
MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT
|
||||
);
|
||||
|
||||
if (xI2CReadTaskHandle_ == NULL) {
|
||||
ESP_LOGE(TAG_I2C_IO_EXPAND_TASK, "Failed to create static I2C read task");
|
||||
} else {
|
||||
ESP_LOGI(TAG_I2C_IO_EXPAND_TASK, "Static I2C read task created successfully");
|
||||
}
|
||||
printf("创建I2C读取任务之后:Internal Free: %d bytes\n", heap_caps_get_free_size(MALLOC_CAP_INTERNAL));
|
||||
printf("创建I2C读取任务之后:PSRAM Free: %d bytes\n", heap_caps_get_free_size(MALLOC_CAP_SPIRAM));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 启动I2C任务 (整合初始化和任务创建)
|
||||
*/
|
||||
esp_err_t IOExpansionBoard::StartTask()
|
||||
{
|
||||
// 再创建任务
|
||||
if (!xI2CReadTaskHandle_) {
|
||||
CreateI2cReadTask();
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
@@ -0,0 +1,284 @@
|
||||
#ifndef IO_EXPANSION_BOARD_H
|
||||
#define IO_EXPANSION_BOARD_H
|
||||
|
||||
#include <cstdint>
|
||||
#include <esp_log.h>
|
||||
#include <esp_check.h>
|
||||
#include <esp_timer.h>
|
||||
#include <driver/gpio.h>
|
||||
#include "i2c_bus.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/event_groups.h"
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
#include <freertos/FreeRTOS.h>
|
||||
#include <freertos/task.h>
|
||||
#include <freertos/queue.h>
|
||||
#include <freertos/semphr.h>
|
||||
#include "esp_err.h"
|
||||
#include "config.h"
|
||||
#include "portmacro.h"
|
||||
|
||||
// 前向声明,避免循环引用
|
||||
class MillimeterWaveRadar;
|
||||
|
||||
/* 寄存器地址 */
|
||||
#define INPUT_PORT0 0x00 // 输入端口0寄存器
|
||||
#define INPUT_PORT1 0x01 // 输入端口1寄存器 0为低电平(仅支持读取)
|
||||
#define OUTPUT_PORT0 0x02 // 输出端口0寄存器
|
||||
#define OUTPUT_PORT1 0x03 // 输出端口1寄存器 0为低电平
|
||||
#define CONFIG_PORT0 0x04 // 配置端口0寄存器
|
||||
#define CONFIG_PORT1 0x05 // 配置端口1寄存器 0为输出模式
|
||||
#define INT_PORT0 0x06 // 中断端口0寄存器
|
||||
#define INT_PORT1 0x07 // 中断端口1寄存器 0为使能中断(根据手册默认是使能的)
|
||||
#define CTL 0x11 // 全局控制寄存器
|
||||
#define ID 0x23 // 芯片ID寄存器(0x23)
|
||||
|
||||
/***********************************IO扩展板电机引脚配置参数*************************************/
|
||||
/* 设置步进电机方向 */
|
||||
#define STEPPER_MOTOR_LEFT false //步进电机的方向为左转
|
||||
#define STEPPER_MOTOR_RIGHT true //步进电机的方向为右转
|
||||
#define STEPPER_MOTOR_DIR_PORT OUTPUT_PORT0 //步进电机方向引脚挂载在IO扩展板的输出端口OUTPUT_PORT0
|
||||
#define STEPPER_MOTOR_DIR_PIN 4 //步进电机方向引脚对应的IO扩展板引脚P0_4
|
||||
|
||||
/* 设置步进电机细分模式 */
|
||||
#define STEPPER_MOTOR_M0_PIN 5 //步进电机细分模式选择引脚对应IO扩展板引脚P1_5
|
||||
#define STEPPER_MOTOR_M1_PIN 4 //步进电机细分模式选择引脚对应IO扩展板引脚P1_4
|
||||
#define STEPPER_MOTOR_MADE_PORT OUTPUT_PORT1 //步进电机模式选择引脚挂载在IO扩展板的输出端口OUTPUT_PORT1
|
||||
|
||||
|
||||
/* 设置步进电机睡眠引脚 */
|
||||
#define STEPPER_MOTOR_SLEEP false //步进电机进入睡眠模式
|
||||
#define STEPPER_MOTOR_WORK true //步进电机进入工作模式
|
||||
#define STEPPER_MOTOR_SLEEP_PIN 6 //步进电机睡眠引脚对应IO扩展板引脚P1_6
|
||||
#define STEPPER_MOTOR_SLEEP_PORT OUTPUT_PORT1 //步进电机睡眠引脚挂载在IO扩展板的输出端口OUTPUT_PORT1
|
||||
|
||||
/* 设置电机的使能引脚 */
|
||||
#define STEPPER_MOTOR_ENABLE_PIN 7 //电机使能引脚对应IO扩展板引脚P0_7
|
||||
#define STEPPER_MOTOR_ENABLE_PORT OUTPUT_PORT0 //电机使能引脚挂载在IO扩展板的输出端口OUTPUT_PORT0
|
||||
#define STEPPER_MOTOR_ENABLE_ENABLE true //电机使能引脚状态为高电平
|
||||
#define STEPPER_MOTOR_ENABLE_DISABLE false //电机使能引脚状态为低电平
|
||||
|
||||
/* 设置毫米波雷达对应IO扩展板的中断引脚 */
|
||||
#define RADAR_INTERRUPT_PIN 7 //毫米波雷达中断引脚对应IO扩展板引脚P1_7
|
||||
#define RADAR_INTERRUPT_PORT CONFIG_PORT1 //毫米波雷达中断引脚挂载在IO扩展板的输入端口INPUT_PORT1
|
||||
#define RADAR_INTERRUPT_ENABLE true //毫米波雷达中断引脚状态为输入状态
|
||||
#define RADAR_INTERRUPT_DISABLE false //毫米波雷达中断引脚状态为输出状态
|
||||
/* 任务配置常量 */
|
||||
#define WRITE_BUF_SIZE 2 // I2C单次写入字节数
|
||||
#define READ_BUF_SIZE 2 // I2C单次读取字节数
|
||||
#define I2C_TASK_PRIORITY 2 // 任务优先级(中等)
|
||||
#define I2C_TASK_STACK 4096 // 任务栈大小(4KB)
|
||||
|
||||
/***********************************IO扩展板LCD引脚配置参数*************************************/
|
||||
/* 设置LCD的BL引脚 */
|
||||
#define LCD_BL_PIN 6 //LCD背光引脚
|
||||
#define LCD_BL_PORT OUTPUT_PORT0 //LCD背光引脚挂载在IO扩展板的输出端口OUTPUT_PORT0
|
||||
#define LCD_BL_HIGH true //LCD背光引脚状态为高电平
|
||||
#define LCD_BL_LOW false //LCD背光引脚状态为低电平
|
||||
|
||||
/* 设置LCD的RST引脚 */
|
||||
#define LCD_RST_PIN 1 //LCD复位引脚
|
||||
#define LCD_RST_PORT OUTPUT_PORT1 //LCD复位引脚挂载在IO扩展板的输出端口OUTPUT_PORT1
|
||||
#define LCD_RST_HIGH true //LCD复位引脚状态为高电平
|
||||
#define LCD_RST_LOW false //LCD复位引脚状态为低电平
|
||||
|
||||
/* 设置LCD的CS引脚 */
|
||||
#define LCD_CS_PIN 2 //LCD片选引脚
|
||||
#define LCD_CS_PORT OUTPUT_PORT1 //LCD片选引脚挂载在IO扩展板的输出端口OUTPUT_PORT1
|
||||
#define LCD_CS_HIGH true //LCD片选引脚状态为高电平
|
||||
#define LCD_CS_LOW false //LCD片选引脚状态为低电平
|
||||
|
||||
#define TAG_GPIO_IO_EXPAND_DETECT "GPIO_IO_EXPAND_DETECT" // GPIO中断检测日志标签
|
||||
#define TAG_I2C_IO_EXPAND_TASK "I2C_IO_EXPAND_TASK" // I2CIO扩展板任务日志标签
|
||||
|
||||
// GPIO引脚定义
|
||||
#define GPIO_INPUT_PIN_SEL GPIO_NUM_10 // IO扩展板中断检测引脚
|
||||
#define IO_EXPAND_RSTN GPIO_NUM_45 // IO扩展板复位引脚
|
||||
|
||||
/**
|
||||
* @class IOExpansionBoard
|
||||
* @brief I/O扩展板驱动类,封装AW9523BTQR芯片操作
|
||||
*/
|
||||
class IOExpansionBoard
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief 构造函数
|
||||
*/
|
||||
IOExpansionBoard();
|
||||
|
||||
/**
|
||||
* @brief 设置毫米波雷达指针
|
||||
* @param radar 毫米波雷达对象指针
|
||||
*/
|
||||
void SetRadar(MillimeterWaveRadar* radar) { radar_ = radar; };
|
||||
|
||||
/**
|
||||
* @brief 析构函数
|
||||
*/
|
||||
~IOExpansionBoard();
|
||||
|
||||
/**
|
||||
* @brief 初始化GPIO中断检测
|
||||
* @param gpio_num 中断引脚编号
|
||||
* @return esp_err_t 初始化结果
|
||||
*/
|
||||
esp_err_t InterruptGpioInit(gpio_num_t gpio_num);
|
||||
|
||||
/**
|
||||
* @brief 初始化IO扩展板复位引脚
|
||||
* @param gpio_num 复位引脚编号
|
||||
* @return esp_err_t 初始化结果
|
||||
*/
|
||||
esp_err_t ResetGpioInit(gpio_num_t gpio_num);
|
||||
|
||||
/**
|
||||
* @brief 初始化IO扩展板复位引脚
|
||||
* @param gpio_num 复位引脚编号
|
||||
* @return esp_err_t 初始化结果
|
||||
*/
|
||||
esp_err_t ResetIoExpand();
|
||||
|
||||
/**
|
||||
* @brief 初始化I2C主机通信
|
||||
* @return esp_err_t 初始化结果
|
||||
*/
|
||||
// esp_err_t IoExpansionI2cInit();
|
||||
|
||||
/**
|
||||
* @brief 创建I2C数据读取任务
|
||||
*/
|
||||
void CreateI2cReadTask();
|
||||
|
||||
/**
|
||||
* @brief 启动I2C任务(整合初始化和任务创建)
|
||||
* @return esp_err_t 操作结果
|
||||
*/
|
||||
esp_err_t StartTask();
|
||||
|
||||
/**
|
||||
* @brief 写寄存器数据
|
||||
* @param reg_addr 寄存器地址
|
||||
* @param data 要写入的数据
|
||||
* @return esp_err_t 操作结果
|
||||
*/
|
||||
esp_err_t IoexpandWriteReg(uint8_t reg_addr, uint8_t data);
|
||||
|
||||
/**
|
||||
* @brief 读寄存器数据
|
||||
* @param reg_addr 寄存器地址
|
||||
* @param data 要读出的数据
|
||||
* @return esp_err_t 操作结果
|
||||
*/
|
||||
esp_err_t IoexpandReadReg(uint8_t reg_addr, uint8_t *data);
|
||||
|
||||
// /**
|
||||
// * @brief 设置IO扩展板GPIO中断状态 通过读取Input_Port0 和 Input_Port1 寄存器可以清除中断
|
||||
// * @param reg_addr 寄存器地址
|
||||
// * @return esp_err_t 操作结果
|
||||
// */
|
||||
// esp_err_t SetInterruptStatus(bool status);
|
||||
|
||||
/**
|
||||
* @brief 配置IO扩展版上的IO口为输出还是输入,并且设置初始为高电平
|
||||
* @return esp_err_t 操作结果
|
||||
*/
|
||||
esp_err_t IoexpandSetMode();
|
||||
|
||||
/**
|
||||
* @brief 设置步进电机的细分模式
|
||||
* @param mode 模式:1/2/4/8/16/32/64
|
||||
* @return esp_err_t 操作结果
|
||||
*/
|
||||
void SetStepperMicrostepMode(uint8_t mode, uint8_t OUTPUT_PORT, uint8_t m0_pin, uint8_t m1_pin);
|
||||
|
||||
/**
|
||||
* @brief 设置步进电机的方向
|
||||
* @param dir 方向
|
||||
* @param OUTPUT_PORT 输出端口
|
||||
* @param pin 引脚号
|
||||
* @return esp_err_t 操作结果
|
||||
*/
|
||||
esp_err_t StepperMotorSetDir(bool dir, uint8_t OUTPUT_PORT, uint8_t pin);
|
||||
|
||||
/**
|
||||
* @brief 设置步进电机的睡眠模式
|
||||
* @param 是否进入睡眠模式
|
||||
* @param 输出端口
|
||||
* @param 引脚号
|
||||
* @return esp_err_t 操作结果
|
||||
*/
|
||||
esp_err_t SetMotorSleepMode(bool mode, uint8_t OUTPUT_PORT, uint8_t nsleep_pin);
|
||||
|
||||
/**
|
||||
* @brief 设置步进电机的使能引脚状态
|
||||
* @param 使能状态
|
||||
* @return esp_err_t 操作结果
|
||||
*/
|
||||
esp_err_t SetMotorEnableMode(bool enable, uint8_t OUTPUT_PORT, uint8_t enable_pin);
|
||||
|
||||
/**
|
||||
* @brief 设置LCD的BL引脚状态
|
||||
* @param BL状态
|
||||
* @return esp_err_t 操作结果
|
||||
*/
|
||||
esp_err_t SetLcdBlMode(bool mode, uint8_t OUTPUT_PORT, uint8_t bl_pin);
|
||||
|
||||
/**
|
||||
* @brief 设置LCD的RST引脚状态
|
||||
* @param RST状态
|
||||
* @return esp_err_t 操作结果
|
||||
*/
|
||||
esp_err_t SetLcdResetMode(bool mode, uint8_t OUTPUT_PORT, uint8_t rst_pin);
|
||||
|
||||
/**
|
||||
* @brief 设置LCD的CS引脚状态
|
||||
* @param CS状态(低电平为选中状态,高电平为不选中状态)
|
||||
* @return esp_err_t 操作结果
|
||||
*/
|
||||
esp_err_t SetLcdCsMode(bool mode, uint8_t OUTPUT_PORT, uint8_t cs_pin);
|
||||
|
||||
/**
|
||||
* @brief 设置雷达中断引脚
|
||||
* @param 毫米波雷达的中断引脚模式
|
||||
* @param 输入端口
|
||||
* @param 引脚号
|
||||
* @return esp_err_t 操作结果
|
||||
*/
|
||||
esp_err_t SetRadarInterruptPin(bool mode, uint8_t INPUT_PORT, uint8_t interrupt_pin);
|
||||
|
||||
// 公共成员变量
|
||||
i2c_bus_handle_t bus_handle_ = nullptr; // I2C总线句柄
|
||||
uint8_t device_addr_; // I2C设备地址
|
||||
|
||||
private:
|
||||
// 静态成员函数
|
||||
MillimeterWaveRadar* radar_ = nullptr; // 毫米波雷达指针,用于触发回调
|
||||
static void IRAM_ATTR GpioIsrHandler(void* arg); // 中断处理函数
|
||||
static void I2cReadTask(void* pvParameters); // I2C数据读取任务函数
|
||||
|
||||
// /**
|
||||
// * @brief 分配静态任务所需的内存
|
||||
// * @return bool 分配是否成功
|
||||
// */
|
||||
// bool AllocateStaticTaskMemory();
|
||||
|
||||
// /**
|
||||
// * @brief 释放静态任务分配的内存
|
||||
// */
|
||||
// void FreeStaticTaskMemory();
|
||||
|
||||
// 实例成员变量
|
||||
EventGroupHandle_t i2c_task_event_group_ = nullptr; // 事件组
|
||||
TaskHandle_t xI2CReadTaskHandle_ = nullptr; // 任务句柄
|
||||
bool is_initialized_ = false; // 初始化状态标记(新增)
|
||||
gpio_num_t interrupt_gpio_ = GPIO_NUM_NC; // 中断引脚
|
||||
gpio_num_t reset_gpio_ = GPIO_NUM_NC; // 复位引脚
|
||||
|
||||
// StackType_t* pI2CReadTaskStackBuffer = nullptr; // 任务栈指针(PSRAM)
|
||||
// StaticTask_t* pxI2CReadTaskBuffer = nullptr; // 任务控制块指针(内部RAM)
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,257 @@
|
||||
/**
|
||||
* @file board.cc
|
||||
* @brief 板级外设初始化类,包含步进电机、毫米波雷达、I2C总线等外设的初始化函数。
|
||||
* @author zouyuhua
|
||||
* @date 2025年8月7日
|
||||
*
|
||||
*/
|
||||
|
||||
extern "C" {
|
||||
#include "esp_log.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "driver/uart.h"
|
||||
#include "driver/ledc.h"
|
||||
#include "esp_err.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "hal/gpio_types.h"
|
||||
#include "hal/uart_types.h"
|
||||
#include "esp_check.h"
|
||||
#include "sdkconfig.h"
|
||||
#include "i2c_bus.h"
|
||||
}
|
||||
|
||||
#include "board_sweekar.h"
|
||||
#include "config.h"
|
||||
#define TAG "board_sweekar"
|
||||
/**
|
||||
* @file board.h
|
||||
* @brief 板级外设初始化类
|
||||
*/
|
||||
/**
|
||||
* @brief 步进电机初始化函数
|
||||
*
|
||||
* 配置LEDC定时器和通道用于PWM输出,设置步进电机的工作模式、使能状态、细分模式和方向,
|
||||
* 并初始化PWM占空比为50%。初始化过程中若出现错误,会通过ESP_LOGE输出错误信息及错误码。
|
||||
*/
|
||||
void BoardSweekar::StepperMotorInit(void)
|
||||
{
|
||||
// 配置LEDC用于PWM输出
|
||||
ledc_timer_config_t ledc_timer = {
|
||||
.speed_mode = LEDC_MODE,
|
||||
.duty_resolution = LEDC_DUTY_RES,
|
||||
.timer_num = LEDC_TIMER,
|
||||
.freq_hz = LEDC_FREQ_HZ,
|
||||
.clk_cfg = LEDC_USE_APB_CLK,
|
||||
};
|
||||
esp_err_t err = ledc_timer_config(&ledc_timer);
|
||||
if (err != ESP_OK){
|
||||
ESP_LOGE(TAG_BOARD, "步进电机LEDC定时器配置失败,错误码: 0x%x", err);
|
||||
}
|
||||
|
||||
// 配置LEDC通道
|
||||
ledc_channel_config_t ledc_channel = {
|
||||
.gpio_num = LEDC_OUTPUT_IO,
|
||||
.speed_mode = LEDC_MODE,
|
||||
.channel = LEDC_CHANNEL,
|
||||
.timer_sel = LEDC_TIMER,
|
||||
.duty = 0, // 初始占空比0
|
||||
.hpoint = 0
|
||||
};
|
||||
err = ledc_channel_config(&ledc_channel);
|
||||
if (err != ESP_OK){
|
||||
ESP_LOGE(TAG_BOARD, "步进电机LEDC通道配置失败,错误码: 0x%x", err);
|
||||
}
|
||||
|
||||
// 检查I2C总线是否已初始化
|
||||
if (bus_handle_ == nullptr) {
|
||||
ESP_LOGE(TAG_BOARD, "I2C总线未初始化,请先调用I2CMasterInit()");
|
||||
return;
|
||||
}
|
||||
|
||||
// 设置步进电机工作模式,使能电机,设置步进电机细分模式,设置步进电机方向
|
||||
err = io_expansion_.SetMotorSleepMode(STEPPER_MOTOR_WORK, STEPPER_MOTOR_SLEEP_PORT, STEPPER_MOTOR_WORK);
|
||||
if (err != ESP_OK){
|
||||
ESP_LOGE(TAG_BOARD, "步进电机初始化失败,错误码: 0x%x", err);
|
||||
}
|
||||
err = io_expansion_.SetMotorEnableMode(STEPPER_MOTOR_ENABLE_DISABLE, STEPPER_MOTOR_ENABLE_PORT, STEPPER_MOTOR_ENABLE_PIN);
|
||||
if (err != ESP_OK){
|
||||
ESP_LOGE(TAG_BOARD, "步进电机初始化失败,错误码: 0x%x", err);
|
||||
}
|
||||
io_expansion_.SetStepperMicrostepMode(4, STEPPER_MOTOR_MADE_PORT, STEPPER_MOTOR_M0_PIN, STEPPER_MOTOR_M1_PIN);
|
||||
err = io_expansion_.StepperMotorSetDir(STEPPER_MOTOR_LEFT, STEPPER_MOTOR_DIR_PORT, STEPPER_MOTOR_DIR_PIN);
|
||||
if (err != ESP_OK){
|
||||
ESP_LOGE(TAG_BOARD, "步进电机初始化失败,错误码: 0x%x", err);
|
||||
}
|
||||
|
||||
// 初始PWM占空比设为0%
|
||||
ledc_set_duty(LEDC_MODE, LEDC_CHANNEL, 0);
|
||||
ledc_update_duty(LEDC_MODE, LEDC_CHANNEL);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 毫米波雷达串口初始化函数
|
||||
*
|
||||
* 配置毫米波雷达所使用的串口参数(波特率、数据位、校验位、停止位等),设置串口引脚,
|
||||
* 并安装串口驱动。采用较大的RX/TX FIFO深度以处理突发数据,禁用驱动自带事件队列以避免
|
||||
* 与自定义中断冲突。
|
||||
*/
|
||||
void BoardSweekar::MillimeterWaveRadarUartInit(void)
|
||||
{
|
||||
uart_config_t uart_config = {
|
||||
.baud_rate = RADAR_BAUD_RATE,
|
||||
.data_bits = UART_DATA_8_BITS,
|
||||
.parity = UART_PARITY_DISABLE,
|
||||
.stop_bits = UART_STOP_BITS_1,
|
||||
.flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
|
||||
.source_clk = UART_SCLK_DEFAULT,
|
||||
};
|
||||
|
||||
// 1. 设置串口参数
|
||||
ESP_ERROR_CHECK(uart_param_config(RADAR_UART_NUM, &uart_config));
|
||||
|
||||
// 2. 设置 UART 引脚
|
||||
ESP_ERROR_CHECK(uart_set_pin(RADAR_UART_NUM, UART_TX_PIN, UART_RX_PIN,
|
||||
UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE));
|
||||
|
||||
// 3. 安装 UART 驱动(禁用驱动自带事件队列,避免与自定义中断冲突)
|
||||
// 增加 RX/TX FIFO 深度以处理突发数据
|
||||
ESP_ERROR_CHECK(uart_driver_install(RADAR_UART_NUM, RADAR_BUF_SIZE * 4, RADAR_BUF_SIZE * 4,
|
||||
0, NULL, 0));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 毫米波雷达中断引脚初始化函数
|
||||
*
|
||||
* 配置毫米波雷达中断引脚为输入模式,禁用上拉电阻,使能下拉电阻,初始禁用中断功能
|
||||
* (如需使用中断需单独进行配置)。
|
||||
*/
|
||||
void BoardSweekar::MillimeterWaveRadarGpioInit(void)
|
||||
{
|
||||
// GPIO配置结构体
|
||||
gpio_config_t io_conf = {
|
||||
.pin_bit_mask = (1ULL << MILLIMETER_WAVE_RADAR_PIN), // 选择GPIO引脚
|
||||
.mode = GPIO_MODE_INPUT, // 设置为输入模式
|
||||
.pull_up_en = GPIO_PULLUP_DISABLE,
|
||||
.pull_down_en = GPIO_PULLDOWN_ENABLE, // 使能下拉
|
||||
.intr_type = GPIO_INTR_DISABLE // 禁用中断(如需中断需单独配置)
|
||||
};
|
||||
|
||||
// 配置GPIO
|
||||
gpio_config(&io_conf);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief I2C总线及从机设备初始化函数
|
||||
*
|
||||
* 首先配置并创建I2C主机总线,然后依次添加IO扩展板和线性马达作为I2C从机设备到总线上。
|
||||
* 若总线创建或设备添加失败,会输出错误信息并进行相应的资源清理(删除已创建的总线)。
|
||||
* 初始化成功后,会通过ESP_LOGI输出IO扩展板和线性马达的从机地址信息。
|
||||
*
|
||||
* @return esp_err_t 初始化结果,ESP_OK表示成功,其他错误码表示相应的失败原因
|
||||
*/
|
||||
esp_err_t BoardSweekar::I2CMasterInit(void)
|
||||
{
|
||||
static const char *I2C_INIT = "I2C_INIT";
|
||||
|
||||
// 初始化IO扩展板复位引脚
|
||||
gpio_config_t reset_io_conf = {
|
||||
.pin_bit_mask = (1ULL << IO_EXPAND_RSTN),
|
||||
.mode = GPIO_MODE_OUTPUT,
|
||||
.pull_up_en = GPIO_PULLUP_ENABLE, // 使能上拉
|
||||
.pull_down_en = GPIO_PULLDOWN_DISABLE,
|
||||
.intr_type = GPIO_INTR_DISABLE
|
||||
};
|
||||
gpio_config(&reset_io_conf);
|
||||
|
||||
// 执行复位时序:先拉低100ms,再拉高并等待100ms
|
||||
gpio_set_level(IO_EXPAND_RSTN, 0); // 拉低复位
|
||||
vTaskDelay(pdMS_TO_TICKS(100)); // 等待100ms
|
||||
gpio_set_level(IO_EXPAND_RSTN, 1); // 释放复位
|
||||
vTaskDelay(pdMS_TO_TICKS(100)); // 等待设备启动
|
||||
|
||||
ESP_LOGI(I2C_INIT, "IO扩展板复位完成");
|
||||
|
||||
// 创建统一的I2C总线(使用ESP-ADF的i2c_bus)
|
||||
i2c_config_t i2c_cfg = {
|
||||
.mode = I2C_MODE_MASTER,
|
||||
.sda_io_num = I2C0_MASTER_SDA_IO,
|
||||
.scl_io_num = I2C0_MASTER_SCL_IO,
|
||||
.sda_pullup_en = GPIO_PULLUP_ENABLE,
|
||||
.scl_pullup_en = GPIO_PULLUP_ENABLE,
|
||||
.master = {
|
||||
.clk_speed = 100000,
|
||||
},
|
||||
};
|
||||
|
||||
// 创建I2C总线(ESP-ADF的audio_board_init会复用这个总线)
|
||||
bus_handle_ = i2c_bus_create(I2C0_MASTER_PORT, &i2c_cfg);
|
||||
if (bus_handle_ == NULL) {
|
||||
ESP_LOGE(TAG, "Failed to create I2C bus");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
vTaskDelay(pdMS_TO_TICKS(100)); // 等待设备启动
|
||||
// ESP-ADF的i2c_bus不需要单独添加设备,直接通过总线句柄和设备地址进行通信
|
||||
|
||||
// 验证线性马达设备是否存在
|
||||
esp_err_t err = i2c_bus_probe_addr(bus_handle_, LINEAR_MOTOR_I2C_SLAVE_ADDR << 1);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(I2C_INIT, "线性马达设备未找到(地址:0x%02X),错误码: 0x%x", LINEAR_MOTOR_I2C_SLAVE_ADDR, err);
|
||||
// 不返回错误,继续初始化
|
||||
} else {
|
||||
ESP_LOGI(I2C_INIT, "线性马达设备检测成功(地址:0x%02X)", LINEAR_MOTOR_I2C_SLAVE_ADDR);
|
||||
}
|
||||
// 验证IO扩展板设备是否存在
|
||||
err = i2c_bus_probe_addr(bus_handle_, I2C_IO_EXPAND_SLAVE_ADDR << 1);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(I2C_INIT, "IO扩展板设备未找到(地址:0x%02X),错误码: 0x%x", I2C_IO_EXPAND_SLAVE_ADDR, err);
|
||||
// 不返回错误,继续初始化其他设备
|
||||
} else {
|
||||
ESP_LOGI(I2C_INIT, "IO扩展板设备检测成功(地址:0x%02X)", I2C_IO_EXPAND_SLAVE_ADDR);
|
||||
}
|
||||
// 验证陀螺仪设备是否存在
|
||||
err = i2c_bus_probe_addr(bus_handle_, GYROSCOPE_I2C_SLAVE_ADDR << 1);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(I2C_INIT, "陀螺仪设备未找到(地址:0x%02X),错误码: 0x%x", GYROSCOPE_I2C_SLAVE_ADDR, err);
|
||||
// 不返回错误,继续初始化
|
||||
} else {
|
||||
ESP_LOGI(I2C_INIT, "陀螺仪设备检测成功(地址:0x%02X)", GYROSCOPE_I2C_SLAVE_ADDR);
|
||||
}
|
||||
|
||||
// 为IO扩展板设置总线句柄和设备地址(使用7位地址)
|
||||
io_expansion_.bus_handle_ = bus_handle_;
|
||||
io_expansion_.device_addr_ = I2C_IO_EXPAND_SLAVE_ADDR << 1;
|
||||
|
||||
// 为线性马达设置总线句柄和设备地址(使用7位地址)
|
||||
linear_motor_.bus_handle_ = bus_handle_;
|
||||
linear_motor_.device_addr_ = LINEAR_MOTOR_I2C_SLAVE_ADDR << 1;
|
||||
|
||||
ESP_LOGI(I2C_INIT, "I2C总线初始化完成");
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 开启VBAT to VBAT_5V
|
||||
*
|
||||
* 创建开启升压的电源管理单元
|
||||
*
|
||||
*/
|
||||
void BoardSweekar::VbatToVbat5vInit(void)
|
||||
{
|
||||
// 配置VBAT_5V引脚为输出模式
|
||||
gpio_config_t io_conf = {
|
||||
.pin_bit_mask = (1ULL << VBAT_5V_PIN),
|
||||
.mode = GPIO_MODE_OUTPUT,
|
||||
.pull_up_en = GPIO_PULLUP_DISABLE,
|
||||
.pull_down_en = GPIO_PULLDOWN_DISABLE,
|
||||
.intr_type = GPIO_INTR_DISABLE
|
||||
};
|
||||
gpio_config(&io_conf);
|
||||
// 使能VBAT_5V
|
||||
gpio_set_level(VBAT_5V_PIN, 1);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
#ifndef __BOARD_H__
|
||||
#define __BOARD_H__
|
||||
#include "config.h"
|
||||
#include "io_expansion_board.h"
|
||||
#include "stepper_motor.h"
|
||||
#include "i2c_bus.h"
|
||||
#include "gyroscope.h"
|
||||
#include "touch_sensor.h"
|
||||
|
||||
class BoardSweekar
|
||||
{
|
||||
private:
|
||||
i2c_bus_handle_t bus_handle_ = nullptr; // 使用ESP-ADF的I2C总线句柄
|
||||
|
||||
public:
|
||||
IOExpansionBoard io_expansion_; // IO扩展板对象
|
||||
LinearMotor linear_motor_; // 线性马达对象
|
||||
Gyroscope gyroscope_; // 陀螺仪对象
|
||||
TouchSensor touch_sensor_; // 触摸传感器对象
|
||||
// 初始化步进电机
|
||||
void StepperMotorInit(void);
|
||||
|
||||
// 初始化串口
|
||||
void MillimeterWaveRadarUartInit(void);
|
||||
|
||||
//初始化毫米波雷达的中断引脚
|
||||
void MillimeterWaveRadarGpioInit(void);
|
||||
|
||||
// 初始化I2C总线
|
||||
esp_err_t I2CMasterInit(void);
|
||||
|
||||
// 初始化VBAT toVBAT_5V引脚
|
||||
void VbatToVbat5vInit(void);
|
||||
|
||||
// 获取I2C总线句柄
|
||||
i2c_bus_handle_t GetBusHandle() const { return bus_handle_; }
|
||||
};
|
||||
#endif
|
||||
@@ -0,0 +1,139 @@
|
||||
/* 定义引脚分配 */
|
||||
#ifndef _BOARD_CONFIG_H_
|
||||
#define _BOARD_CONFIG_H_
|
||||
|
||||
/**
|
||||
* @file config.h
|
||||
* @brief 定义了引脚的分配。
|
||||
* @author zouyuhua
|
||||
* @date 2025年8月7日
|
||||
*
|
||||
*/
|
||||
|
||||
#include "driver/gpio.h"
|
||||
#include "driver/i2c_master.h"
|
||||
#include "driver/i2s.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_rom_sys.h" // 用于 esp_rom_delay_us
|
||||
#include "esp_timer.h"
|
||||
#include "esp_mac.h"
|
||||
#include "driver/ledc.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "esp_log.h"
|
||||
#include "driver/timer.h"
|
||||
#include "esp_intr_alloc.h"
|
||||
#include "soc/timer_group_struct.h" // 包含TIMERG0、TIMERG1的结构体定义
|
||||
#include "soc/timer_group_reg.h" // 包含定时器相关寄存器宏定义
|
||||
#include "driver/uart.h"
|
||||
#include "esp_err.h"
|
||||
#include "freertos/queue.h"
|
||||
#include "soc/uart_reg.h"
|
||||
#include "linear_motor.h"
|
||||
#include "gyroscope.h"
|
||||
|
||||
#define TAG_BOARD "SWEEKAR_ESP32"
|
||||
/*I2C总线引脚定义*/
|
||||
#define I2C0_MASTER_PORT I2C_NUM_0
|
||||
#define I2C0_MASTER_SDA_IO GPIO_NUM_2
|
||||
#define I2C0_MASTER_SCL_IO GPIO_NUM_3
|
||||
|
||||
/* 步进电机引脚设置 */
|
||||
#define LEDC_OUTPUT_IO GPIO_NUM_42 // 步进电机LEDC引脚输入
|
||||
|
||||
/* 定义屏幕驱动控制引脚 */
|
||||
#define ST7789_PIN_CLK GPIO_NUM_48 // SPI时钟引脚
|
||||
#define ST7789_PIN_DC GPIO_NUM_38 // 数据/命令选择引脚RSEL
|
||||
#define ST7789_PIN_MOSI GPIO_NUM_47 // SPI数据输出引脚
|
||||
#define ST7789_PIN_CS GPIO_NUM_46 // SPI片选引脚
|
||||
#define ST7789_PIN_BL GPIO_NUM_NC // 背光引脚
|
||||
#define ST7789_PIN_RST GPIO_NUM_NC // 复位引脚
|
||||
#define LCD_BL_ACTIVE_LEVEL 0 // 背光有效电平:1=高电平有效(NMOS),0=低电平有效(PMOS)
|
||||
|
||||
#define LCD_WIDTH 172 // 屏幕宽度(水平方向像素数)
|
||||
#define LCD_HEIGHT 320 // 屏幕高度(垂直方向像素数)
|
||||
|
||||
/* 毫米波雷达配置参数 */
|
||||
/* 定义毫米波雷达的中断引脚 */
|
||||
#define MILLIMETER_WAVE_RADAR_PIN GPIO_NUM_35
|
||||
// UART 配置参数
|
||||
#define RADAR_UART_NUM UART_NUM_1 // 使用 UART1
|
||||
#define UART_TX_PIN GPIO_NUM_40 // GPIO43 作为 TX(根据实际硬件连接调整)
|
||||
#define UART_RX_PIN GPIO_NUM_39 // GPIO44 作为 RX
|
||||
#define RADAR_BAUD_RATE 9600 // 雷达波特率
|
||||
#define RADAR_BUF_SIZE 100 // 雷达接收缓冲区大小
|
||||
|
||||
/* IO扩展硬件配置常量 */
|
||||
#define I2C_MASTER_FREQ_HZ 100000 // I2C通信频率(100kHz)(可更改至400000)
|
||||
#define I2C_IO_EXPAND_SLAVE_ADDR 0x5B // AW9523BTQR器件地址
|
||||
#define GPIO_INPUT_PIN_SEL GPIO_NUM_10 // 中断检测引脚
|
||||
#define ESP_INTR_FLAG_DEFAULT 0 // 中断标志默认值
|
||||
#define IO_EXPAND_RSTN GPIO_NUM_45 // IO扩展板复位引脚
|
||||
|
||||
/* 定义线性马达的I2C从机配置常量 */
|
||||
#define LINEAR_MOTOR_I2C_SLAVE_ADDR 0x5A // 线性马达的I2C从机地址
|
||||
|
||||
/* 定义陀螺仪的I2C从机配置常量 */
|
||||
#define GYROSCOPE_I2C_SLAVE_ADDR 0x6A // 陀螺仪的I2C从机地址
|
||||
#define GYROSCOPE_INPUT_PIN_SEL GPIO_NUM_21 // 陀螺仪中断引脚
|
||||
|
||||
/* 原生触摸引脚配置 */
|
||||
// 触摸按键数量配置
|
||||
// #define TOUCH_BUTTON_NUM 4
|
||||
#define TOUCH_BUTTON_NUM 3
|
||||
// 触摸通道定义
|
||||
// #define TOUCH_PAD_CHANNEL_1 TOUCH_PAD_NUM11 // GPIO11
|
||||
#define TOUCH_PAD_CHANNEL_2 TOUCH_PAD_NUM12 // GPIO12
|
||||
#define TOUCH_PAD_CHANNEL_3 TOUCH_PAD_NUM13 // GPIO13
|
||||
#define TOUCH_PAD_CHANNEL_4 TOUCH_PAD_NUM14 // GPIO14
|
||||
|
||||
/* ES8311音频编解码器配置 (ESP-ADF兼容) */
|
||||
#define AUDIO_INPUT_SAMPLE_RATE 24000
|
||||
#define AUDIO_OUTPUT_SAMPLE_RATE 24000
|
||||
#define AUDIO_INPUT_REFERENCE true
|
||||
|
||||
/* I2S GPIO定义 */
|
||||
#define AUDIO_I2S_GPIO_MCLK GPIO_NUM_15
|
||||
#define AUDIO_I2S_GPIO_WS GPIO_NUM_4
|
||||
#define AUDIO_I2S_GPIO_BCLK GPIO_NUM_5
|
||||
#define AUDIO_I2S_GPIO_DIN GPIO_NUM_6
|
||||
#define AUDIO_I2S_GPIO_DOUT GPIO_NUM_7
|
||||
|
||||
/* PA引脚定义 */
|
||||
#define AUDIO_CODEC_PA_PIN GPIO_NUM_NC
|
||||
|
||||
/* I2C配置 */
|
||||
#define AUDIO_CODEC_I2C_SDA_PIN GPIO_NUM_2
|
||||
#define AUDIO_CODEC_I2C_SCL_PIN GPIO_NUM_3
|
||||
#define AUDIO_CODEC_ES8311_ADDR 0x18
|
||||
#define AUDIO_CODEC_ES7210_ADDR 0x40
|
||||
|
||||
/* WS2812 RGB LED配置 */
|
||||
#define WS2812_PIN GPIO_NUM_41 // WS2812数据引脚
|
||||
#define WS2812_NUM_LEDS 2 // WS2812 LED数量
|
||||
|
||||
/* 创建VBAT to VBAT_5V */
|
||||
#define VBAT_5V_PIN GPIO_NUM_NC // VBAT_5V引脚
|
||||
|
||||
/* 定义按键的中断引脚 */
|
||||
#define BUTTON_PIN GPIO_NUM_0 // 按键中断引脚
|
||||
#define RIGHT_BUTTON_PIN GPIO_NUM_8 // 按键中断引脚
|
||||
|
||||
#endif // _BOARD_CONFIG_H_
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,724 @@
|
||||
#include "io_expansion_board.h"
|
||||
#include "millimeter_wave_radar.h"
|
||||
#include "esp_heap_caps.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_check.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/idf_additions.h"
|
||||
#include "freertos/portable.h"
|
||||
#include "freertos/task.h"
|
||||
#include "freertos/event_groups.h"
|
||||
#include "esp_rom_sys.h"
|
||||
/**
|
||||
* @file io_expansion_board.cc
|
||||
* @brief IO扩展板功能实现类,包含I2C通信、GPIO中断配置、外设控制等功能
|
||||
* @details 实现了IO扩展板的初始化(中断引脚、复位引脚)、寄存器读写、步进电机控制(细分模式、使能、方向、睡眠状态)、
|
||||
* LCD相关引脚控制(背光、复位、片选)、毫米波雷达中断引脚配置等功能,并提供I2C数据读取任务的创建与管理
|
||||
* @author zouyuhua
|
||||
* @date 2025年8月7日
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief 构造函数
|
||||
*/
|
||||
IOExpansionBoard::IOExpansionBoard()
|
||||
: bus_handle_(nullptr),
|
||||
device_addr_(0),
|
||||
i2c_task_event_group_(nullptr),
|
||||
xI2CReadTaskHandle_(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 析构函数
|
||||
*/
|
||||
IOExpansionBoard::~IOExpansionBoard()
|
||||
{
|
||||
// 删除任务
|
||||
if (xI2CReadTaskHandle_) {
|
||||
vTaskDelete(xI2CReadTaskHandle_);
|
||||
}
|
||||
|
||||
// if(pI2CReadTaskStackBuffer) {
|
||||
// heap_caps_free(pI2CReadTaskStackBuffer);
|
||||
// pI2CReadTaskStackBuffer = nullptr;
|
||||
// }
|
||||
|
||||
// if(pxI2CReadTaskBuffer) {
|
||||
// vPortFree(pxI2CReadTaskBuffer);
|
||||
// pxI2CReadTaskBuffer = nullptr;
|
||||
// }
|
||||
|
||||
// 删除事件组
|
||||
if (i2c_task_event_group_) {
|
||||
vEventGroupDelete(i2c_task_event_group_);
|
||||
}
|
||||
|
||||
// 移除中断处理
|
||||
if (interrupt_gpio_ != GPIO_NUM_NC) {
|
||||
gpio_isr_handler_remove(interrupt_gpio_);
|
||||
}
|
||||
|
||||
// 删除IO扩展板设备
|
||||
// 使用i2c_bus API时不需要手动删除设备句柄
|
||||
// bus_handle_由board_sweekar统一管理
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 静态中断处理函数
|
||||
*/
|
||||
void IRAM_ATTR IOExpansionBoard::GpioIsrHandler(void* arg)
|
||||
{
|
||||
IOExpansionBoard* instance = static_cast<IOExpansionBoard*>(arg);
|
||||
if (!instance) return;
|
||||
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
|
||||
// 设置事件标志位
|
||||
if (instance->i2c_task_event_group_) {
|
||||
xEventGroupSetBitsFromISR(
|
||||
instance->i2c_task_event_group_,
|
||||
BIT0,
|
||||
&xHigherPriorityTaskWoken
|
||||
);
|
||||
}
|
||||
|
||||
// // 唤醒挂起的I2C任务
|
||||
// if (instance->xI2CReadTaskHandle_) {
|
||||
// if (xTaskResumeFromISR(instance->xI2CReadTaskHandle_) == pdTRUE) {
|
||||
// xHigherPriorityTaskWoken = pdTRUE;
|
||||
// }
|
||||
// }
|
||||
|
||||
// 触发上下文切换
|
||||
if (xHigherPriorityTaskWoken) {
|
||||
portYIELD_FROM_ISR();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 初始化GPIO中断检测
|
||||
*/
|
||||
esp_err_t IOExpansionBoard::InterruptGpioInit(gpio_num_t gpio_num)
|
||||
{
|
||||
// 配置IO扩展板中断引脚
|
||||
gpio_config_t io_conf = {};
|
||||
io_conf.intr_type = GPIO_INTR_NEGEDGE;
|
||||
io_conf.pin_bit_mask = 1ULL << gpio_num;
|
||||
io_conf.mode = GPIO_MODE_INPUT;
|
||||
io_conf.pull_up_en = GPIO_PULLUP_ENABLE;
|
||||
io_conf.pull_down_en = GPIO_PULLDOWN_DISABLE;
|
||||
|
||||
esp_err_t err = gpio_config(&io_conf);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG_GPIO_IO_EXPAND_DETECT, "GPIO配置失败,错误码: 0x%x", err);
|
||||
return err;
|
||||
}
|
||||
// 配置中断服务
|
||||
err = gpio_install_isr_service(ESP_INTR_FLAG_LEVEL3);
|
||||
if (err != ESP_OK && err != ESP_ERR_INVALID_STATE) {
|
||||
ESP_LOGE(TAG_GPIO_IO_EXPAND_DETECT, "GPIO中断服务安装失败,错误码: 0x%x", err);
|
||||
return err;
|
||||
}
|
||||
// 注册中断处理函数
|
||||
err = gpio_isr_handler_add(gpio_num, GpioIsrHandler, this);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG_GPIO_IO_EXPAND_DETECT, "GPIO中断处理函数添加失败,错误码: 0x%x", err);
|
||||
return err;
|
||||
}
|
||||
// 创建事件组
|
||||
i2c_task_event_group_ = xEventGroupCreate();
|
||||
if (!i2c_task_event_group_) {
|
||||
ESP_LOGE(TAG_GPIO_IO_EXPAND_DETECT, "事件组创建失败");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
ESP_LOGI(TAG_GPIO_IO_EXPAND_DETECT, "GPIO%d中断初始化完成", gpio_num);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 初始化硬件复位引脚
|
||||
* 设置为上拉,需要复位,需要输出低电平为20us的脉冲信号
|
||||
*/
|
||||
esp_err_t IOExpansionBoard::ResetGpioInit(gpio_num_t gpio_num)
|
||||
{
|
||||
reset_gpio_ = gpio_num;
|
||||
|
||||
// 配置复位引脚
|
||||
gpio_config_t io_conf = {};
|
||||
io_conf.intr_type = GPIO_INTR_DISABLE;
|
||||
io_conf.pin_bit_mask = 1ULL << gpio_num;
|
||||
io_conf.mode = GPIO_MODE_OUTPUT;
|
||||
io_conf.pull_up_en = GPIO_PULLUP_ENABLE;
|
||||
io_conf.pull_down_en = GPIO_PULLDOWN_DISABLE;
|
||||
esp_err_t err = gpio_config(&io_conf);
|
||||
gpio_set_level(gpio_num, 1); // 复位引脚拉高
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG_GPIO_IO_EXPAND_DETECT, "GPIO配置失败,错误码: 0x%x", err);
|
||||
return err;
|
||||
}
|
||||
else{
|
||||
ESP_LOGI(TAG_GPIO_IO_EXPAND_DETECT, "GPIO%d复位引脚初始化完成", gpio_num);
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 复位IO扩展板
|
||||
*/
|
||||
esp_err_t IOExpansionBoard::ResetIoExpand()
|
||||
{
|
||||
if (reset_gpio_ == GPIO_NUM_NC) {
|
||||
ESP_LOGE(TAG_I2C_IO_EXPAND_TASK, "复位引脚未初始化");
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
|
||||
// 复位IO扩展板
|
||||
gpio_set_level(reset_gpio_, 0);
|
||||
esp_rom_delay_us(30);
|
||||
gpio_set_level(reset_gpio_, 1);
|
||||
uint8_t ctl_val;
|
||||
//配置P0_0-P0_7的端口为推挽输出模式
|
||||
esp_err_t err = IoexpandReadReg(CTL, &ctl_val);
|
||||
ctl_val |= (1 << 4); // 设置D[4]位为1(GPOMD=1),切换P0为推挽模式
|
||||
err = IoexpandWriteReg(CTL, ctl_val);
|
||||
if(err != ESP_OK){
|
||||
ESP_LOGE(TAG_I2C_IO_EXPAND_TASK, "复位失败,错误码:0x%x", err);
|
||||
return err;
|
||||
}
|
||||
else{
|
||||
ESP_LOGI(TAG_I2C_IO_EXPAND_TASK, "复位成功");
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 写寄存器数据
|
||||
* @param reg_addr 寄存器地址
|
||||
* @param data 要写入的数据
|
||||
* @return esp_err_t 操作结果
|
||||
*/
|
||||
esp_err_t IOExpansionBoard::IoexpandWriteReg(uint8_t reg_addr, uint8_t data)
|
||||
{
|
||||
return i2c_bus_write_bytes(bus_handle_, device_addr_, ®_addr, 1, &data, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 从寄存器读取数据
|
||||
* @param reg_addr 寄存器地址(如INPUT_PORT0、ID等)
|
||||
* @param data 输出参数,用于存储读取到的数据
|
||||
* @return esp_err_t 操作结果(ESP_OK为成功)
|
||||
*/
|
||||
esp_err_t IOExpansionBoard::IoexpandReadReg(uint8_t reg_addr, uint8_t* data)
|
||||
{
|
||||
if (data == nullptr){ // 检查输入参数有效性
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
// 使用i2c_bus_read_bytes进行寄存器读取
|
||||
esp_err_t err = i2c_bus_read_bytes(bus_handle_, device_addr_, ®_addr, 1, data, 1);
|
||||
if (err != ESP_OK){
|
||||
ESP_LOGE(TAG_I2C_IO_EXPAND_TASK, "读取寄存器失败,错误码:0x%x", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
//设置IO扩展板为输入模式或是输出模式
|
||||
/*
|
||||
* 这里需要根据实际情况设置IO扩展板的模式,比如输入模式还是输出模式,以及各个引脚的配置。
|
||||
* P0_0 对应NFC_RST引脚,需要设置为输出模式,低电平有效。(待测)
|
||||
* P0_1 对应USB_VBUS引脚,需要设置为输出模式,低电平有效。(待测)
|
||||
* P0_2 对应BTN_RIGHT_EAR引脚,需要设置为输出模式,低电平有效。(待测)
|
||||
* P0_3 暂时未使用。
|
||||
* P0_4 对应步进电机方向引脚,需要设置为输出模式,根据需求设置。(待测)
|
||||
* P0_5 对应CHRG引脚(待测)
|
||||
* P0_6 LCD_DC引脚,需要设置为输出模式,根据需求设置电平。(待测)
|
||||
* P0_7 对应步进电机的使能引脚,需要设置为输出模式,根据需求设置。(待测)
|
||||
*
|
||||
*
|
||||
* P1_0 对应EG800K_PWR。(待测)
|
||||
* P1_1 对应LCD_RST,需要设置为输出模式,低电平有效。(待测)
|
||||
* P1_2 对应LCD_CS,需要设置为输出模式,低电平有效。(待测)
|
||||
* P1_3 暂时未使用。
|
||||
* P1_4 对应步进电机的细分模式M1引脚。(待测)
|
||||
* P1_5 对应步进电机的细分模式M0引脚。(待测)
|
||||
* P1_6 对应步进电机的睡眠引脚。(待测)
|
||||
* P1_7 对应RADAR_O雷达的输出引脚。(待测)
|
||||
* */
|
||||
esp_err_t IOExpansionBoard::IoexpandSetMode(void)
|
||||
{
|
||||
uint8_t ctl_val;
|
||||
//配置P0_0-P0_7的端口为推挽输出模式
|
||||
esp_err_t err = IoexpandReadReg(CTL, &ctl_val);
|
||||
ctl_val |= (1 << 4); // 设置D[4]位为1(GPOMD=1),切换P0为推挽模式
|
||||
err = IoexpandWriteReg(CTL, ctl_val);
|
||||
if(err != ESP_OK){
|
||||
ESP_LOGE(TAG_I2C_IO_EXPAND_TASK, "配置P0端口失败,错误码:0x%x", err);
|
||||
return err;
|
||||
}
|
||||
else{
|
||||
ESP_LOGI(TAG_I2C_IO_EXPAND_TASK, "配置P0端口成功");
|
||||
}
|
||||
// 配置P0_0-P0_7的端口为输入还是输出:0-输出;1-输入
|
||||
// err = IoexpandWriteReg(CONFIG_PORT0, 0x04); // 0000 0100
|
||||
err = IoexpandWriteReg(CONFIG_PORT0, 0x24); // 0010 0100
|
||||
// err = IoexpandWriteReg(CONFIG_PORT0, 0x2C); // 0010 1100 0-2,0-3,0-5都是输入
|
||||
|
||||
// D 1101
|
||||
// 9 1001
|
||||
|
||||
if(err != ESP_OK){
|
||||
ESP_LOGE(TAG_I2C_IO_EXPAND_TASK, "配置P0端口失败,错误码:0x%x", err);
|
||||
return err;
|
||||
}
|
||||
else{
|
||||
ESP_LOGI(TAG_I2C_IO_EXPAND_TASK, "配置P0端口成功");
|
||||
}
|
||||
// 配置P1_0-P1_7的端口输出:0-输出;1-输入
|
||||
// err = IoexpandWriteReg(CONFIG_PORT1, 0x84);
|
||||
err = IoexpandWriteReg(CONFIG_PORT1, 0x80); // 1000 0000
|
||||
if(err != ESP_OK){
|
||||
ESP_LOGE(TAG_I2C_IO_EXPAND_TASK, "配置P1端口失败,错误码:0x%x", err);
|
||||
return err;
|
||||
}
|
||||
else{
|
||||
ESP_LOGI(TAG_I2C_IO_EXPAND_TASK, "配置P1端口成功");
|
||||
}
|
||||
// 配置P0_0-P0_7的初始为高电平
|
||||
// 配置P1_0-P1_7的初始为高电平
|
||||
err = IoexpandWriteReg(OUTPUT_PORT0, 0xFD); // 1111 1101
|
||||
if(err != ESP_OK){
|
||||
ESP_LOGE(TAG_I2C_IO_EXPAND_TASK, "配置P0端口初始值失败,错误码:0x%x", err);
|
||||
return err;
|
||||
}
|
||||
else{
|
||||
ESP_LOGI(TAG_I2C_IO_EXPAND_TASK, "配置P0端口初始值成功");
|
||||
}
|
||||
err = IoexpandWriteReg(OUTPUT_PORT1, 0x7E); // 0111 1110
|
||||
if(err != ESP_OK){
|
||||
ESP_LOGE(TAG_I2C_IO_EXPAND_TASK, "配置P1端口初始值失败,错误码:0x%x", err);
|
||||
return err;
|
||||
}
|
||||
else{
|
||||
ESP_LOGI(TAG_I2C_IO_EXPAND_TASK, "配置P1端口初始值成功");
|
||||
}
|
||||
|
||||
err = IoexpandWriteReg(INT_PORT1, 0x7F); // 0111 1111
|
||||
if(err != ESP_OK){
|
||||
ESP_LOGE(TAG_I2C_IO_EXPAND_TASK, "配置P1端口中断使能失败,错误码:0x%x", err);
|
||||
return err;
|
||||
}
|
||||
else{
|
||||
ESP_LOGI(TAG_I2C_IO_EXPAND_TASK, "配置P1端口中断使能成功");
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 设置步进电机的细分模式
|
||||
*/
|
||||
void IOExpansionBoard::SetStepperMicrostepMode(uint8_t mode, uint8_t OUTPUT_PORT, uint8_t m0_pin, uint8_t m1_pin)
|
||||
{
|
||||
uint8_t current_val;
|
||||
switch (mode) {
|
||||
case 1: //全步输出模式 低低电平
|
||||
/* code */
|
||||
IoexpandReadReg(OUTPUT_PORT, ¤t_val);
|
||||
ESP_LOGW(TAG_I2C_IO_EXPAND_TASK, "0x%x", current_val);
|
||||
current_val &= ~(1 << m0_pin);
|
||||
ESP_LOGW(TAG_I2C_IO_EXPAND_TASK, "!!!!!!!!!0x%x", current_val);
|
||||
if(IoexpandWriteReg(OUTPUT_PORT, current_val) != ESP_OK){
|
||||
ESP_LOGE(TAG_I2C_IO_EXPAND_TASK, "设置步进电机细分模式失败");
|
||||
}
|
||||
IoexpandReadReg(OUTPUT_PORT, ¤t_val);
|
||||
ESP_LOGW(TAG_I2C_IO_EXPAND_TASK, "0x%x", current_val);
|
||||
current_val &= ~(1 << m1_pin);
|
||||
ESP_LOGW(TAG_I2C_IO_EXPAND_TASK, "!!!!!!!!!0x%x", current_val);
|
||||
if(IoexpandWriteReg(OUTPUT_PORT, current_val) != ESP_OK){
|
||||
ESP_LOGE(TAG_I2C_IO_EXPAND_TASK, "设置步进电机细分模式失败");
|
||||
}
|
||||
break;
|
||||
case 2: //非圆 1/2 高低电平
|
||||
/* code */
|
||||
IoexpandReadReg(OUTPUT_PORT, ¤t_val);
|
||||
ESP_LOGW(TAG_I2C_IO_EXPAND_TASK, "0x%x", current_val);
|
||||
current_val |= (1 << m0_pin);
|
||||
ESP_LOGW(TAG_I2C_IO_EXPAND_TASK, "!!!!!!!!!0x%x", current_val);
|
||||
if(IoexpandWriteReg(OUTPUT_PORT, current_val) != ESP_OK){
|
||||
ESP_LOGE(TAG_I2C_IO_EXPAND_TASK, "设置步进电机细分模式失败");
|
||||
}
|
||||
IoexpandReadReg(OUTPUT_PORT, ¤t_val);
|
||||
ESP_LOGW(TAG_I2C_IO_EXPAND_TASK, "0x%x", current_val);
|
||||
current_val &= ~(1 << m1_pin);
|
||||
ESP_LOGW(TAG_I2C_IO_EXPAND_TASK, "!!!!!!!!!0x%x", current_val);
|
||||
if(IoexpandWriteReg(OUTPUT_PORT, current_val) != ESP_OK){
|
||||
ESP_LOGE(TAG_I2C_IO_EXPAND_TASK, "设置步进电机细分模式失败");
|
||||
}
|
||||
break;
|
||||
case 3: //1/4 步 低高电平
|
||||
/* code */
|
||||
IoexpandReadReg(OUTPUT_PORT, ¤t_val);
|
||||
ESP_LOGW(TAG_I2C_IO_EXPAND_TASK, "0x%x", current_val);
|
||||
current_val &= ~(1 << m0_pin);
|
||||
ESP_LOGW(TAG_I2C_IO_EXPAND_TASK, "!!!!!!!!!0x%x", current_val);
|
||||
if(IoexpandWriteReg(OUTPUT_PORT, current_val) != ESP_OK){
|
||||
ESP_LOGE(TAG_I2C_IO_EXPAND_TASK, "设置步进电机细分模式失败");
|
||||
}
|
||||
IoexpandReadReg(OUTPUT_PORT, ¤t_val);
|
||||
ESP_LOGW(TAG_I2C_IO_EXPAND_TASK, "0x%x", current_val);
|
||||
current_val |= (1 << m1_pin);
|
||||
ESP_LOGW(TAG_I2C_IO_EXPAND_TASK, "!!!!!!!!!0x%x", current_val);
|
||||
if(IoexpandWriteReg(OUTPUT_PORT, current_val) != ESP_OK){
|
||||
ESP_LOGE(TAG_I2C_IO_EXPAND_TASK, "设置步进电机细分模式失败");
|
||||
}
|
||||
break;
|
||||
case 4: //1/8 步 高高电平
|
||||
/* code */
|
||||
IoexpandReadReg(OUTPUT_PORT, ¤t_val);
|
||||
ESP_LOGW(TAG_I2C_IO_EXPAND_TASK, "0x%x", current_val);
|
||||
current_val |= (1 << m0_pin);
|
||||
ESP_LOGW(TAG_I2C_IO_EXPAND_TASK, "!!!!!!!!!0x%x", current_val);
|
||||
if(IoexpandWriteReg(OUTPUT_PORT, current_val) != ESP_OK){
|
||||
ESP_LOGE(TAG_I2C_IO_EXPAND_TASK, "设置步进电机细分模式失败");
|
||||
}
|
||||
IoexpandReadReg(OUTPUT_PORT, ¤t_val);
|
||||
ESP_LOGW(TAG_I2C_IO_EXPAND_TASK, "0x%x", current_val);
|
||||
current_val |= (1 << m1_pin);
|
||||
ESP_LOGW(TAG_I2C_IO_EXPAND_TASK, "!!!!!!!!!0x%x", current_val);
|
||||
if(IoexpandWriteReg(OUTPUT_PORT, current_val) != ESP_OK){
|
||||
ESP_LOGE(TAG_I2C_IO_EXPAND_TASK, "设置步进电机细分模式失败");
|
||||
}
|
||||
break;
|
||||
default: //全步输入模式 低低电平
|
||||
/* code */
|
||||
IoexpandReadReg(OUTPUT_PORT, ¤t_val);
|
||||
ESP_LOGW(TAG_I2C_IO_EXPAND_TASK, "0x%x", current_val);
|
||||
current_val &= ~(1 << m0_pin);
|
||||
ESP_LOGW(TAG_I2C_IO_EXPAND_TASK, "!!!!!!!!!0x%x", current_val);
|
||||
if(IoexpandWriteReg(OUTPUT_PORT, current_val) != ESP_OK){
|
||||
ESP_LOGE(TAG_I2C_IO_EXPAND_TASK, "设置步进电机细分模式失败");
|
||||
}
|
||||
IoexpandReadReg(OUTPUT_PORT, ¤t_val);
|
||||
ESP_LOGW(TAG_I2C_IO_EXPAND_TASK, "0x%x", current_val);
|
||||
current_val &= ~(1 << m1_pin);
|
||||
ESP_LOGW(TAG_I2C_IO_EXPAND_TASK, "!!!!!!!!!0x%x", current_val);
|
||||
if(IoexpandWriteReg(OUTPUT_PORT, current_val) != ESP_OK){
|
||||
ESP_LOGE(TAG_I2C_IO_EXPAND_TASK, "设置步进电机细分模式失败");
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 设置步进电机的使能
|
||||
*/
|
||||
esp_err_t IOExpansionBoard::SetMotorEnableMode(bool enable, uint8_t OUTPUT_PORT, uint8_t enable_pin)
|
||||
{
|
||||
uint8_t current_val;
|
||||
if(enable){
|
||||
// 进入工作状态mode
|
||||
IoexpandReadReg(OUTPUT_PORT, ¤t_val);
|
||||
ESP_LOGW(TAG_I2C_IO_EXPAND_TASK, "0x%x", current_val);
|
||||
current_val |= (1 << enable_pin);
|
||||
// ESP_LOGE(TAG_I2C_IO_EXPAND_TASK, "!!!!!!!!!0x%x", current_val);
|
||||
return IoexpandWriteReg(OUTPUT_PORT, current_val);
|
||||
}
|
||||
else{
|
||||
// 进入睡眠状态
|
||||
IoexpandReadReg(OUTPUT_PORT, ¤t_val);
|
||||
ESP_LOGW(TAG_I2C_IO_EXPAND_TASK, "0x%x", current_val);
|
||||
current_val &= ~(1 << enable_pin);
|
||||
// ESP_LOGE(TAG_I2C_IO_EXPAND_TASK, "!!!!!!!!!0x%x", current_val);
|
||||
return IoexpandWriteReg(OUTPUT_PORT, current_val);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @brief 设置步进电机运行方向
|
||||
*/
|
||||
esp_err_t IOExpansionBoard::StepperMotorSetDir(bool dir, uint8_t OUTPUT_PORT, uint8_t pin)
|
||||
{
|
||||
uint8_t current_val;
|
||||
if(dir){
|
||||
// 方向为正转
|
||||
IoexpandReadReg(OUTPUT_PORT, ¤t_val);
|
||||
ESP_LOGW(TAG_I2C_IO_EXPAND_TASK, "0x%x", current_val);
|
||||
current_val |= (1 << pin);
|
||||
// ESP_LOGE(TAG_I2C_IO_EXPAND_TASK, "!!!!!!!!!0x%x", current_val);
|
||||
return IoexpandWriteReg(OUTPUT_PORT, current_val);
|
||||
}
|
||||
else{
|
||||
IoexpandReadReg(OUTPUT_PORT, ¤t_val);
|
||||
ESP_LOGW(TAG_I2C_IO_EXPAND_TASK, "0x%x", current_val);
|
||||
current_val &= ~(1 << pin);
|
||||
// ESP_LOGE(TAG_I2C_IO_EXPAND_TASK, "!!!!!!!!!0x%x", current_val);
|
||||
return IoexpandWriteReg(OUTPUT_PORT, current_val);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief 设置步进电机是否进入睡眠或者工作状态(高电平进入工作状态,低电平进入睡眠状态)
|
||||
*/
|
||||
esp_err_t IOExpansionBoard::SetMotorSleepMode(bool mode, uint8_t OUTPUT_PORT, uint8_t nsleep_pin)
|
||||
{
|
||||
uint8_t current_val;
|
||||
if(mode){
|
||||
// 进入工作状态mode
|
||||
IoexpandReadReg(OUTPUT_PORT, ¤t_val);
|
||||
ESP_LOGW(TAG_I2C_IO_EXPAND_TASK, "0x%x", current_val);
|
||||
current_val |= (1 << nsleep_pin);
|
||||
// ESP_LOGE(TAG_I2C_IO_EXPAND_TASK, "!!!!!!!!!0x%x", current_val);
|
||||
return IoexpandWriteReg(OUTPUT_PORT, current_val);
|
||||
}
|
||||
else{
|
||||
// 进入睡眠状态
|
||||
IoexpandReadReg(OUTPUT_PORT, ¤t_val);
|
||||
ESP_LOGW(TAG_I2C_IO_EXPAND_TASK, "0x%x", current_val);
|
||||
current_val &= ~(1 << nsleep_pin);
|
||||
// ESP_LOGE(TAG_I2C_IO_EXPAND_TASK, "!!!!!!!!!0x%x", current_val);
|
||||
return IoexpandWriteReg(OUTPUT_PORT, current_val);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*********************************************IO扩展板LCD引脚配置参数***********************************************/
|
||||
/**
|
||||
* @brief 设置 LCD_BL引脚电平(高电平为命令模式,低电平为数据模式)
|
||||
*/
|
||||
esp_err_t IOExpansionBoard::SetLcdBlMode(bool mode, uint8_t OUTPUT_PORT, uint8_t bl_pin)
|
||||
{
|
||||
uint8_t current_val;
|
||||
if(mode){
|
||||
// 进入命令模式
|
||||
IoexpandReadReg(OUTPUT_PORT, ¤t_val);
|
||||
ESP_LOGW(TAG_I2C_IO_EXPAND_TASK, "0x%x", current_val);
|
||||
current_val |= (1 << bl_pin);
|
||||
// ESP_LOGE(TAG_I2C_IO_EXPAND_TASK, "!!!!!!!!!0x%x", current_val);
|
||||
return IoexpandWriteReg(OUTPUT_PORT, current_val);
|
||||
}
|
||||
else{
|
||||
// 进入数据模式
|
||||
IoexpandReadReg(OUTPUT_PORT, ¤t_val);
|
||||
ESP_LOGW(TAG_I2C_IO_EXPAND_TASK, "0x%x", current_val);
|
||||
current_val &= ~(1 << bl_pin);
|
||||
// ESP_LOGE(TAG_I2C_IO_EXPAND_TASK, "!!!!!!!!!0x%x", current_val);
|
||||
return IoexpandWriteReg(OUTPUT_PORT, current_val);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 设置 LCD_RST引脚电平(高电平为复位模式,低电平为工作模式)
|
||||
*/
|
||||
esp_err_t IOExpansionBoard::SetLcdResetMode(bool mode, uint8_t OUTPUT_PORT, uint8_t reset_pin)
|
||||
{
|
||||
uint8_t current_val;
|
||||
if(mode){
|
||||
// 进入复位模式
|
||||
IoexpandReadReg(OUTPUT_PORT, ¤t_val);
|
||||
ESP_LOGW(TAG_I2C_IO_EXPAND_TASK, "0x%x", current_val);
|
||||
current_val |= (1 << reset_pin);
|
||||
// ESP_LOGE(TAG_I2C_IO_EXPAND_TASK, "!!!!!!!!!0x%x", current_val);
|
||||
return IoexpandWriteReg(OUTPUT_PORT, current_val);
|
||||
}
|
||||
else{
|
||||
// 进入工作模式
|
||||
IoexpandReadReg(OUTPUT_PORT, ¤t_val);
|
||||
ESP_LOGW(TAG_I2C_IO_EXPAND_TASK, "0x%x", current_val);
|
||||
current_val &= ~(1 << reset_pin);
|
||||
// ESP_LOGE(TAG_I2C_IO_EXPAND_TASK, "!!!!!!!!!0x%x", current_val);
|
||||
return IoexpandWriteReg(OUTPUT_PORT, current_val);
|
||||
}
|
||||
}
|
||||
|
||||
/*********************************************IO扩展板的输入引脚配置以及中断引脚定义***********************************************/
|
||||
/**
|
||||
* @brief 设置 毫米波雷达的中断引脚
|
||||
*/
|
||||
esp_err_t IOExpansionBoard::SetRadarInterruptPin(bool mode, uint8_t INPUT_PORT, uint8_t interrupt_pin)
|
||||
{
|
||||
uint8_t current_val;
|
||||
if(mode){
|
||||
// 进入输入模式
|
||||
IoexpandReadReg(INPUT_PORT, ¤t_val);
|
||||
ESP_LOGW(TAG_I2C_IO_EXPAND_TASK, "0x%x", current_val);
|
||||
current_val |= (1 << interrupt_pin);
|
||||
// ESP_LOGE(TAG_I2C_IO_EXPAND_TASK, "!!!!!!!!!0x%x", current_val);
|
||||
return IoexpandWriteReg(INPUT_PORT, current_val);
|
||||
}
|
||||
else{
|
||||
// 进入输出模式
|
||||
IoexpandReadReg(INPUT_PORT, ¤t_val);
|
||||
ESP_LOGW(TAG_I2C_IO_EXPAND_TASK, "0x%x", current_val);
|
||||
current_val &= ~(1 << interrupt_pin);
|
||||
// ESP_LOGE(TAG_I2C_IO_EXPAND_TASK, "!!!!!!!!!0x%x", current_val);
|
||||
return IoexpandWriteReg(INPUT_PORT, current_val);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 设置 LCD_CS引脚电平(低电平为选中状态,高电平为不选中状态)
|
||||
*/
|
||||
esp_err_t IOExpansionBoard::SetLcdCsMode(bool mode, uint8_t OUTPUT_PORT, uint8_t cs_pin)
|
||||
{
|
||||
uint8_t current_val;
|
||||
if(mode){
|
||||
// 进入选中状态
|
||||
IoexpandReadReg(OUTPUT_PORT, ¤t_val);
|
||||
ESP_LOGW(TAG_I2C_IO_EXPAND_TASK, "0x%x", current_val);
|
||||
current_val &= ~(1 << cs_pin);
|
||||
// ESP_LOGE(TAG_I2C_IO_EXPAND_TASK, "!!!!!!!!!0x%x", current_val);
|
||||
return IoexpandWriteReg(OUTPUT_PORT, current_val);
|
||||
}
|
||||
else{
|
||||
// 进入不选中状态
|
||||
IoexpandReadReg(OUTPUT_PORT, ¤t_val);
|
||||
ESP_LOGW(TAG_I2C_IO_EXPAND_TASK, "0x%x", current_val);
|
||||
current_val |= (1 << cs_pin);
|
||||
// ESP_LOGE(TAG_I2C_IO_EXPAND_TASK, "!!!!!!!!!0x%x", current_val);
|
||||
return IoexpandWriteReg(OUTPUT_PORT, current_val);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @brief I2C数据读取任务主体
|
||||
*/
|
||||
void IOExpansionBoard::I2cReadTask(void* pvParameters)
|
||||
{
|
||||
IOExpansionBoard* instance = static_cast<IOExpansionBoard*>(pvParameters);
|
||||
if (!instance) {
|
||||
vTaskDelete(nullptr);
|
||||
return;
|
||||
}
|
||||
// 初始化复位引脚
|
||||
esp_err_t err = instance->ResetGpioInit(IO_EXPAND_RSTN);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG_GPIO_IO_EXPAND_DETECT, "GPIO复位初始化失败");
|
||||
}
|
||||
// 初始化IO扩展板子的中断引脚
|
||||
err = instance->InterruptGpioInit(GPIO_INPUT_PIN_SEL);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG_GPIO_IO_EXPAND_DETECT, "GPIO中断初始化失败");
|
||||
}
|
||||
// 设置IO扩展板模式
|
||||
instance->IoexpandSetMode();
|
||||
|
||||
// 设置LCD屏幕复位引脚
|
||||
err = instance->SetLcdResetMode(LCD_RST_HIGH, LCD_RST_PORT, LCD_RST_PIN);
|
||||
if(err != ESP_OK){
|
||||
ESP_LOGE(TAG_GPIO_IO_EXPAND_DETECT, "设置LCD屏幕复位引脚失败");
|
||||
}
|
||||
else{
|
||||
ESP_LOGI(TAG_GPIO_IO_EXPAND_DETECT, "设置LCD屏幕复位引脚成功");
|
||||
}
|
||||
instance->IoexpandWriteReg(OUTPUT_PORT0, 0xff);
|
||||
uint8_t current_val;
|
||||
for (;;) {
|
||||
// 等待中断事件触发
|
||||
if (instance->i2c_task_event_group_) {
|
||||
xEventGroupWaitBits(instance->i2c_task_event_group_, BIT0, pdTRUE, pdFALSE, portMAX_DELAY);
|
||||
}
|
||||
// 读取I2C数据
|
||||
instance->IoexpandReadReg(INPUT_PORT1,¤t_val);
|
||||
ESP_LOGI(TAG_I2C_IO_EXPAND_TASK, "读取数据: 0x%0X", current_val);
|
||||
if(current_val & (1 << 7)){
|
||||
ESP_LOGI(TAG_GPIO_IO_EXPAND_DETECT, "检测到中断来自雷达引脚(P1_7)\n");
|
||||
// 调用毫米波雷达回调函数
|
||||
if (instance->radar_) {
|
||||
instance->radar_->TriggerRadarDetectCallback();
|
||||
}
|
||||
}
|
||||
|
||||
// vTaskSuspend(nullptr); // 挂起任务等待下次唤醒
|
||||
}
|
||||
}
|
||||
|
||||
// bool IOExpansionBoard::AllocateStaticTaskMemory()
|
||||
// {
|
||||
// printf("IO拓展芯片创建任务前:Internal Free: %d bytes\n", heap_caps_get_free_size(MALLOC_CAP_INTERNAL));
|
||||
// printf("IO拓展芯片创建任务前 Free: %d bytes\n", heap_caps_get_free_size(MALLOC_CAP_SPIRAM));
|
||||
// // 分配任务栈(PSRAM)
|
||||
// const size_t TASK_STACK_SIZE = 4096;
|
||||
// pI2CReadTaskStackBuffer = (StackType_t*)heap_caps_malloc(
|
||||
// TASK_STACK_SIZE * sizeof(StackType_t),
|
||||
// MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT
|
||||
// );
|
||||
|
||||
// if (!pI2CReadTaskStackBuffer) {
|
||||
// ESP_LOGE(TAG_I2C_IO_EXPAND_TASK, "Failed to allocate task stack from PSRAM");
|
||||
// return false;
|
||||
// }
|
||||
|
||||
// // 分配任务控制块(内部RAM)
|
||||
// pxI2CReadTaskBuffer = (StaticTask_t*)pvPortMalloc(sizeof(StaticTask_t));
|
||||
// if (!pxI2CReadTaskBuffer) {
|
||||
// ESP_LOGE(TAG_I2C_IO_EXPAND_TASK, "Failed to allocate task TCB from internal RAM");
|
||||
// heap_caps_free(pI2CReadTaskStackBuffer);
|
||||
// pI2CReadTaskStackBuffer = nullptr;
|
||||
// return false;
|
||||
// }
|
||||
|
||||
// ESP_LOGI(TAG_I2C_IO_EXPAND_TASK, "Static task memory allocated successfully");
|
||||
// printf("IO拓展芯片创建任务后:Internal Free: %d bytes\n", heap_caps_get_free_size(MALLOC_CAP_INTERNAL));
|
||||
// printf("IO拓展芯片创建任务后 Free: %d bytes\n", heap_caps_get_free_size(MALLOC_CAP_SPIRAM));
|
||||
// return true;
|
||||
// }
|
||||
|
||||
// void IOExpansionBoard::FreeStaticTaskMemory()
|
||||
// {
|
||||
// if (pI2CReadTaskStackBuffer != nullptr) {
|
||||
// heap_caps_free(pI2CReadTaskStackBuffer);
|
||||
// pI2CReadTaskStackBuffer = nullptr;
|
||||
// }
|
||||
|
||||
// if (pxI2CReadTaskBuffer != nullptr) {
|
||||
// vPortFree(pxI2CReadTaskBuffer);
|
||||
// pxI2CReadTaskBuffer = nullptr;
|
||||
// }
|
||||
|
||||
// ESP_LOGI(TAG_I2C_IO_EXPAND_TASK, "Static task memory freed");
|
||||
// }
|
||||
|
||||
/**
|
||||
* @brief 创建I2C数据读取任务
|
||||
*/
|
||||
void IOExpansionBoard::CreateI2cReadTask()
|
||||
{
|
||||
printf("创建I2C读取任务之前:Internal Free: %d bytes\n", heap_caps_get_free_size(MALLOC_CAP_INTERNAL));
|
||||
printf("创建I2C读取任务之前:PSRAM Free: %d bytes\n", heap_caps_get_free_size(MALLOC_CAP_SPIRAM));
|
||||
if (xI2CReadTaskHandle_) {
|
||||
return; // 任务已创建
|
||||
}
|
||||
|
||||
xTaskCreateWithCaps(
|
||||
I2cReadTask,
|
||||
"i2c_read_task",
|
||||
I2C_TASK_STACK,
|
||||
this,
|
||||
I2C_TASK_PRIORITY,
|
||||
&xI2CReadTaskHandle_,
|
||||
MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT
|
||||
);
|
||||
|
||||
if (xI2CReadTaskHandle_ == NULL) {
|
||||
ESP_LOGE(TAG_I2C_IO_EXPAND_TASK, "Failed to create static I2C read task");
|
||||
} else {
|
||||
ESP_LOGI(TAG_I2C_IO_EXPAND_TASK, "Static I2C read task created successfully");
|
||||
}
|
||||
printf("创建I2C读取任务之后:Internal Free: %d bytes\n", heap_caps_get_free_size(MALLOC_CAP_INTERNAL));
|
||||
printf("创建I2C读取任务之后:PSRAM Free: %d bytes\n", heap_caps_get_free_size(MALLOC_CAP_SPIRAM));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 启动I2C任务 (整合初始化和任务创建)
|
||||
*/
|
||||
esp_err_t IOExpansionBoard::StartTask()
|
||||
{
|
||||
// 再创建任务
|
||||
if (!xI2CReadTaskHandle_) {
|
||||
CreateI2cReadTask();
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
@@ -0,0 +1,284 @@
|
||||
#ifndef IO_EXPANSION_BOARD_H
|
||||
#define IO_EXPANSION_BOARD_H
|
||||
|
||||
#include <cstdint>
|
||||
#include <esp_log.h>
|
||||
#include <esp_check.h>
|
||||
#include <esp_timer.h>
|
||||
#include <driver/gpio.h>
|
||||
#include "i2c_bus.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/event_groups.h"
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
#include <freertos/FreeRTOS.h>
|
||||
#include <freertos/task.h>
|
||||
#include <freertos/queue.h>
|
||||
#include <freertos/semphr.h>
|
||||
#include "esp_err.h"
|
||||
#include "config.h"
|
||||
#include "portmacro.h"
|
||||
|
||||
// 前向声明,避免循环引用
|
||||
class MillimeterWaveRadar;
|
||||
|
||||
/* 寄存器地址 */
|
||||
#define INPUT_PORT0 0x00 // 输入端口0寄存器
|
||||
#define INPUT_PORT1 0x01 // 输入端口1寄存器 0为低电平(仅支持读取)
|
||||
#define OUTPUT_PORT0 0x02 // 输出端口0寄存器
|
||||
#define OUTPUT_PORT1 0x03 // 输出端口1寄存器 0为低电平
|
||||
#define CONFIG_PORT0 0x04 // 配置端口0寄存器
|
||||
#define CONFIG_PORT1 0x05 // 配置端口1寄存器 0为输出模式
|
||||
#define INT_PORT0 0x06 // 中断端口0寄存器
|
||||
#define INT_PORT1 0x07 // 中断端口1寄存器 0为使能中断(根据手册默认是使能的)
|
||||
#define CTL 0x11 // 全局控制寄存器
|
||||
#define ID 0x23 // 芯片ID寄存器(0x23)
|
||||
|
||||
/***********************************IO扩展板电机引脚配置参数*************************************/
|
||||
/* 设置步进电机方向 */
|
||||
#define STEPPER_MOTOR_LEFT false //步进电机的方向为左转
|
||||
#define STEPPER_MOTOR_RIGHT true //步进电机的方向为右转
|
||||
#define STEPPER_MOTOR_DIR_PORT OUTPUT_PORT0 //步进电机方向引脚挂载在IO扩展板的输出端口OUTPUT_PORT0
|
||||
#define STEPPER_MOTOR_DIR_PIN 4 //步进电机方向引脚对应的IO扩展板引脚P0_4
|
||||
|
||||
/* 设置步进电机细分模式 */
|
||||
#define STEPPER_MOTOR_M0_PIN 5 //步进电机细分模式选择引脚对应IO扩展板引脚P1_5
|
||||
#define STEPPER_MOTOR_M1_PIN 4 //步进电机细分模式选择引脚对应IO扩展板引脚P1_4
|
||||
#define STEPPER_MOTOR_MADE_PORT OUTPUT_PORT1 //步进电机模式选择引脚挂载在IO扩展板的输出端口OUTPUT_PORT1
|
||||
|
||||
|
||||
/* 设置步进电机睡眠引脚 */
|
||||
#define STEPPER_MOTOR_SLEEP false //步进电机进入睡眠模式
|
||||
#define STEPPER_MOTOR_WORK true //步进电机进入工作模式
|
||||
#define STEPPER_MOTOR_SLEEP_PIN 6 //步进电机睡眠引脚对应IO扩展板引脚P1_6
|
||||
#define STEPPER_MOTOR_SLEEP_PORT OUTPUT_PORT1 //步进电机睡眠引脚挂载在IO扩展板的输出端口OUTPUT_PORT1
|
||||
|
||||
/* 设置电机的使能引脚 */
|
||||
#define STEPPER_MOTOR_ENABLE_PIN 7 //电机使能引脚对应IO扩展板引脚P0_7
|
||||
#define STEPPER_MOTOR_ENABLE_PORT OUTPUT_PORT0 //电机使能引脚挂载在IO扩展板的输出端口OUTPUT_PORT0
|
||||
#define STEPPER_MOTOR_ENABLE_ENABLE true //电机使能引脚状态为高电平
|
||||
#define STEPPER_MOTOR_ENABLE_DISABLE false //电机使能引脚状态为低电平
|
||||
|
||||
/* 设置毫米波雷达对应IO扩展板的中断引脚 */
|
||||
#define RADAR_INTERRUPT_PIN 7 //毫米波雷达中断引脚对应IO扩展板引脚P1_7
|
||||
#define RADAR_INTERRUPT_PORT CONFIG_PORT1 //毫米波雷达中断引脚挂载在IO扩展板的输入端口INPUT_PORT1
|
||||
#define RADAR_INTERRUPT_ENABLE true //毫米波雷达中断引脚状态为输入状态
|
||||
#define RADAR_INTERRUPT_DISABLE false //毫米波雷达中断引脚状态为输出状态
|
||||
/* 任务配置常量 */
|
||||
#define WRITE_BUF_SIZE 2 // I2C单次写入字节数
|
||||
#define READ_BUF_SIZE 2 // I2C单次读取字节数
|
||||
#define I2C_TASK_PRIORITY 2 // 任务优先级(中等)
|
||||
#define I2C_TASK_STACK 4096 // 任务栈大小(4KB)
|
||||
|
||||
/***********************************IO扩展板LCD引脚配置参数*************************************/
|
||||
/* 设置LCD的BL引脚 */
|
||||
#define LCD_BL_PIN 6 //LCD背光引脚
|
||||
#define LCD_BL_PORT OUTPUT_PORT0 //LCD背光引脚挂载在IO扩展板的输出端口OUTPUT_PORT0
|
||||
#define LCD_BL_HIGH true //LCD背光引脚状态为高电平
|
||||
#define LCD_BL_LOW false //LCD背光引脚状态为低电平
|
||||
|
||||
/* 设置LCD的RST引脚 */
|
||||
#define LCD_RST_PIN 1 //LCD复位引脚
|
||||
#define LCD_RST_PORT OUTPUT_PORT1 //LCD复位引脚挂载在IO扩展板的输出端口OUTPUT_PORT1
|
||||
#define LCD_RST_HIGH true //LCD复位引脚状态为高电平
|
||||
#define LCD_RST_LOW false //LCD复位引脚状态为低电平
|
||||
|
||||
/* 设置LCD的CS引脚 */
|
||||
#define LCD_CS_PIN 2 //LCD片选引脚
|
||||
#define LCD_CS_PORT OUTPUT_PORT1 //LCD片选引脚挂载在IO扩展板的输出端口OUTPUT_PORT1
|
||||
#define LCD_CS_HIGH true //LCD片选引脚状态为高电平
|
||||
#define LCD_CS_LOW false //LCD片选引脚状态为低电平
|
||||
|
||||
#define TAG_GPIO_IO_EXPAND_DETECT "GPIO_IO_EXPAND_DETECT" // GPIO中断检测日志标签
|
||||
#define TAG_I2C_IO_EXPAND_TASK "I2C_IO_EXPAND_TASK" // I2CIO扩展板任务日志标签
|
||||
|
||||
// GPIO引脚定义
|
||||
#define GPIO_INPUT_PIN_SEL GPIO_NUM_10 // IO扩展板中断检测引脚
|
||||
#define IO_EXPAND_RSTN GPIO_NUM_45 // IO扩展板复位引脚
|
||||
|
||||
/**
|
||||
* @class IOExpansionBoard
|
||||
* @brief I/O扩展板驱动类,封装AW9523BTQR芯片操作
|
||||
*/
|
||||
class IOExpansionBoard
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief 构造函数
|
||||
*/
|
||||
IOExpansionBoard();
|
||||
|
||||
/**
|
||||
* @brief 设置毫米波雷达指针
|
||||
* @param radar 毫米波雷达对象指针
|
||||
*/
|
||||
void setRadar(MillimeterWaveRadar* radar) { radar_ = radar; };
|
||||
|
||||
/**
|
||||
* @brief 析构函数
|
||||
*/
|
||||
~IOExpansionBoard();
|
||||
|
||||
/**
|
||||
* @brief 初始化GPIO中断检测
|
||||
* @param gpio_num 中断引脚编号
|
||||
* @return esp_err_t 初始化结果
|
||||
*/
|
||||
esp_err_t InterruptGpioInit(gpio_num_t gpio_num);
|
||||
|
||||
/**
|
||||
* @brief 初始化IO扩展板复位引脚
|
||||
* @param gpio_num 复位引脚编号
|
||||
* @return esp_err_t 初始化结果
|
||||
*/
|
||||
esp_err_t ResetGpioInit(gpio_num_t gpio_num);
|
||||
|
||||
/**
|
||||
* @brief 初始化IO扩展板复位引脚
|
||||
* @param gpio_num 复位引脚编号
|
||||
* @return esp_err_t 初始化结果
|
||||
*/
|
||||
esp_err_t ResetIoExpand();
|
||||
|
||||
/**
|
||||
* @brief 初始化I2C主机通信
|
||||
* @return esp_err_t 初始化结果
|
||||
*/
|
||||
// esp_err_t IoExpansionI2cInit();
|
||||
|
||||
/**
|
||||
* @brief 创建I2C数据读取任务
|
||||
*/
|
||||
void CreateI2cReadTask();
|
||||
|
||||
/**
|
||||
* @brief 启动I2C任务(整合初始化和任务创建)
|
||||
* @return esp_err_t 操作结果
|
||||
*/
|
||||
esp_err_t StartTask();
|
||||
|
||||
/**
|
||||
* @brief 写寄存器数据
|
||||
* @param reg_addr 寄存器地址
|
||||
* @param data 要写入的数据
|
||||
* @return esp_err_t 操作结果
|
||||
*/
|
||||
esp_err_t IoexpandWriteReg(uint8_t reg_addr, uint8_t data);
|
||||
|
||||
/**
|
||||
* @brief 读寄存器数据
|
||||
* @param reg_addr 寄存器地址
|
||||
* @param data 要读出的数据
|
||||
* @return esp_err_t 操作结果
|
||||
*/
|
||||
esp_err_t IoexpandReadReg(uint8_t reg_addr, uint8_t *data);
|
||||
|
||||
// /**
|
||||
// * @brief 设置IO扩展板GPIO中断状态 通过读取Input_Port0 和 Input_Port1 寄存器可以清除中断
|
||||
// * @param reg_addr 寄存器地址
|
||||
// * @return esp_err_t 操作结果
|
||||
// */
|
||||
// esp_err_t SetInterruptStatus(bool status);
|
||||
|
||||
/**
|
||||
* @brief 配置IO扩展版上的IO口为输出还是输入,并且设置初始为高电平
|
||||
* @return esp_err_t 操作结果
|
||||
*/
|
||||
esp_err_t IoexpandSetMode();
|
||||
|
||||
/**
|
||||
* @brief 设置步进电机的细分模式
|
||||
* @param mode 模式:1/2/4/8/16/32/64
|
||||
* @return esp_err_t 操作结果
|
||||
*/
|
||||
void SetStepperMicrostepMode(uint8_t mode, uint8_t OUTPUT_PORT, uint8_t m0_pin, uint8_t m1_pin);
|
||||
|
||||
/**
|
||||
* @brief 设置步进电机的方向
|
||||
* @param dir 方向
|
||||
* @param OUTPUT_PORT 输出端口
|
||||
* @param pin 引脚号
|
||||
* @return esp_err_t 操作结果
|
||||
*/
|
||||
esp_err_t StepperMotorSetDir(bool dir, uint8_t OUTPUT_PORT, uint8_t pin);
|
||||
|
||||
/**
|
||||
* @brief 设置步进电机的睡眠模式
|
||||
* @param 是否进入睡眠模式
|
||||
* @param 输出端口
|
||||
* @param 引脚号
|
||||
* @return esp_err_t 操作结果
|
||||
*/
|
||||
esp_err_t SetMotorSleepMode(bool mode, uint8_t OUTPUT_PORT, uint8_t nsleep_pin);
|
||||
|
||||
/**
|
||||
* @brief 设置步进电机的使能引脚状态
|
||||
* @param 使能状态
|
||||
* @return esp_err_t 操作结果
|
||||
*/
|
||||
esp_err_t SetMotorEnableMode(bool enable, uint8_t OUTPUT_PORT, uint8_t enable_pin);
|
||||
|
||||
/**
|
||||
* @brief 设置LCD的BL引脚状态
|
||||
* @param BL状态
|
||||
* @return esp_err_t 操作结果
|
||||
*/
|
||||
esp_err_t SetLcdBlMode(bool mode, uint8_t OUTPUT_PORT, uint8_t bl_pin);
|
||||
|
||||
/**
|
||||
* @brief 设置LCD的RST引脚状态
|
||||
* @param RST状态
|
||||
* @return esp_err_t 操作结果
|
||||
*/
|
||||
esp_err_t SetLcdResetMode(bool mode, uint8_t OUTPUT_PORT, uint8_t rst_pin);
|
||||
|
||||
/**
|
||||
* @brief 设置LCD的CS引脚状态
|
||||
* @param CS状态(低电平为选中状态,高电平为不选中状态)
|
||||
* @return esp_err_t 操作结果
|
||||
*/
|
||||
esp_err_t SetLcdCsMode(bool mode, uint8_t OUTPUT_PORT, uint8_t cs_pin);
|
||||
|
||||
/**
|
||||
* @brief 设置雷达中断引脚
|
||||
* @param 毫米波雷达的中断引脚模式
|
||||
* @param 输入端口
|
||||
* @param 引脚号
|
||||
* @return esp_err_t 操作结果
|
||||
*/
|
||||
esp_err_t SetRadarInterruptPin(bool mode, uint8_t INPUT_PORT, uint8_t interrupt_pin);
|
||||
|
||||
// 公共成员变量
|
||||
i2c_bus_handle_t bus_handle_ = nullptr; // I2C总线句柄
|
||||
uint8_t device_addr_; // I2C设备地址
|
||||
|
||||
private:
|
||||
// 静态成员函数
|
||||
MillimeterWaveRadar* radar_ = nullptr; // 毫米波雷达指针,用于触发回调
|
||||
static void IRAM_ATTR GpioIsrHandler(void* arg); // 中断处理函数
|
||||
static void I2cReadTask(void* pvParameters); // I2C数据读取任务函数
|
||||
|
||||
// /**
|
||||
// * @brief 分配静态任务所需的内存
|
||||
// * @return bool 分配是否成功
|
||||
// */
|
||||
// bool AllocateStaticTaskMemory();
|
||||
|
||||
// /**
|
||||
// * @brief 释放静态任务分配的内存
|
||||
// */
|
||||
// void FreeStaticTaskMemory();
|
||||
|
||||
// 实例成员变量
|
||||
EventGroupHandle_t i2c_task_event_group_ = nullptr; // 事件组
|
||||
TaskHandle_t xI2CReadTaskHandle_ = nullptr; // 任务句柄
|
||||
bool is_initialized_ = false; // 初始化状态标记(新增)
|
||||
gpio_num_t interrupt_gpio_ = GPIO_NUM_NC; // 中断引脚
|
||||
gpio_num_t reset_gpio_ = GPIO_NUM_NC; // 复位引脚
|
||||
|
||||
// StackType_t* pI2CReadTaskStackBuffer = nullptr; // 任务栈指针(PSRAM)
|
||||
// StaticTask_t* pxI2CReadTaskBuffer = nullptr; // 任务控制块指针(内部RAM)
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,311 @@
|
||||
/**
|
||||
* @file board.cc
|
||||
* @brief 板级外设初始化类,包含步进电机、毫米波雷达、I2C总线等外设的初始化函数。
|
||||
* @author zouyuhua
|
||||
* @date 2025年8月7日
|
||||
*
|
||||
*/
|
||||
|
||||
extern "C" {
|
||||
#include "esp_log.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "driver/uart.h"
|
||||
#include "driver/ledc.h"
|
||||
#include "driver/gptimer.h"
|
||||
#include "esp_err.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "hal/gpio_types.h"
|
||||
#include "hal/uart_types.h"
|
||||
#include "esp_check.h"
|
||||
#include "sdkconfig.h"
|
||||
#include "i2c_bus.h"
|
||||
}
|
||||
|
||||
#include "board_sweekar.h"
|
||||
#include "config.h"
|
||||
#define TAG "board_sweekar"
|
||||
|
||||
/*========================== 步进电机相关驱动 ==========================*/
|
||||
|
||||
/**
|
||||
* @brief 步进电机初始化函数
|
||||
* 配置步进电机所需的GPIO引脚模式,通过IO扩展板设置步进驱动芯片的工作模式
|
||||
* 在 stepper_motor.cc 中完成 GPTimer + GPIO 翻转 STEP 脉冲的初始化
|
||||
*/
|
||||
void BoardSweekar::StepperMotorInit(void)
|
||||
{
|
||||
esp_err_t err = ESP_OK;
|
||||
|
||||
// 1) STEP 引脚改为普通 GPIO(不再用 LEDC)
|
||||
gpio_config_t io_cfg;
|
||||
io_cfg.pin_bit_mask = 1ULL << STEPPER_STEP_IO;
|
||||
io_cfg.mode = GPIO_MODE_OUTPUT;
|
||||
io_cfg.pull_up_en = GPIO_PULLUP_DISABLE;
|
||||
io_cfg.pull_down_en = GPIO_PULLDOWN_DISABLE;
|
||||
io_cfg.intr_type = GPIO_INTR_DISABLE;
|
||||
err = gpio_config(&io_cfg);
|
||||
if (err != ESP_OK)
|
||||
{
|
||||
ESP_LOGE(TAG_BOARD, "步进电机 STEP GPIO 配置失败, 错误码: 0x%x", err);
|
||||
}
|
||||
|
||||
// 初始电平拉低,保证上电不乱跳
|
||||
gpio_set_level(STEPPER_STEP_IO, 0);
|
||||
|
||||
// 2) 检查 I2C 总线是否已初始化
|
||||
if (bus_handle_ == nullptr)
|
||||
{
|
||||
ESP_LOGE(TAG_BOARD, "I2C总线未初始化,请先调用I2CMasterInit()");
|
||||
return;
|
||||
}
|
||||
|
||||
// 3) 通过 IO 扩展板配置步进驱动芯片:睡眠/使能/细分/方向
|
||||
err = io_expansion_.SetMotorSleepMode(
|
||||
STEPPER_MOTOR_WORK,
|
||||
STEPPER_MOTOR_SLEEP_PORT,
|
||||
STEPPER_MOTOR_WORK
|
||||
);
|
||||
if (err != ESP_OK)
|
||||
{
|
||||
ESP_LOGE(TAG_BOARD, "步进电机睡眠模式配置失败, 错误码: 0x%x", err);
|
||||
}
|
||||
|
||||
err = io_expansion_.SetMotorEnableMode(
|
||||
STEPPER_MOTOR_ENABLE_DISABLE,
|
||||
STEPPER_MOTOR_ENABLE_PORT,
|
||||
STEPPER_MOTOR_ENABLE_PIN
|
||||
);
|
||||
if (err != ESP_OK)
|
||||
{
|
||||
ESP_LOGE(TAG_BOARD, "步进电机使能配置失败, 错误码: 0x%x", err);
|
||||
}
|
||||
|
||||
// 细分设置:这里仍然用原来的 1/8 细分
|
||||
io_expansion_.SetStepperMicrostepMode(
|
||||
4,
|
||||
STEPPER_MOTOR_M0_MADE_PORT,
|
||||
STEPPER_MOTOR_M0_PIN,
|
||||
STEPPER_MOTOR_M1_MADE_PORT,
|
||||
STEPPER_MOTOR_M1_PIN
|
||||
);
|
||||
if (err != ESP_OK)
|
||||
{
|
||||
ESP_LOGE(TAG_BOARD, "步进电机细分模式配置失败, 错误码: 0x%x", err);
|
||||
}
|
||||
|
||||
// 默认方向先设一个(比如“上升”方向)
|
||||
err = io_expansion_.StepperMotorSetDir(
|
||||
STEPPER_MOTOR_LEFT,
|
||||
STEPPER_MOTOR_DIR_PORT,
|
||||
STEPPER_MOTOR_DIR_PIN
|
||||
);
|
||||
if (err != ESP_OK)
|
||||
{
|
||||
ESP_LOGE(TAG_BOARD, "步进电机方向配置失败, 错误码: 0x%x", err);
|
||||
}
|
||||
}
|
||||
|
||||
/*========================== 毫米波雷达相关驱动 ==========================*/
|
||||
|
||||
/**
|
||||
* @brief 毫米波雷达串口初始化函数
|
||||
*
|
||||
* 配置毫米波雷达所使用的串口参数(波特率、数据位、校验位、停止位等),设置串口引脚,
|
||||
* 并安装串口驱动。采用较大的RX/TX FIFO深度以处理突发数据,禁用驱动自带事件队列以避免
|
||||
* 与自定义中断冲突。
|
||||
*/
|
||||
void BoardSweekar::MillimeterWaveRadarUartInit(void)
|
||||
{
|
||||
uart_config_t uart_config = {
|
||||
.baud_rate = RADAR_BAUD_RATE,
|
||||
.data_bits = UART_DATA_8_BITS,
|
||||
.parity = UART_PARITY_DISABLE,
|
||||
.stop_bits = UART_STOP_BITS_1,
|
||||
.flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
|
||||
.source_clk = UART_SCLK_DEFAULT,
|
||||
};
|
||||
|
||||
// 1. 设置串口参数
|
||||
ESP_ERROR_CHECK(uart_param_config(RADAR_UART_NUM, &uart_config));
|
||||
|
||||
// 2. 设置 UART 引脚
|
||||
ESP_ERROR_CHECK(uart_set_pin(RADAR_UART_NUM, UART_TX_PIN, UART_RX_PIN,
|
||||
UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE));
|
||||
|
||||
// 3. 安装 UART 驱动(禁用驱动自带事件队列,避免与自定义中断冲突)
|
||||
// 增加 RX/TX FIFO 深度以处理突发数据
|
||||
ESP_ERROR_CHECK(uart_driver_install(RADAR_UART_NUM, RADAR_BUF_SIZE * 4, RADAR_BUF_SIZE * 4,
|
||||
0, NULL, 0));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 毫米波雷达中断引脚初始化函数
|
||||
*
|
||||
* 配置毫米波雷达中断引脚为输入模式,禁用上拉电阻,使能下拉电阻,初始禁用中断功能
|
||||
* (如需使用中断需单独进行配置)。
|
||||
*/
|
||||
void BoardSweekar::MillimeterWaveRadarGpioInit(void)
|
||||
{
|
||||
// GPIO配置结构体
|
||||
gpio_config_t io_conf = {
|
||||
.pin_bit_mask = (1ULL << MILLIMETER_WAVE_RADAR_PIN), // 选择GPIO引脚
|
||||
.mode = GPIO_MODE_INPUT, // 设置为输入模式
|
||||
.pull_up_en = GPIO_PULLUP_DISABLE,
|
||||
.pull_down_en = GPIO_PULLDOWN_ENABLE, // 使能下拉
|
||||
.intr_type = GPIO_INTR_DISABLE // 禁用中断(如需中断需单独配置)
|
||||
};
|
||||
|
||||
// 配置GPIO
|
||||
gpio_config(&io_conf);
|
||||
}
|
||||
|
||||
/*========================== I2C总线及挂载的从设备相关驱动 ==========================*/
|
||||
|
||||
/**
|
||||
* @brief I2C总线及从机设备初始化函数
|
||||
*
|
||||
* 首先配置并创建I2C主机总线,然后依次添加IO扩展板和线性马达作为I2C从机设备到总线上。
|
||||
* 若总线创建或设备添加失败,会输出错误信息并进行相应的资源清理(删除已创建的总线)。
|
||||
* 初始化成功后,会通过ESP_LOGI输出IO扩展板和线性马达的从机地址信息。
|
||||
*
|
||||
* @return esp_err_t 初始化结果,ESP_OK表示成功,其他错误码表示相应的失败原因
|
||||
*/
|
||||
esp_err_t BoardSweekar::I2CMasterInit(void)
|
||||
{
|
||||
static const char *I2C_INIT = "I2C_INIT";
|
||||
|
||||
// 初始化IO扩展板复位引脚
|
||||
gpio_config_t reset_io_conf = {
|
||||
.pin_bit_mask = (1ULL << IO_EXPAND_RSTN),
|
||||
.mode = GPIO_MODE_OUTPUT,
|
||||
.pull_up_en = GPIO_PULLUP_ENABLE, // 使能上拉
|
||||
.pull_down_en = GPIO_PULLDOWN_DISABLE,
|
||||
.intr_type = GPIO_INTR_DISABLE
|
||||
};
|
||||
gpio_config(&reset_io_conf);
|
||||
|
||||
// 执行复位时序:先拉低100ms,再拉高并等待100ms
|
||||
gpio_set_level(IO_EXPAND_RSTN, 0); // 拉低复位
|
||||
vTaskDelay(pdMS_TO_TICKS(100)); // 等待100ms
|
||||
gpio_set_level(IO_EXPAND_RSTN, 1); // 释放复位
|
||||
vTaskDelay(pdMS_TO_TICKS(100)); // 等待设备启动
|
||||
|
||||
ESP_LOGI(I2C_INIT, "IO扩展板复位完成");
|
||||
|
||||
// 创建统一的I2C总线(使用ESP-ADF的i2c_bus)
|
||||
i2c_config_t i2c_cfg = {
|
||||
.mode = I2C_MODE_MASTER,
|
||||
.sda_io_num = I2C0_MASTER_SDA_IO,
|
||||
.scl_io_num = I2C0_MASTER_SCL_IO,
|
||||
.sda_pullup_en = GPIO_PULLUP_ENABLE,
|
||||
.scl_pullup_en = GPIO_PULLUP_ENABLE,
|
||||
.master = {
|
||||
.clk_speed = 100000,
|
||||
},
|
||||
};
|
||||
|
||||
// 创建I2C总线(ESP-ADF的audio_board_init会复用这个总线)
|
||||
bus_handle_ = i2c_bus_create(I2C0_MASTER_PORT, &i2c_cfg);
|
||||
if (bus_handle_ == NULL) {
|
||||
ESP_LOGE(TAG, "Failed to create I2C bus");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
vTaskDelay(pdMS_TO_TICKS(100)); // 等待设备启动
|
||||
// ESP-ADF的i2c_bus不需要单独添加设备,直接通过总线句柄和设备地址进行通信
|
||||
|
||||
// 验证线性马达设备是否存在
|
||||
esp_err_t err = i2c_bus_probe_addr(bus_handle_, LINEAR_MOTOR_I2C_SLAVE_ADDR << 1);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(I2C_INIT, "线性马达设备未找到(地址:0x%02X),错误码: 0x%x", LINEAR_MOTOR_I2C_SLAVE_ADDR, err);
|
||||
// 不返回错误,继续初始化
|
||||
} else {
|
||||
ESP_LOGI(I2C_INIT, "线性马达设备检测成功(地址:0x%02X)", LINEAR_MOTOR_I2C_SLAVE_ADDR);
|
||||
}
|
||||
// 验证IO扩展板设备是否存在
|
||||
err = i2c_bus_probe_addr(bus_handle_, I2C_IO_EXPAND_SLAVE_ADDR << 1);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(I2C_INIT, "IO扩展板设备未找到(地址:0x%02X),错误码: 0x%x", I2C_IO_EXPAND_SLAVE_ADDR, err);
|
||||
// 不返回错误,继续初始化其他设备
|
||||
} else {
|
||||
ESP_LOGI(I2C_INIT, "IO扩展板设备检测成功(地址:0x%02X)", I2C_IO_EXPAND_SLAVE_ADDR);
|
||||
}
|
||||
// 验证陀螺仪设备是否存在
|
||||
err = i2c_bus_probe_addr(bus_handle_, GYROSCOPE_I2C_SLAVE_ADDR << 1);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(I2C_INIT, "陀螺仪设备未找到(地址:0x%02X),错误码: 0x%x", GYROSCOPE_I2C_SLAVE_ADDR, err);
|
||||
// 不返回错误,继续初始化
|
||||
} else {
|
||||
ESP_LOGI(I2C_INIT, "陀螺仪设备检测成功(地址:0x%02X)", GYROSCOPE_I2C_SLAVE_ADDR);
|
||||
}
|
||||
|
||||
// 为IO扩展板设置总线句柄和设备地址(使用7位地址)
|
||||
io_expansion_.bus_handle_ = bus_handle_;
|
||||
io_expansion_.device_addr_ = I2C_IO_EXPAND_SLAVE_ADDR << 1;
|
||||
|
||||
// 为线性马达设置总线句柄和设备地址(使用7位地址)
|
||||
linear_motor_.bus_handle_ = bus_handle_;
|
||||
linear_motor_.device_addr_ = LINEAR_MOTOR_I2C_SLAVE_ADDR << 1;
|
||||
|
||||
ESP_LOGI(I2C_INIT, "I2C总线初始化完成");
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
/*========================== VBAT to VBAT_5V相关驱动 ==========================*/
|
||||
|
||||
/**
|
||||
* @brief 开启VBAT to VBAT_5V
|
||||
*
|
||||
* 创建开启升压的电源管理单元
|
||||
*
|
||||
*/
|
||||
void BoardSweekar::VbatToVbat5vInit(void)
|
||||
{
|
||||
// 配置VBAT_5V引脚为输出模式
|
||||
gpio_config_t io_conf = {
|
||||
.pin_bit_mask = (1ULL << VBAT_5V_PIN),
|
||||
.mode = GPIO_MODE_OUTPUT,
|
||||
.pull_up_en = GPIO_PULLUP_DISABLE,
|
||||
.pull_down_en = GPIO_PULLDOWN_DISABLE,
|
||||
.intr_type = GPIO_INTR_DISABLE
|
||||
};
|
||||
gpio_config(&io_conf);
|
||||
// 使能VBAT_5V
|
||||
gpio_set_level(VBAT_5V_PIN, 1);
|
||||
}
|
||||
|
||||
/*========================== 底座控制串口相关驱动 ==========================*/
|
||||
|
||||
/**
|
||||
* @brief 底座控制命令串口初始化函数
|
||||
*/
|
||||
void BoardSweekar::BaseBoardControlUartInit(void)
|
||||
{
|
||||
uart_config_t uart_config = {
|
||||
.baud_rate = BASE_BOARD_CTL_UART_BAUDRATE,
|
||||
.data_bits = UART_DATA_8_BITS,
|
||||
.parity = UART_PARITY_DISABLE,
|
||||
.stop_bits = UART_STOP_BITS_1,
|
||||
.flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
|
||||
.source_clk = UART_SCLK_DEFAULT,
|
||||
};
|
||||
|
||||
// 1. 设置串口参数
|
||||
ESP_ERROR_CHECK(uart_param_config(BASE_BOARD_CTL_UART_PORT, &uart_config));
|
||||
|
||||
// 2. 设置 UART 引脚
|
||||
ESP_ERROR_CHECK(uart_set_pin(BASE_BOARD_CTL_UART_PORT, BASE_BOARD_CTL_UART_TX_PIN, BASE_BOARD_CTL_UART_RX_PIN,
|
||||
UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE));
|
||||
|
||||
// 3. 安装 UART 驱动
|
||||
ESP_ERROR_CHECK(uart_driver_install(BASE_BOARD_CTL_UART_PORT,
|
||||
BASE_BOARD_CTL_UART_BUF_SIZE,
|
||||
BASE_BOARD_CTL_UART_BUF_SIZE,
|
||||
0, NULL, 0));
|
||||
|
||||
base_board_control_.SetUartPort(BASE_BOARD_CTL_UART_PORT);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
#ifndef __BOARD_H__
|
||||
#define __BOARD_H__
|
||||
#include "config.h"
|
||||
#include "io_expansion_board.h"
|
||||
#include "stepper_motor.h"
|
||||
#include "i2c_bus.h"
|
||||
#include "gyroscope.h"
|
||||
#include "touch_sensor.h"
|
||||
#include "base_board_control.h"
|
||||
|
||||
class BoardSweekar
|
||||
{
|
||||
private:
|
||||
i2c_bus_handle_t bus_handle_ = nullptr; // 使用ESP-ADF的I2C总线句柄
|
||||
|
||||
public:
|
||||
IOExpansionBoard io_expansion_; // IO扩展板对象
|
||||
LinearMotor linear_motor_; // 线性马达对象
|
||||
Gyroscope gyroscope_; // 陀螺仪对象
|
||||
TouchSensor touch_sensor_; // 触摸传感器对象
|
||||
BaseBoardControl base_board_control_; // 底座控制对象
|
||||
|
||||
|
||||
// 初始化步进电机
|
||||
void StepperMotorInit(void);
|
||||
|
||||
// 初始化串口
|
||||
void MillimeterWaveRadarUartInit(void);
|
||||
|
||||
//初始化毫米波雷达的中断引脚
|
||||
void MillimeterWaveRadarGpioInit(void);
|
||||
|
||||
// 初始化I2C总线
|
||||
esp_err_t I2CMasterInit(void);
|
||||
|
||||
// 初始化VBAT toVBAT_5V引脚
|
||||
void VbatToVbat5vInit(void);
|
||||
|
||||
// 初始化底座控制串口
|
||||
void BaseBoardControlUartInit(void);
|
||||
|
||||
// 获取I2C总线句柄
|
||||
i2c_bus_handle_t GetBusHandle() const { return bus_handle_; }
|
||||
};
|
||||
#endif
|
||||
@@ -0,0 +1,145 @@
|
||||
/* 定义引脚分配 */
|
||||
#ifndef _BOARD_CONFIG_H_
|
||||
#define _BOARD_CONFIG_H_
|
||||
|
||||
/**
|
||||
* @file config.h
|
||||
* @brief 定义了引脚的分配。
|
||||
* @author zouyuhua
|
||||
* @date 2025年8月7日
|
||||
*
|
||||
*/
|
||||
|
||||
#include "driver/gpio.h"
|
||||
#include "driver/i2c_master.h"
|
||||
#include "driver/i2s.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_rom_sys.h" // 用于 esp_rom_delay_us
|
||||
#include "esp_timer.h"
|
||||
#include "esp_mac.h"
|
||||
#include "driver/ledc.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "esp_log.h"
|
||||
#include "driver/timer.h"
|
||||
#include "esp_intr_alloc.h"
|
||||
#include "soc/timer_group_struct.h" // 包含TIMERG0、TIMERG1的结构体定义
|
||||
#include "soc/timer_group_reg.h" // 包含定时器相关寄存器宏定义
|
||||
#include "driver/uart.h"
|
||||
#include "esp_err.h"
|
||||
#include "freertos/queue.h"
|
||||
#include "soc/uart_reg.h"
|
||||
#include "linear_motor.h"
|
||||
#include "gyroscope.h"
|
||||
|
||||
#define TAG_BOARD "SWEEKAR_ESP32"
|
||||
/*I2C总线引脚定义*/
|
||||
#define I2C0_MASTER_PORT I2C_NUM_0
|
||||
#define I2C0_MASTER_SDA_IO GPIO_NUM_2
|
||||
#define I2C0_MASTER_SCL_IO GPIO_NUM_3
|
||||
|
||||
/* 步进电机配置 */
|
||||
#define STEPPER_STEP_IO GPIO_NUM_42 // 步进电机脉冲输入引脚
|
||||
#define STEPPER_TIMER_RES_HZ 1000000 // 步进电机定时器分辨率 1 MHz(1 us 步进)
|
||||
|
||||
/* 定义屏幕驱动控制引脚 */
|
||||
#define ST7789_PIN_CLK GPIO_NUM_48 // SPI时钟引脚
|
||||
#define ST7789_PIN_DC GPIO_NUM_38 // 数据/命令选择引脚RSEL
|
||||
#define ST7789_PIN_MOSI GPIO_NUM_47 // SPI数据输出引脚
|
||||
#define ST7789_PIN_CS GPIO_NUM_46 // SPI片选引脚
|
||||
#define ST7789_PIN_BL GPIO_NUM_NC // 背光引脚
|
||||
#define ST7789_PIN_RST GPIO_NUM_NC // 复位引脚
|
||||
#define LCD_BL_ACTIVE_LEVEL 0 // 背光有效电平:1=高电平有效(NMOS),0=低电平有效(PMOS)
|
||||
|
||||
#define LCD_WIDTH 172 // 屏幕宽度(水平方向像素数)
|
||||
#define LCD_HEIGHT 320 // 屏幕高度(垂直方向像素数)
|
||||
|
||||
/* 毫米波雷达配置参数 */
|
||||
/* 定义毫米波雷达的中断引脚 */
|
||||
#define MILLIMETER_WAVE_RADAR_PIN GPIO_NUM_35
|
||||
// UART 配置参数
|
||||
#define RADAR_UART_NUM UART_NUM_1 // 使用 UART1
|
||||
#define UART_TX_PIN GPIO_NUM_40 // GPIO40 作为 TX(根据实际硬件连接调整)
|
||||
#define UART_RX_PIN GPIO_NUM_39 // GPIO39 作为 RX
|
||||
#define RADAR_BAUD_RATE 9600 // 雷达波特率
|
||||
#define RADAR_BUF_SIZE 100 // 雷达接收缓冲区大小
|
||||
|
||||
/* IO扩展硬件配置常量 */
|
||||
#define I2C_MASTER_FREQ_HZ 100000 // I2C通信频率(100kHz)(可更改至400000)
|
||||
#define I2C_IO_EXPAND_SLAVE_ADDR 0x58 // AW9523BTQR器件地址,v1_1_13的addr1和addr0是0
|
||||
#define GPIO_INPUT_PIN_SEL GPIO_NUM_10 // 中断检测引脚
|
||||
#define ESP_INTR_FLAG_DEFAULT 0 // 中断标志默认值
|
||||
#define IO_EXPAND_RSTN GPIO_NUM_45 // IO扩展板复位引脚
|
||||
|
||||
/* 定义线性马达的I2C从机配置常量 */
|
||||
#define LINEAR_MOTOR_I2C_SLAVE_ADDR 0x5A // 线性马达的I2C从机地址
|
||||
|
||||
/* 定义陀螺仪的I2C从机配置常量 */
|
||||
#define GYROSCOPE_I2C_SLAVE_ADDR 0x6A // 陀螺仪的I2C从机地址
|
||||
#define GYROSCOPE_INPUT_PIN_SEL GPIO_NUM_21 // 陀螺仪中断引脚
|
||||
|
||||
/* 原生触摸引脚配置 */
|
||||
// 触摸按键数量配置
|
||||
#define TOUCH_BUTTON_NUM 3
|
||||
// 触摸通道定义
|
||||
#define TOUCH_PAD_CHANNEL_1 TOUCH_PAD_NUM11 // GPIO11
|
||||
#define TOUCH_PAD_CHANNEL_2 TOUCH_PAD_NUM12 // GPIO12
|
||||
#define TOUCH_PAD_CHANNEL_3 TOUCH_PAD_NUM13 // GPIO13
|
||||
|
||||
/* ES8311音频编解码器配置 (ESP-ADF兼容) */
|
||||
#define AUDIO_INPUT_SAMPLE_RATE 24000
|
||||
#define AUDIO_OUTPUT_SAMPLE_RATE 24000
|
||||
#define AUDIO_INPUT_REFERENCE true
|
||||
|
||||
/* I2S GPIO定义 */
|
||||
#define AUDIO_I2S_GPIO_MCLK GPIO_NUM_15
|
||||
#define AUDIO_I2S_GPIO_WS GPIO_NUM_4
|
||||
#define AUDIO_I2S_GPIO_BCLK GPIO_NUM_5
|
||||
#define AUDIO_I2S_GPIO_DIN GPIO_NUM_6
|
||||
#define AUDIO_I2S_GPIO_DOUT GPIO_NUM_7
|
||||
|
||||
/* PA引脚定义 */
|
||||
#define AUDIO_CODEC_PA_PIN GPIO_NUM_NC
|
||||
|
||||
/* I2C配置 */
|
||||
#define AUDIO_CODEC_I2C_SDA_PIN GPIO_NUM_2
|
||||
#define AUDIO_CODEC_I2C_SCL_PIN GPIO_NUM_3
|
||||
#define AUDIO_CODEC_ES8311_ADDR 0x18
|
||||
#define AUDIO_CODEC_ES7210_ADDR 0x40
|
||||
|
||||
/* WS2812 RGB LED配置 */
|
||||
#define WS2812_PIN GPIO_NUM_41 // WS2812数据引脚
|
||||
#define WS2812_NUM_LEDS 2 // WS2812 LED数量
|
||||
|
||||
/* 创建VBAT to VBAT_5V */
|
||||
#define VBAT_5V_PIN GPIO_NUM_NC // VBAT_5V引脚
|
||||
|
||||
/* 定义按键的中断引脚 */
|
||||
#define BUTTON_PIN GPIO_NUM_0 // 按键中断引脚
|
||||
#define RIGHT_BUTTON_PIN GPIO_NUM_8 // 按键中断引脚
|
||||
|
||||
/* 底座控制命令串口配置 */
|
||||
#define BASE_BOARD_CTL_UART_PORT UART_NUM_0
|
||||
#define BASE_BOARD_CTL_UART_TX_PIN GPIO_NUM_43
|
||||
#define BASE_BOARD_CTL_UART_RX_PIN GPIO_NUM_44
|
||||
#define BASE_BOARD_CTL_UART_BAUDRATE 115200
|
||||
#define BASE_BOARD_CTL_UART_BUF_SIZE 256
|
||||
|
||||
#endif // _BOARD_CONFIG_H_
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,419 @@
|
||||
#ifndef IO_EXPANSION_BOARD_H
|
||||
#define IO_EXPANSION_BOARD_H
|
||||
|
||||
#include <cstdint>
|
||||
#include <esp_log.h>
|
||||
#include <esp_check.h>
|
||||
#include <esp_timer.h>
|
||||
#include <driver/gpio.h>
|
||||
#include <functional>
|
||||
#include "i2c_bus.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/event_groups.h"
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
#include <freertos/FreeRTOS.h>
|
||||
#include <freertos/task.h>
|
||||
#include <freertos/queue.h>
|
||||
#include <freertos/semphr.h>
|
||||
#include "esp_err.h"
|
||||
#include "config.h"
|
||||
#include "portmacro.h"
|
||||
|
||||
// 前向声明,避免循环引用
|
||||
class MillimeterWaveRadar;
|
||||
class PhotoInterrupter;
|
||||
class AdcBatteryMonitor;
|
||||
|
||||
// 回调函数类型定义
|
||||
typedef std::function<void()> RadarCallback;
|
||||
typedef std::function<void()> PhotoInterrupterStartCallback;
|
||||
typedef std::function<void()> PhotoInterrupterEndCallback;
|
||||
typedef std::function<void()> BatteryChargingCallback;
|
||||
typedef std::function<void()> BatteryFullCallback;
|
||||
typedef std::function<void()> BatteryNotChargingCallback;
|
||||
|
||||
/* 寄存器地址 */
|
||||
#define INPUT_PORT0 0x00 // 输入端口0寄存器
|
||||
#define INPUT_PORT1 0x01 // 输入端口1寄存器 0为低电平(仅支持读取)
|
||||
#define OUTPUT_PORT0 0x02 // 输出端口0寄存器
|
||||
#define OUTPUT_PORT1 0x03 // 输出端口1寄存器 0为低电平
|
||||
#define CONFIG_PORT0 0x04 // 配置端口0寄存器
|
||||
#define CONFIG_PORT1 0x05 // 配置端口1寄存器 0为输出模式
|
||||
#define INT_PORT0 0x06 // 中断端口0寄存器
|
||||
#define INT_PORT1 0x07 // 中断端口1寄存器 0为使能中断(根据手册默认是使能的)
|
||||
#define CTL 0x11 // 全局控制寄存器
|
||||
#define ID 0x23 // 芯片ID寄存器(0x23)
|
||||
|
||||
/***********************************IO扩展板电机引脚配置参数*************************************/
|
||||
/* 设置步进电机方向 */
|
||||
#define STEPPER_MOTOR_LEFT false //步进电机的方向为左转
|
||||
#define STEPPER_MOTOR_RIGHT true //步进电机的方向为右转
|
||||
#define STEPPER_MOTOR_DIR_PORT OUTPUT_PORT0 //步进电机方向引脚挂载在IO扩展板的输出端口OUTPUT_PORT0
|
||||
#define STEPPER_MOTOR_DIR_PIN 4 //步进电机方向引脚对应的IO扩展板引脚P0_4
|
||||
#define STEPPER_MOTOR_DIR_CONFIG CONFIG_PORT0 //步进电机方向引脚配置在P0_4
|
||||
|
||||
/* 设置步进电机细分模式 */
|
||||
#define STEPPER_MOTOR_M0_PIN 5 //步进电机细分模式选择引脚对应IO扩展板引脚P1_5
|
||||
#define STEPPER_MOTOR_M0_MADE_PORT OUTPUT_PORT1 //步进电机模式选择引脚挂载在IO扩展板的输出端口OUTPUT_PORT1
|
||||
#define STEPPER_MOTOR_M0_CONFIG CONFIG_PORT1 //步进电机细分模式选择引脚配置在P1_5
|
||||
|
||||
#define STEPPER_MOTOR_M1_PIN 4 //步进电机细分模式选择引脚对应IO扩展板引脚P1_4
|
||||
#define STEPPER_MOTOR_M1_MADE_PORT OUTPUT_PORT1 //步进电机模式选择引脚挂载在IO扩展板的输出端口OUTPUT_PORT1
|
||||
#define STEPPER_MOTOR_M1_CONFIG CONFIG_PORT1 //步进电机细分模式选择引脚配置在P1_4
|
||||
|
||||
/* 设置步进电机睡眠引脚 */
|
||||
#define STEPPER_MOTOR_SLEEP false //步进电机进入睡眠模式
|
||||
#define STEPPER_MOTOR_WORK true //步进电机进入工作模式
|
||||
#define STEPPER_MOTOR_SLEEP_PIN 6 //步进电机睡眠引脚对应IO扩展板引脚P1_6
|
||||
#define STEPPER_MOTOR_SLEEP_CONFIG CONFIG_PORT1 //步进电机睡眠引脚配置在P1_6
|
||||
#define STEPPER_MOTOR_SLEEP_PORT OUTPUT_PORT1 //步进电机睡眠引脚挂载在IO扩展板的输出端口OUTPUT_PORT1
|
||||
|
||||
/* 设置电机的使能引脚 */
|
||||
#define STEPPER_MOTOR_ENABLE_PIN 7 //电机使能引脚对应IO扩展板引脚P0_7
|
||||
#define STEPPER_MOTOR_ENABLE_PORT OUTPUT_PORT0 //电机使能引脚挂载在IO扩展板的输出端口OUTPUT_PORT0
|
||||
#define STEPPER_MOTOR_ENABLE_CONFIG CONFIG_PORT0 //电机使能引脚配置在P0_7
|
||||
#define STEPPER_MOTOR_ENABLE_ENABLE true //电机使能引脚状态为高电平
|
||||
#define STEPPER_MOTOR_ENABLE_DISABLE false //电机使能引脚状态为低电平
|
||||
|
||||
/* 设置毫米波雷达对应IO扩展板的中断引脚 */
|
||||
#define RADAR_INTERRUPT_PIN 7 //毫米波雷达中断引脚对应IO扩展板引脚P1_7
|
||||
#define RADAR_INTERRUPT_CONFIG CONFIG_PORT1 //毫米波雷达中断引脚挂载在IO扩展板的输入端口
|
||||
#define RADAR_INTERRUPT_INPUT INPUT_PORT1 //毫米波雷达中断引脚输入状态检测在INPUT_PORT1
|
||||
#define RADAR_INTERRUPT_ENABLE true //毫米波雷达中断引脚状态为输入状态
|
||||
#define RADAR_INTERRUPT_DISABLE false //毫米波雷达中断引脚状态为输出状态
|
||||
/* 任务配置常量 */
|
||||
#define WRITE_BUF_SIZE 2 // I2C单次写入字节数
|
||||
#define READ_BUF_SIZE 2 // I2C单次读取字节数
|
||||
#define I2C_TASK_PRIORITY 2 // 任务优先级(中等)
|
||||
#define I2C_TASK_STACK 4096 // 任务栈大小(4KB)
|
||||
|
||||
// 光学传感器引脚定义
|
||||
#define START_PHOTO_INTERRUPTER_PIN 2 // 光学传感器引脚(P0_2)
|
||||
#define START_PHOTO_INTERRUPTER_CONFIG CONFIG_PORT0 // 光学传感器引脚挂载在IO扩展板的输入端口
|
||||
#define START_PHOTO_INTERRUPTER_INPUT INPUT_PORT0 // 光学传感器引脚输入状态检测在INPUT_PORT0
|
||||
#define START_PHOTO_INTERRUPTER_HIGH true // 光学传感器引脚状态为高电平
|
||||
#define START_PHOTO_INTERRUPTER_LOW false // 光学传感器引脚状态为低电平
|
||||
|
||||
#define END_PHOTO_INTERRUPTER_PIN 3 // 光学传感器引脚(P0_3)
|
||||
#define END_PHOTO_INTERRUPTER_PORT_CONFIG CONFIG_PORT0 // 光学传感器引脚挂载在IO扩展板的输入端口
|
||||
#define END_PHOTO_INTERRUPTER_INPUT INPUT_PORT0 // 光学传感器引脚输入状态检测在INPUT_PORT0
|
||||
#define END_PHOTO_INTERRUPTER_HIGH true // 光学传感器引脚状态为高电平
|
||||
#define END_PHOTO_INTERRUPTER_LOW false // 光学传感器引脚状态为低电平
|
||||
|
||||
/***********************************IO扩展板LCD引脚配置参数*************************************/
|
||||
/* 设置LCD的BL引脚 */
|
||||
#define LCD_BL_PIN 6 //LCD背光引脚对应IO扩展板引脚P0_6
|
||||
#define LCD_BL_PORT OUTPUT_PORT0 //LCD背光引脚挂载在IO扩展板的输出端口OUTPUT_PORT0
|
||||
#define LCD_BL_CONFIG CONFIG_PORT0 //LCD背光引脚配置在P0_6
|
||||
#define LCD_BL_HIGH true //LCD背光引脚状态为高电平
|
||||
#define LCD_BL_LOW false //LCD背光引脚状态为低电平
|
||||
|
||||
/* 设置LCD的RST引脚 */
|
||||
#define LCD_RST_PIN 1 //LCD复位引脚对应IO扩展板引脚P1_1
|
||||
#define LCD_RST_CONFIG CONFIG_PORT1 //LCD复位引脚配置在P1_1
|
||||
#define LCD_RST_PORT OUTPUT_PORT1 //LCD复位引脚挂载在IO扩展板的输出端口OUTPUT_PORT1
|
||||
#define LCD_RST_HIGH true //LCD复位引脚状态为高电平
|
||||
#define LCD_RST_LOW false //LCD复位引脚状态为低电平
|
||||
|
||||
/* 设置PA控制引脚 */
|
||||
#define PA_CTRL_PIN 2 //PA控制引脚对应IO扩展板引脚P1_2
|
||||
#define PA_CTRL_CONFIG CONFIG_PORT1 //PA控制引脚配置在P1_2
|
||||
#define PA_CTRL_PORT OUTPUT_PORT1 //PA控制引脚挂载在IO扩展板的输出端口OUTPUT_PORT1
|
||||
#define PA_CTRL_HIGH true //PA控制引脚状态为高电平
|
||||
#define PA_CTRL_LOW false //PA控制引脚状态为低电平
|
||||
|
||||
// 电池充电检测引脚定义
|
||||
#define BATTERY_FULL_INPUT INPUT_PORT1 // 电池充满检测引脚挂载在IO扩展板的输入端口
|
||||
#define BATTERY_FULL_PIN 3 // 电池充满检测引脚对应IO扩展板引脚P1_3
|
||||
#define BATTERY_FULL_CONFIG CONFIG_PORT1 // 电池充满检测引脚配置在P1_3
|
||||
|
||||
#define BATTERY_CHRG_INPUT INPUT_PORT0 // 充电检测引脚挂载在IO扩展板的输入端口
|
||||
#define BATTERY_CHRG_PIN 5 // 充电检测引脚(P0_5)
|
||||
#define BATTERY_CHRG_CONFIG CONFIG_PORT0 // 充电检测引脚挂载在IO扩展板的输入端口
|
||||
|
||||
#define TAG_GPIO_IO_EXPAND_DETECT "GPIO_IO_EXPAND_DETECT" // GPIO中断检测日志标签
|
||||
#define TAG_I2C_IO_EXPAND_TASK "I2C_IO_EXPAND_TASK" // I2CIO扩展板任务日志标签
|
||||
|
||||
// GPIO引脚定义
|
||||
#define GPIO_INPUT_PIN_SEL GPIO_NUM_10 // IO扩展板中断检测引脚
|
||||
#define IO_EXPAND_RSTN GPIO_NUM_45 // IO扩展板复位引脚
|
||||
|
||||
/**
|
||||
* @class IOExpansionBoard
|
||||
* @brief I/O扩展板驱动类,封装AW9523BTQR芯片操作
|
||||
*/
|
||||
class IOExpansionBoard
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief 构造函数
|
||||
*/
|
||||
IOExpansionBoard();
|
||||
|
||||
/**
|
||||
* @brief 设置毫米波雷达指针
|
||||
* @param radar 毫米波雷达对象指针
|
||||
*/
|
||||
void SetRadar(MillimeterWaveRadar* radar) { radar_ = radar; };
|
||||
|
||||
/**
|
||||
* @brief 设置限位开关指针
|
||||
* @param photo_interrupter 限位开关对象指针
|
||||
*/
|
||||
void setPhotoInterrupter(PhotoInterrupter* photo_interrupter) { photo_interrupter_ = photo_interrupter; };
|
||||
|
||||
/**
|
||||
* @brief 设置电池监控器指针
|
||||
* @param battery_monitor 电池监控器对象指针
|
||||
*/
|
||||
void setBatteryMonitor(AdcBatteryMonitor* battery_monitor) { battery_monitor_ = battery_monitor; };
|
||||
|
||||
/**
|
||||
* @brief 析构函数
|
||||
*/
|
||||
~IOExpansionBoard();
|
||||
|
||||
/**
|
||||
* @brief 初始化GPIO中断检测
|
||||
* @param gpio_num 中断引脚编号
|
||||
* @return esp_err_t 初始化结果
|
||||
*/
|
||||
esp_err_t InterruptGpioInit(gpio_num_t gpio_num);
|
||||
|
||||
/**
|
||||
* @brief 初始化IO扩展板复位引脚
|
||||
* @param gpio_num 复位引脚编号
|
||||
* @return esp_err_t 初始化结果
|
||||
*/
|
||||
esp_err_t ResetGpioInit(gpio_num_t gpio_num);
|
||||
|
||||
/**
|
||||
* @brief 初始化IO扩展板复位引脚
|
||||
* @param gpio_num 复位引脚编号
|
||||
* @return esp_err_t 初始化结果
|
||||
*/
|
||||
esp_err_t ResetIoExpand();
|
||||
|
||||
/**
|
||||
* @brief 初始化I2C主机通信
|
||||
* @return esp_err_t 初始化结果
|
||||
*/
|
||||
// esp_err_t IoExpansionI2cInit();
|
||||
|
||||
/**
|
||||
* @brief 创建I2C数据读取任务
|
||||
*/
|
||||
void CreateI2cReadTask();
|
||||
|
||||
/**
|
||||
* @brief 启动I2C任务(整合初始化和任务创建)
|
||||
* @return esp_err_t 操作结果
|
||||
*/
|
||||
esp_err_t StartTask();
|
||||
|
||||
/**
|
||||
* @brief 写寄存器数据
|
||||
* @param reg_addr 寄存器地址
|
||||
* @param data 要写入的数据
|
||||
* @return esp_err_t 操作结果
|
||||
*/
|
||||
esp_err_t IoexpandWriteReg(uint8_t reg_addr, uint8_t data);
|
||||
|
||||
/**
|
||||
* @brief 读寄存器数据
|
||||
* @param reg_addr 寄存器地址
|
||||
* @param data 要读出的数据
|
||||
* @return esp_err_t 操作结果
|
||||
*/
|
||||
esp_err_t IoexpandReadReg(uint8_t reg_addr, uint8_t *data);
|
||||
|
||||
/**
|
||||
* @brief 读取输入端口0寄存器数据
|
||||
* @param data 输出参数,用于存储读取到的数据
|
||||
* @return esp_err_t 操作结果
|
||||
*/
|
||||
esp_err_t ReadInputPort0(uint8_t *data);
|
||||
|
||||
/**
|
||||
* @brief 读取输入端口1寄存器数据
|
||||
* @param data 输出参数,用于存储读取到的数据
|
||||
* @return esp_err_t 操作结果
|
||||
*/
|
||||
esp_err_t ReadInputPort1(uint8_t *data);
|
||||
|
||||
// /**
|
||||
// * @brief 设置IO扩展板GPIO中断状态 通过读取Input_Port0 和 Input_Port1 寄存器可以清除中断
|
||||
// * @param reg_addr 寄存器地址
|
||||
// * @return esp_err_t 操作结果
|
||||
// */
|
||||
// esp_err_t SetInterruptStatus(bool status);
|
||||
|
||||
/**
|
||||
* @brief 配置IO扩展版上的IO口为输出还是输入,并且设置初始为高电平
|
||||
* @return esp_err_t 操作结果
|
||||
*/
|
||||
esp_err_t IoexpandSetMode();
|
||||
|
||||
/**
|
||||
* @brief 设置步进电机的细分模式
|
||||
* @param mode 模式:1/2/4/8/16/32/64
|
||||
* @return esp_err_t 操作结果
|
||||
*/
|
||||
void SetStepperMicrostepMode(uint8_t mode, uint8_t OUTPUT_PORT_m0, uint8_t m0_pin, uint8_t OUTPUT_PORT_m1, uint8_t m1_pin);
|
||||
|
||||
/**
|
||||
* @brief 设置步进电机的方向
|
||||
* @param dir 方向
|
||||
* @param OUTPUT_PORT 输出端口
|
||||
* @param pin 引脚号
|
||||
* @return esp_err_t 操作结果
|
||||
*/
|
||||
esp_err_t StepperMotorSetDir(bool dir, uint8_t OUTPUT_PORT, uint8_t pin);
|
||||
|
||||
/**
|
||||
* @brief 设置步进电机的睡眠模式
|
||||
* @param 是否进入睡眠模式
|
||||
* @param 输出端口
|
||||
* @param 引脚号
|
||||
* @return esp_err_t 操作结果
|
||||
*/
|
||||
esp_err_t SetMotorSleepMode(bool mode, uint8_t OUTPUT_PORT, uint8_t nsleep_pin);
|
||||
|
||||
/**
|
||||
* @brief 设置步进电机的使能引脚状态
|
||||
* @param 使能状态
|
||||
* @return esp_err_t 操作结果
|
||||
*/
|
||||
esp_err_t SetMotorEnableMode(bool enable, uint8_t OUTPUT_PORT, uint8_t enable_pin);
|
||||
|
||||
/**
|
||||
* @brief 设置LCD的BL引脚状态
|
||||
* @param BL状态
|
||||
* @return esp_err_t 操作结果
|
||||
*/
|
||||
esp_err_t SetLcdBlMode(bool mode, uint8_t OUTPUT_PORT, uint8_t bl_pin);
|
||||
|
||||
/**
|
||||
* @brief 设置LCD的RST引脚状态
|
||||
* @param RST状态
|
||||
* @return esp_err_t 操作结果
|
||||
*/
|
||||
esp_err_t SetLcdResetMode(bool mode, uint8_t OUTPUT_PORT, uint8_t rst_pin);
|
||||
|
||||
/**
|
||||
* @brief 设置PA控制引脚状态
|
||||
* @param PA_CTRL状态(低电平为选中状态,高电平为不选中状态)
|
||||
* @return esp_err_t 操作结果
|
||||
*/
|
||||
esp_err_t SetPaCtrlMode(bool mode, uint8_t OUTPUT_PORT, uint8_t pa_ctrl_pin);
|
||||
|
||||
/**
|
||||
* @brief 设置雷达中断引脚
|
||||
* @param 毫米波雷达的中断引脚模式
|
||||
* @param 输入端口
|
||||
* @param 引脚号
|
||||
* @return esp_err_t 操作结果
|
||||
*/
|
||||
esp_err_t SetRadarInterruptPin(bool mode, uint8_t INPUT_PORT, uint8_t interrupt_pin);
|
||||
|
||||
/**
|
||||
* @brief 计算Port0的字节值
|
||||
* @return uint8_t 操作结果
|
||||
*/
|
||||
uint8_t ByteCalculatePort0();
|
||||
|
||||
/**
|
||||
* @brief 计算Port1的字节值
|
||||
* @return uint8_t 操作结果
|
||||
*/
|
||||
uint8_t ByteCalculatePort1();
|
||||
|
||||
/**
|
||||
* @brief 设置雷达中断回调函数
|
||||
* @param callback 雷达中断回调函数
|
||||
*/
|
||||
void SetRadarCallback(RadarCallback callback) { radar_callback_ = callback; }
|
||||
|
||||
/**
|
||||
* @brief 设置光学传感器开始中断回调函数
|
||||
* @param callback 光学传感器开始中断回调函数
|
||||
*/
|
||||
void SetPhotoInterrupterStartCallback(PhotoInterrupterStartCallback callback) { photo_start_callback_ = callback; }
|
||||
|
||||
/**
|
||||
* @brief 设置光学传感器结束中断回调函数
|
||||
* @param callback 光学传感器结束中断回调函数
|
||||
*/
|
||||
void SetPhotoInterrupterEndCallback(PhotoInterrupterEndCallback callback) { photo_end_callback_ = callback; }
|
||||
|
||||
/**
|
||||
* @brief 设置电池充电中断回调函数
|
||||
* @param callback 电池充电中断回调函数
|
||||
*/
|
||||
void SetBatteryChargingCallback(BatteryChargingCallback callback) { battery_charging_callback_ = callback; }
|
||||
|
||||
/**
|
||||
* @brief 设置电池充满中断回调函数
|
||||
* @param callback 电池充满中断回调函数
|
||||
*/
|
||||
void SetBatteryFullCallback(BatteryFullCallback callback) { battery_full_callback_ = callback; }
|
||||
|
||||
/**
|
||||
* @brief 设置电池非充电中断回调函数
|
||||
* @param callback 电池非充电中断回调函数
|
||||
*/
|
||||
void SetBatteryNotChargingCallback(BatteryNotChargingCallback callback) { battery_not_charging_callback_ = callback; }
|
||||
|
||||
// 公共成员变量
|
||||
i2c_bus_handle_t bus_handle_ = nullptr; // I2C总线句柄
|
||||
uint8_t device_addr_; // I2C设备地址
|
||||
|
||||
private:
|
||||
// 静态成员函数
|
||||
MillimeterWaveRadar* radar_ = nullptr; // 毫米波雷达指针,用于触发回调
|
||||
PhotoInterrupter* photo_interrupter_ = nullptr; // 限位开关指针,用于触发回调
|
||||
AdcBatteryMonitor* battery_monitor_ = nullptr; // 电池监控器指针,用于触发回调
|
||||
static void IRAM_ATTR GpioIsrHandler(void* arg); // 中断处理函数
|
||||
static void I2cReadTask(void* pvParameters); // I2C数据读取任务函数
|
||||
|
||||
// 成员变量用于状态跟踪
|
||||
uint8_t last_port0_state_ = 0; // 上次检测到的Port0状态
|
||||
uint8_t last_port1_state_ = 0; // 上次检测到的Port1状态
|
||||
bool radar_last_state_ = false; // 雷达引脚上一次的状态
|
||||
bool battery_charging_last_state_ = false; // 电池充电状态上一次的状态
|
||||
bool battery_full_last_state_ = false; // 电池充满状态上一次的状态
|
||||
|
||||
// 回调函数成员变量
|
||||
RadarCallback radar_callback_ = nullptr;
|
||||
PhotoInterrupterStartCallback photo_start_callback_ = nullptr;
|
||||
PhotoInterrupterEndCallback photo_end_callback_ = nullptr;
|
||||
BatteryChargingCallback battery_charging_callback_ = nullptr;
|
||||
BatteryFullCallback battery_full_callback_ = nullptr;
|
||||
BatteryNotChargingCallback battery_not_charging_callback_ = nullptr;
|
||||
|
||||
// PhotoInterrupter* photo_interrupter_ = nullptr; // 光学传感器指针,用于触发回调
|
||||
// /**
|
||||
// * @brief 分配静态任务所需的内存
|
||||
// * @return bool 分配是否成功
|
||||
// */
|
||||
// bool AllocateStaticTaskMemory();
|
||||
|
||||
// /**
|
||||
// * @brief 释放静态任务分配的内存
|
||||
// */
|
||||
// void FreeStaticTaskMemory();
|
||||
|
||||
// 实例成员变量
|
||||
EventGroupHandle_t i2c_task_event_group_ = nullptr; // 事件组
|
||||
TaskHandle_t xI2CReadTaskHandle_ = nullptr; // 任务句柄
|
||||
bool is_initialized_ = false; // 初始化状态标记(新增)
|
||||
gpio_num_t interrupt_gpio_ = GPIO_NUM_NC; // 中断引脚
|
||||
gpio_num_t reset_gpio_ = GPIO_NUM_NC; // 复位引脚
|
||||
|
||||
// StackType_t* pI2CReadTaskStackBuffer = nullptr; // 任务栈指针(PSRAM)
|
||||
// StaticTask_t* pxI2CReadTaskBuffer = nullptr; // 任务控制块指针(内部RAM)
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,702 @@
|
||||
/**
|
||||
* @file board.cc
|
||||
* @brief 板级外设初始化类,包含步进电机、毫米波雷达、I2C总线等外设的初始化函数。
|
||||
* @author zouyuhua
|
||||
* @date 2025年8月7日
|
||||
*
|
||||
*/
|
||||
|
||||
extern "C" {
|
||||
#include "esp_log.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "driver/uart.h"
|
||||
#include "driver/ledc.h"
|
||||
#include "driver/gptimer.h"
|
||||
#include "esp_err.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "hal/gpio_types.h"
|
||||
#include "hal/uart_types.h"
|
||||
#include "esp_check.h"
|
||||
#include "sdkconfig.h"
|
||||
#include "i2c_bus.h"
|
||||
#include "esp_peripherals.h"
|
||||
#include "periph_sdcard.h"
|
||||
#include "esp_sleep.h"
|
||||
#include "driver/rtc_io.h"
|
||||
}
|
||||
|
||||
#include "board_sweekar.h"
|
||||
#include "config.h"
|
||||
#include "board.h" // 添加board.h以获取audio_board_sdcard_init函数声明
|
||||
#include "drv8428.h"
|
||||
#include "aw8646.h"
|
||||
|
||||
#define TAG "board_sweekar"
|
||||
|
||||
BoardSweekar::BoardSweekar()
|
||||
: base_board_hal_uart_(BASE_BOARD_CTL_UART_PORT)
|
||||
{
|
||||
#ifdef CONFIG_STEPPER_DRIVER_AW8646
|
||||
stepper_driver_ = new Aw8646Driver(io_expansion_);
|
||||
#else
|
||||
stepper_driver_ = new Drv8428Driver(io_expansion_);
|
||||
#endif
|
||||
}
|
||||
|
||||
BoardSweekar::~BoardSweekar()
|
||||
{
|
||||
if (stepper_driver_) {
|
||||
delete stepper_driver_;
|
||||
stepper_driver_ = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*========================== 步进电机相关驱动 ==========================*/
|
||||
|
||||
/**
|
||||
* @brief 步进电机初始化函数
|
||||
* 配置步进电机所需的GPIO引脚模式,通过IO扩展板设置步进驱动芯片的工作模式
|
||||
* 在 stepper_motor.cc 中完成 GPTimer + GPIO 翻转 STEP 脉冲的初始化
|
||||
*/
|
||||
void BoardSweekar::StepperMotorInit(void)
|
||||
{
|
||||
esp_err_t err = ESP_OK;
|
||||
|
||||
// 1) STEP 引脚改为普通 GPIO(不再用 LEDC)
|
||||
gpio_config_t io_cfg;
|
||||
io_cfg.pin_bit_mask = 1ULL << STEPPER_STEP_IO;
|
||||
io_cfg.mode = GPIO_MODE_OUTPUT;
|
||||
io_cfg.pull_up_en = GPIO_PULLUP_DISABLE;
|
||||
io_cfg.pull_down_en = GPIO_PULLDOWN_DISABLE;
|
||||
io_cfg.intr_type = GPIO_INTR_DISABLE;
|
||||
err = gpio_config(&io_cfg);
|
||||
if (err != ESP_OK)
|
||||
{
|
||||
ESP_LOGE(TAG_BOARD, "步进电机 STEP GPIO 配置失败, 错误码: 0x%x", err);
|
||||
}
|
||||
|
||||
// 初始电平拉低,保证上电不乱跳
|
||||
gpio_set_level(STEPPER_STEP_IO, 0);
|
||||
|
||||
// 2) 检查 I2C 总线是否已初始化
|
||||
if (bus_handle_ == nullptr)
|
||||
{
|
||||
ESP_LOGE(TAG_BOARD, "I2C总线未初始化,请先调用I2CMasterInit()");
|
||||
return;
|
||||
}
|
||||
|
||||
// 3) 初始化驱动对象并初始化
|
||||
if (stepper_driver_) {
|
||||
err = stepper_driver_->Init();
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG_BOARD, "步进电机驱动初始化失败, 错误码: 0x%x", err);
|
||||
}
|
||||
} else {
|
||||
ESP_LOGE(TAG_BOARD, "步进电机驱动创建失败");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief LCD IO引脚初始化函数(消除与步进电机的耦合)
|
||||
*
|
||||
* 配置LCD所需的IO扩展板寄存器,确保LCD复位引脚正常工作
|
||||
* 此函数独立于步进电机初始化,专门处理LCD相关的IO配置
|
||||
*/
|
||||
void BoardSweekar::LcdIoInit(void)
|
||||
{
|
||||
esp_err_t err = ESP_OK;
|
||||
|
||||
// 1) 检查I2C总线是否已初始化
|
||||
if (bus_handle_ == nullptr)
|
||||
{
|
||||
ESP_LOGE(TAG_BOARD, "I2C总线未初始化,请先调用I2CMasterInit()");
|
||||
return;
|
||||
}
|
||||
|
||||
// 2) 执行硬件复位,确保IO扩展板处于已知状态
|
||||
err = io_expansion_.ResetIoExpand();
|
||||
if (err != ESP_OK)
|
||||
{
|
||||
ESP_LOGE(TAG_BOARD, "IO扩展板硬件复位失败, 错误码: 0x%x", err);
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
ESP_LOGI(TAG_BOARD, "IO扩展板硬件复位成功");
|
||||
}
|
||||
|
||||
// 3) 配置IO扩展板模式(端口方向等)
|
||||
err = io_expansion_.IoexpandSetMode();
|
||||
if (err != ESP_OK)
|
||||
{
|
||||
ESP_LOGE(TAG_BOARD, "IO扩展板模式配置失败, 错误码: 0x%x", err);
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
ESP_LOGI(TAG_BOARD, "IO扩展板模式配置成功");
|
||||
}
|
||||
|
||||
// 4) 初始化LCD复位引脚:设置为高电平
|
||||
err = io_expansion_.SetLcdResetMode(LCD_RST_HIGH, LCD_RST_PORT, LCD_RST_PIN);
|
||||
if (err != ESP_OK)
|
||||
{
|
||||
ESP_LOGE(TAG_BOARD, "LCD复位引脚高电平设置失败, 错误码: 0x%x", err);
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
ESP_LOGI(TAG_BOARD, "LCD复位引脚高电平设置成功");
|
||||
}
|
||||
|
||||
io_expansion_.SetLedEnMode(true);
|
||||
}
|
||||
|
||||
/*========================== 毫米波雷达相关驱动 ==========================*/
|
||||
|
||||
/**
|
||||
* @brief 毫米波雷达串口初始化函数
|
||||
*
|
||||
* 配置毫米波雷达所使用的串口参数(波特率、数据位、校验位、停止位等),设置串口引脚,
|
||||
* 并安装串口驱动。采用较大的RX/TX FIFO深度以处理突发数据,禁用驱动自带事件队列以避免
|
||||
* 与自定义中断冲突。
|
||||
*/
|
||||
void BoardSweekar::MillimeterWaveRadarUartInit(void)
|
||||
{
|
||||
uart_config_t uart_config = {
|
||||
.baud_rate = RADAR_BAUD_RATE,
|
||||
.data_bits = UART_DATA_8_BITS,
|
||||
.parity = UART_PARITY_DISABLE,
|
||||
.stop_bits = UART_STOP_BITS_1,
|
||||
.flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
|
||||
.rx_flow_ctrl_thresh = 122,
|
||||
.source_clk = UART_SCLK_DEFAULT,
|
||||
.flags = {
|
||||
.allow_pd = 0,
|
||||
.backup_before_sleep = 0,
|
||||
},
|
||||
};
|
||||
|
||||
// 1. 设置串口参数
|
||||
ESP_ERROR_CHECK(uart_param_config(RADAR_UART_NUM, &uart_config));
|
||||
|
||||
// 2. 设置 UART 引脚
|
||||
ESP_ERROR_CHECK(uart_set_pin(RADAR_UART_NUM, UART_TX_PIN, UART_RX_PIN,
|
||||
UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE));
|
||||
|
||||
// 3. 安装 UART 驱动(禁用驱动自带事件队列,避免与自定义中断冲突)
|
||||
// 增加 RX/TX FIFO 深度以处理突发数据
|
||||
ESP_ERROR_CHECK(uart_driver_install(RADAR_UART_NUM, RADAR_BUF_SIZE * 4, RADAR_BUF_SIZE * 4,
|
||||
0, NULL, 0));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 毫米波雷达中断引脚初始化函数
|
||||
*
|
||||
* 配置毫米波雷达中断引脚为输入模式,禁用上拉电阻,使能下拉电阻,初始禁用中断功能
|
||||
* (如需使用中断需单独进行配置)。
|
||||
*/
|
||||
void BoardSweekar::MillimeterWaveRadarGpioInit(void)
|
||||
{
|
||||
// GPIO配置结构体
|
||||
gpio_config_t io_conf = {
|
||||
.pin_bit_mask = (1ULL << MILLIMETER_WAVE_RADAR_PIN), // 选择GPIO引脚
|
||||
.mode = GPIO_MODE_INPUT, // 设置为输入模式
|
||||
.pull_up_en = GPIO_PULLUP_DISABLE,
|
||||
.pull_down_en = GPIO_PULLDOWN_ENABLE, // 使能下拉
|
||||
.intr_type = GPIO_INTR_DISABLE // 禁用中断(如需中断需单独配置)
|
||||
};
|
||||
|
||||
// 配置GPIO
|
||||
gpio_config(&io_conf);
|
||||
}
|
||||
|
||||
/*========================== I2C总线及挂载的从设备相关驱动 ==========================*/
|
||||
|
||||
/**
|
||||
* @brief I2C总线及从机设备初始化函数
|
||||
*
|
||||
* 首先配置并创建I2C主机总线,然后依次添加IO扩展板和线性马达作为I2C从机设备到总线上。
|
||||
* 若总线创建或设备添加失败,会输出错误信息并进行相应的资源清理(删除已创建的总线)。
|
||||
* 初始化成功后,会通过ESP_LOGI输出IO扩展板和线性马达的从机地址信息。
|
||||
*
|
||||
* @return esp_err_t 初始化结果,ESP_OK表示成功,其他错误码表示相应的失败原因
|
||||
*/
|
||||
esp_err_t BoardSweekar::I2CMasterInit(void)
|
||||
{
|
||||
static const char *I2C_INIT = "I2C_INIT";
|
||||
|
||||
// 初始化IO扩展板复位引脚
|
||||
gpio_config_t reset_io_conf = {
|
||||
.pin_bit_mask = (1ULL << IO_EXPAND_RSTN),
|
||||
.mode = GPIO_MODE_OUTPUT,
|
||||
.pull_up_en = GPIO_PULLUP_ENABLE, // 使能上拉
|
||||
.pull_down_en = GPIO_PULLDOWN_DISABLE,
|
||||
.intr_type = GPIO_INTR_DISABLE
|
||||
};
|
||||
gpio_config(&reset_io_conf);
|
||||
|
||||
// 执行复位时序:先拉低100ms,再拉高并等待100ms
|
||||
gpio_set_level(IO_EXPAND_RSTN, 0); // 拉低复位
|
||||
vTaskDelay(pdMS_TO_TICKS(100)); // 等待100ms
|
||||
gpio_set_level(IO_EXPAND_RSTN, 1); // 释放复位
|
||||
vTaskDelay(pdMS_TO_TICKS(100)); // 等待设备启动
|
||||
|
||||
ESP_LOGI(I2C_INIT, "IO扩展板复位完成");
|
||||
|
||||
// 创建统一的I2C总线(使用ESP-ADF的i2c_bus)
|
||||
i2c_config_t i2c_cfg = {
|
||||
.mode = I2C_MODE_MASTER,
|
||||
.sda_io_num = I2C0_MASTER_SDA_IO,
|
||||
.scl_io_num = I2C0_MASTER_SCL_IO,
|
||||
.sda_pullup_en = GPIO_PULLUP_ENABLE,
|
||||
.scl_pullup_en = GPIO_PULLUP_ENABLE,
|
||||
.master = {
|
||||
.clk_speed = 100000,
|
||||
},
|
||||
.clk_flags = 0,
|
||||
};
|
||||
|
||||
// 创建I2C总线(ESP-ADF的audio_board_init会复用这个总线)
|
||||
bus_handle_ = i2c_bus_create(I2C0_MASTER_PORT, &i2c_cfg);
|
||||
if (bus_handle_ == NULL) {
|
||||
ESP_LOGE(TAG, "Failed to create I2C bus");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
vTaskDelay(pdMS_TO_TICKS(100)); // 等待设备启动
|
||||
// ESP-ADF的i2c_bus不需要单独添加设备,直接通过总线句柄和设备地址进行通信
|
||||
|
||||
// 验证线性马达设备是否存在
|
||||
esp_err_t err = i2c_bus_probe_addr(bus_handle_, LINEAR_MOTOR_I2C_SLAVE_ADDR << 1);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(I2C_INIT, "线性马达设备未找到(地址:0x%02X),错误码: 0x%x", LINEAR_MOTOR_I2C_SLAVE_ADDR, err);
|
||||
// 不返回错误,继续初始化
|
||||
} else {
|
||||
ESP_LOGI(I2C_INIT, "线性马达设备检测成功(地址:0x%02X)", LINEAR_MOTOR_I2C_SLAVE_ADDR);
|
||||
}
|
||||
// 验证IO扩展板设备是否存在
|
||||
err = i2c_bus_probe_addr(bus_handle_, I2C_IO_EXPAND_SLAVE_ADDR << 1);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(I2C_INIT, "IO扩展板设备未找到(地址:0x%02X),错误码: 0x%x", I2C_IO_EXPAND_SLAVE_ADDR, err);
|
||||
// 不返回错误,继续初始化其他设备
|
||||
} else {
|
||||
ESP_LOGI(I2C_INIT, "IO扩展板设备检测成功(地址:0x%02X)", I2C_IO_EXPAND_SLAVE_ADDR);
|
||||
}
|
||||
// 验证陀螺仪设备是否存在
|
||||
err = i2c_bus_probe_addr(bus_handle_, GYROSCOPE_I2C_SLAVE_ADDR << 1);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(I2C_INIT, "陀螺仪设备未找到(地址:0x%02X),错误码: 0x%x", GYROSCOPE_I2C_SLAVE_ADDR, err);
|
||||
// 不返回错误,继续初始化
|
||||
} else {
|
||||
ESP_LOGI(I2C_INIT, "陀螺仪设备检测成功(地址:0x%02X)", GYROSCOPE_I2C_SLAVE_ADDR);
|
||||
}
|
||||
|
||||
// 为IO扩展板设置总线句柄和设备地址(使用7位地址)
|
||||
io_expansion_.bus_handle_ = bus_handle_;
|
||||
io_expansion_.device_addr_ = I2C_IO_EXPAND_SLAVE_ADDR << 1;
|
||||
|
||||
// 线性马达的初始化已移至 InitializeAllHardware 中统一调用 Init 方法
|
||||
// linear_motor_ 的参数传递将在那里完成,不再此处直接赋值,提高内聚性
|
||||
|
||||
ESP_LOGI(I2C_INIT, "I2C总线初始化完成");
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
/*========================== VBAT to VBAT_5V相关驱动 ==========================*/
|
||||
|
||||
/**
|
||||
* @brief 开启VBAT to VBAT_5V
|
||||
*
|
||||
* 创建开启升压的电源管理单元
|
||||
*
|
||||
*/
|
||||
void BoardSweekar::VbatToVbat5vInit(void)
|
||||
{
|
||||
if (VBAT_5V_PIN == GPIO_NUM_NC) {
|
||||
return;
|
||||
}
|
||||
// 配置VBAT_5V引脚为输出模式
|
||||
gpio_config_t io_conf = {
|
||||
.pin_bit_mask = (VBAT_5V_PIN != GPIO_NUM_NC) ? (1ULL << VBAT_5V_PIN) : 0,
|
||||
.mode = GPIO_MODE_OUTPUT,
|
||||
.pull_up_en = GPIO_PULLUP_DISABLE,
|
||||
.pull_down_en = GPIO_PULLDOWN_DISABLE,
|
||||
.intr_type = GPIO_INTR_DISABLE
|
||||
};
|
||||
gpio_config(&io_conf);
|
||||
// 使能VBAT_5V
|
||||
gpio_set_level(VBAT_5V_PIN, 1);
|
||||
}
|
||||
|
||||
/*========================== 底座控制串口相关驱动 ==========================*/
|
||||
|
||||
/**
|
||||
* @brief 底座控制命令串口初始化函数
|
||||
*/
|
||||
void BoardSweekar::BaseBoardControlUartInit(void)
|
||||
{
|
||||
uart_config_t uart_config = {
|
||||
.baud_rate = BASE_BOARD_CTL_UART_BAUDRATE,
|
||||
.data_bits = UART_DATA_8_BITS,
|
||||
.parity = UART_PARITY_DISABLE,
|
||||
.stop_bits = UART_STOP_BITS_1,
|
||||
.flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
|
||||
.rx_flow_ctrl_thresh = 122,
|
||||
.source_clk = UART_SCLK_DEFAULT,
|
||||
.flags = {
|
||||
.allow_pd = 0,
|
||||
.backup_before_sleep = 0,
|
||||
},
|
||||
};
|
||||
|
||||
// 1. 设置串口参数
|
||||
ESP_ERROR_CHECK(uart_param_config(BASE_BOARD_CTL_UART_PORT, &uart_config));
|
||||
|
||||
// 2. 设置 UART 引脚
|
||||
ESP_ERROR_CHECK(uart_set_pin(BASE_BOARD_CTL_UART_PORT, BASE_BOARD_CTL_UART_TX_PIN, BASE_BOARD_CTL_UART_RX_PIN,
|
||||
UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE));
|
||||
|
||||
// 3. 安装 UART 驱动
|
||||
ESP_ERROR_CHECK(uart_driver_install(BASE_BOARD_CTL_UART_PORT,
|
||||
BASE_BOARD_CTL_UART_BUF_SIZE,
|
||||
BASE_BOARD_CTL_UART_BUF_SIZE,
|
||||
0, NULL, 0));
|
||||
|
||||
base_board_control_.Init(&base_board_hal_uart_);
|
||||
}
|
||||
|
||||
/*========================== SD卡相关驱动 ==========================*/
|
||||
|
||||
/**
|
||||
* @brief SD卡初始化函数
|
||||
*
|
||||
* 初始化SD卡外设,使用1线模式进行通信。该函数负责初始化外设管理器
|
||||
* 并配置SD卡,为后续的文件系统操作做准备。
|
||||
*
|
||||
* @return esp_err_t 初始化结果,ESP_OK表示成功,其他错误码表示失败原因
|
||||
*/
|
||||
esp_err_t BoardSweekar::InitializeSdcard(void)
|
||||
{
|
||||
static const char *SDCARD_TAG = "SDCARD_INIT";
|
||||
esp_err_t ret;
|
||||
|
||||
ESP_LOGI(SDCARD_TAG, "Initializing SD card");
|
||||
|
||||
if (is_sdcard_initialized_) {
|
||||
ESP_LOGW(SDCARD_TAG, "SD card already initialized");
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
// 初始化外设管理
|
||||
esp_periph_config_t periph_cfg = DEFAULT_ESP_PERIPH_SET_CONFIG();
|
||||
periph_cfg.extern_stack = true; // 将任务栈分配到 PSRAM 以节省 Internal SRAM
|
||||
periph_set_ = esp_periph_set_init(&periph_cfg);
|
||||
if (!periph_set_) {
|
||||
ESP_LOGE(SDCARD_TAG, "Failed to initialize peripheral set");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
// 初始化SD卡外设
|
||||
ret = audio_board_sdcard_init(periph_set_, SD_MODE_1_LINE);
|
||||
if (ret != ESP_OK) {
|
||||
ESP_LOGE(SDCARD_TAG, "Failed to initialize SD card: %s", esp_err_to_name(ret));
|
||||
return ret;
|
||||
}
|
||||
|
||||
is_sdcard_initialized_ = true;
|
||||
ESP_LOGI(SDCARD_TAG, "SD card initialized successfully");
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 统一的硬件初始化接口实现
|
||||
*
|
||||
* 按照依赖关系顺序初始化所有硬件资源:
|
||||
* 1. I2C总线(最基础,其他设备可能依赖)
|
||||
* 2. IO扩展板(可能影响其他设备)
|
||||
* 3. SD卡(文件系统,供显示和音频使用)
|
||||
* 4. 其他外设
|
||||
*
|
||||
* @return esp_err_t 初始化结果,ESP_OK表示全部成功
|
||||
*/
|
||||
esp_err_t BoardSweekar::InitializeAllHardware(void)
|
||||
{
|
||||
static const char *HW_INIT_TAG = "HW_INIT";
|
||||
esp_err_t ret;
|
||||
|
||||
ESP_LOGI(HW_INIT_TAG, "Starting unified hardware initialization...");
|
||||
|
||||
// 1. 初始化I2C总线(最基础)
|
||||
ret = I2CMasterInit();
|
||||
if (ret != ESP_OK) {
|
||||
ESP_LOGE(HW_INIT_TAG, "Failed to initialize I2C master: %s", esp_err_to_name(ret));
|
||||
return ret;
|
||||
}
|
||||
ESP_LOGI(HW_INIT_TAG, "I2C master initialized");
|
||||
|
||||
// 2. 创建I2C读任务(IO扩展板需要)
|
||||
io_expansion_.CreateI2cReadTask();
|
||||
ESP_LOGI(HW_INIT_TAG, "I2C read task created");
|
||||
|
||||
// 3. 初始化SD卡(文件系统,供显示和音频使用)
|
||||
ret = InitializeSdcard();
|
||||
if (ret != ESP_OK) {
|
||||
ESP_LOGE(HW_INIT_TAG, "Failed to initialize SD card: %s", esp_err_to_name(ret));
|
||||
// SD卡失败不是致命错误,继续初始化其他硬件
|
||||
ESP_LOGW(HW_INIT_TAG, "SD card initialization failed, but continuing with other hardware");
|
||||
} else {
|
||||
ESP_LOGI(HW_INIT_TAG, "SD card initialized");
|
||||
}
|
||||
|
||||
// 4. 初始化LCD IO引脚
|
||||
LcdIoInit();
|
||||
ESP_LOGI(HW_INIT_TAG, "LCD IO pins initialized");
|
||||
|
||||
// 5. 初始化触摸传感器
|
||||
touch_sensor_.SetI2cHandle(bus_handle_);
|
||||
touch_sensor_.Begin();
|
||||
ESP_LOGI(HW_INIT_TAG, "Touch sensor initialized");
|
||||
|
||||
// 6. 初始化其他必要外设
|
||||
// BaseBoardControlUartInit(); // 底座控制串口(demo5需要)
|
||||
// ESP_LOGI(HW_INIT_TAG, "Base board control UART initialized");
|
||||
|
||||
// 初始化底座控制
|
||||
// base_board_control_.Init();
|
||||
// ESP_LOGI(HW_INIT_TAG, "Base board control initialized");
|
||||
|
||||
// 可选外设(根据具体应用需求)
|
||||
// MillimeterWaveRadarUartInit();
|
||||
// MillimeterWaveRadarGpioInit();
|
||||
StepperMotorInit();
|
||||
|
||||
|
||||
|
||||
ESP_LOGI(HW_INIT_TAG, "Unified hardware initialization completed successfully");
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 进入低功耗模式
|
||||
*
|
||||
* 根据指定的功耗模式,执行相应的功耗优化策略:
|
||||
* - IDLE模式:关闭非必要外设,保持快速响应
|
||||
* - LIGHT_SLEEP模式:进入轻度睡眠,CPU暂停,外设断电
|
||||
* - DEEP_SLEEP模式:深度睡眠,仅RTC运行,功耗最低
|
||||
*/
|
||||
esp_err_t BoardSweekar::EnterLowPowerMode(power_mode_t mode) {
|
||||
static const char *POWER_TAG = "POWER_MGMT";
|
||||
esp_err_t ret = ESP_OK;
|
||||
|
||||
ESP_LOGI(POWER_TAG, "Entering power mode: %d", mode);
|
||||
|
||||
if (mode == current_power_mode_) {
|
||||
ESP_LOGW(POWER_TAG, "Already in power mode %d", mode);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
// 保存当前模式,以便恢复
|
||||
power_mode_t previous_mode = current_power_mode_;
|
||||
|
||||
switch (mode) {
|
||||
case POWER_MODE_NORMAL:
|
||||
// 正常模式,不需要特殊处理
|
||||
break;
|
||||
|
||||
case POWER_MODE_IDLE:
|
||||
// 空闲模式:关闭非必要外设
|
||||
ESP_LOGI(POWER_TAG, "Idle mode: disabling non-essential peripherals");
|
||||
|
||||
// 关闭SD卡(如果正在使用,需要先卸载)
|
||||
if (is_sdcard_initialized_) {
|
||||
// 注意:这里只是示例,实际应用中需要确保没有文件操作
|
||||
ESP_LOGW(POWER_TAG, "SD card still active in idle mode");
|
||||
}
|
||||
|
||||
// 关闭显示背光
|
||||
// 关闭非必要GPIO的上拉/下拉
|
||||
// 降低I2C时钟频率
|
||||
break;
|
||||
|
||||
case POWER_MODE_LIGHT_SLEEP:
|
||||
// 轻度睡眠
|
||||
ESP_LOGI(POWER_TAG, "Light sleep mode: preparing for sleep");
|
||||
|
||||
// 设置唤醒源(需要根据具体需求配置)
|
||||
// esp_sleep_enable_timer_wakeup(1000000); // 1秒后唤醒
|
||||
// esp_sleep_enable_ext0_wakeup(GPIO_NUM_XX, 0); // 外部中断唤醒
|
||||
|
||||
// 进入轻度睡眠
|
||||
// ret = esp_light_sleep_start();
|
||||
if (ret != ESP_OK) {
|
||||
ESP_LOGE(POWER_TAG, "Failed to enter light sleep: %s", esp_err_to_name(ret));
|
||||
current_power_mode_ = previous_mode;
|
||||
return ret;
|
||||
}
|
||||
break;
|
||||
|
||||
case POWER_MODE_DEEP_SLEEP:
|
||||
// 深度睡眠
|
||||
ESP_LOGI(POWER_TAG, "Deep sleep mode: system will restart after wake-up");
|
||||
|
||||
// 保存必要的RTC数据
|
||||
// rtc_gpio_isolate(GPIO_NUM_XX); // 隔离GPIO
|
||||
|
||||
// 设置深度睡眠唤醒源
|
||||
// esp_sleep_enable_timer_wakeup(60000000); // 60秒后唤醒
|
||||
|
||||
// 进入深度睡眠
|
||||
// esp_deep_sleep_start();
|
||||
// 注意:深度睡眠后系统会重启,不会返回
|
||||
break;
|
||||
|
||||
default:
|
||||
ESP_LOGE(POWER_TAG, "Invalid power mode: %d", mode);
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
current_power_mode_ = mode;
|
||||
ESP_LOGI(POWER_TAG, "Successfully entered power mode: %d", mode);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 退出低功耗模式
|
||||
*
|
||||
* 从低功耗模式恢复到正常运行模式,重新初始化必要的硬件资源。
|
||||
*/
|
||||
esp_err_t BoardSweekar::ExitLowPowerMode(void) {
|
||||
static const char *POWER_TAG = "POWER_MGMT";
|
||||
|
||||
ESP_LOGI(POWER_TAG, "Exiting low power mode");
|
||||
|
||||
if (current_power_mode_ == POWER_MODE_NORMAL) {
|
||||
ESP_LOGW(POWER_TAG, "Already in normal mode");
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
// 根据之前的功耗模式执行相应的恢复操作
|
||||
switch (current_power_mode_) {
|
||||
case POWER_MODE_IDLE:
|
||||
// 恢复空闲模式
|
||||
ESP_LOGI(POWER_TAG, "Restoring from idle mode");
|
||||
|
||||
// 重新初始化必要的外设
|
||||
// 恢复I2C时钟频率
|
||||
// 重新开启显示背光
|
||||
break;
|
||||
|
||||
case POWER_MODE_LIGHT_SLEEP:
|
||||
// 轻度睡眠唤醒后会自动继续执行
|
||||
ESP_LOGI(POWER_TAG, "Woken up from light sleep");
|
||||
|
||||
// 重新配置时钟(如果需要)
|
||||
// 重新初始化外设
|
||||
break;
|
||||
|
||||
case POWER_MODE_DEEP_SLEEP:
|
||||
// 深度睡眠后系统会重启,不会执行到这里
|
||||
ESP_LOGW(POWER_TAG, "Deep sleep recovery should not reach here");
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// 恢复到正常模式
|
||||
current_power_mode_ = POWER_MODE_NORMAL;
|
||||
ESP_LOGI(POWER_TAG, "Successfully exited low power mode");
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 设置硬件模块电源状态
|
||||
*
|
||||
* 提供精细化的电源管理,可以单独控制各个硬件模块的电源状态。
|
||||
*/
|
||||
esp_err_t BoardSweekar::SetModulePower(hardware_module_t module, bool enable) {
|
||||
static const char *POWER_TAG = "POWER_MODULE";
|
||||
esp_err_t ret = ESP_OK;
|
||||
|
||||
ESP_LOGI(POWER_TAG, "%s module %d", enable ? "Enabling" : "Disabling", module);
|
||||
|
||||
// 更新电源状态位图
|
||||
if (enable) {
|
||||
power_state_flags_ |= (1 << module);
|
||||
} else {
|
||||
power_state_flags_ &= ~(1 << module);
|
||||
}
|
||||
|
||||
switch (module) {
|
||||
case HW_MODULE_I2C:
|
||||
if (!enable && bus_handle_) {
|
||||
// 注意:I2C总线通常不建议完全关闭,可能影响多个设备
|
||||
ESP_LOGW(POWER_TAG, "I2C bus power control not recommended");
|
||||
}
|
||||
break;
|
||||
|
||||
case HW_MODULE_SDCARD:
|
||||
if (enable && !is_sdcard_initialized_) {
|
||||
ret = InitializeSdcard();
|
||||
} else if (!enable && is_sdcard_initialized_) {
|
||||
// 卸载SD卡文件系统
|
||||
// 注意:需要确保没有打开的文件
|
||||
ESP_LOGW(POWER_TAG, "SD card power down requires file system cleanup");
|
||||
}
|
||||
break;
|
||||
|
||||
case HW_MODULE_LCD:
|
||||
// LCD背光控制
|
||||
// LCD电源引脚控制(如果有)
|
||||
break;
|
||||
|
||||
case HW_MODULE_AUDIO:
|
||||
// 音频编解码器电源控制
|
||||
// 需要与AudioPlayer协调
|
||||
break;
|
||||
|
||||
case HW_MODULE_MOTOR:
|
||||
// 步进电机驱动器电源控制
|
||||
// 电机睡眠模式
|
||||
break;
|
||||
|
||||
case HW_MODULE_GYROSCOPE:
|
||||
// 陀螺仪电源控制
|
||||
// 设置陀螺仪为低功耗模式
|
||||
break;
|
||||
|
||||
case HW_MODULE_TOUCH:
|
||||
// 触摸传感器电源控制
|
||||
// 设置触摸传感器为睡眠模式
|
||||
break;
|
||||
|
||||
case HW_MODULE_RADAR:
|
||||
// 毫米波雷达电源控制
|
||||
// 设置雷达为低功耗模式
|
||||
break;
|
||||
|
||||
case HW_MODULE_IO_EXPAND:
|
||||
// IO扩展板电源控制
|
||||
// 设置扩展板为低功耗模式
|
||||
break;
|
||||
|
||||
default:
|
||||
ESP_LOGE(POWER_TAG, "Unknown hardware module: %d", module);
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
if (ret == ESP_OK) {
|
||||
ESP_LOGI(POWER_TAG, "Module %d power %s successfully", module, enable ? "enabled" : "disabled");
|
||||
} else {
|
||||
ESP_LOGE(POWER_TAG, "Failed to %s module %d: %s", enable ? "enable" : "disable", module, esp_err_to_name(ret));
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,171 @@
|
||||
#ifndef __BOARD_H__
|
||||
#define __BOARD_H__
|
||||
#include "config.h"
|
||||
#include "io_expansion_board.h"
|
||||
#include "stepper_motor.h"
|
||||
#include "stepper_driver.h"
|
||||
#include "i2c_bus.h"
|
||||
#include "gyroscope.h"
|
||||
#include "touch_sensor.h"
|
||||
#include "base_board_control.h"
|
||||
#include "base_board_hal_uart.h"
|
||||
#include "esp_peripherals.h"
|
||||
#include "periph_sdcard.h"
|
||||
#include "esp_sleep.h"
|
||||
#include "driver/rtc_io.h"
|
||||
|
||||
/**
|
||||
* @brief 功耗模式枚举
|
||||
*/
|
||||
typedef enum {
|
||||
POWER_MODE_NORMAL, // 正常运行模式,所有硬件可用
|
||||
POWER_MODE_IDLE, // 空闲模式,关闭非必要外设
|
||||
POWER_MODE_LIGHT_SLEEP, // 轻度睡眠,快速唤醒
|
||||
POWER_MODE_DEEP_SLEEP, // 深度睡眠,仅RTC运行
|
||||
} power_mode_t;
|
||||
|
||||
/**
|
||||
* @brief 硬件模块枚举,用于精细化电源管理
|
||||
*/
|
||||
typedef enum {
|
||||
HW_MODULE_I2C, // I2C总线
|
||||
HW_MODULE_SDCARD, // SD卡
|
||||
HW_MODULE_LCD, // LCD显示
|
||||
HW_MODULE_AUDIO, // 音频编解码器
|
||||
HW_MODULE_MOTOR, // 步进电机
|
||||
HW_MODULE_GYROSCOPE, // 陀螺仪
|
||||
HW_MODULE_TOUCH, // 触摸传感器
|
||||
HW_MODULE_RADAR, // 毫米波雷达
|
||||
HW_MODULE_IO_EXPAND, // IO扩展板
|
||||
} hardware_module_t;
|
||||
|
||||
/**
|
||||
* @brief 硬件板级管理器
|
||||
*
|
||||
* 采用高内聚低耦合设计原则,统一管理所有硬件资源。
|
||||
* 提供统一的硬件初始化接口和资源访问,避免各模块重复初始化。
|
||||
*/
|
||||
class BoardSweekar
|
||||
{
|
||||
private:
|
||||
i2c_bus_handle_t bus_handle_ = nullptr; // 使用ESP-ADF的I2C总线句柄
|
||||
esp_periph_set_handle_t periph_set_ = nullptr; // 外设管理句柄
|
||||
bool is_sdcard_initialized_ = false; // SD卡初始化状态
|
||||
power_mode_t current_power_mode_ = POWER_MODE_NORMAL; // 当前功耗模式
|
||||
uint32_t power_state_flags_ = 0xFFFFFFFF; // 各模块电源状态位图(1为开启)
|
||||
|
||||
public:
|
||||
BoardSweekar();
|
||||
~BoardSweekar();
|
||||
|
||||
IOExpansionBoard io_expansion_; // IO扩展板对象
|
||||
Gyroscope gyroscope_; // 陀螺仪对象
|
||||
TouchSensor touch_sensor_; // 触摸传感器对象
|
||||
BaseBoardHalUart base_board_hal_uart_; // 底座控制HAL对象
|
||||
BaseBoardControl base_board_control_; // 底座控制对象
|
||||
StepperDriver* stepper_driver_ = nullptr; // 步进电机驱动对象
|
||||
|
||||
StepperDriver* GetStepperDriver() const { return stepper_driver_; }
|
||||
|
||||
// 初始化步进电机
|
||||
void StepperMotorInit(void);
|
||||
|
||||
// 初始化LCD IO引脚(消除与步进电机的耦合)
|
||||
void LcdIoInit(void);
|
||||
|
||||
// 初始化串口
|
||||
void MillimeterWaveRadarUartInit(void);
|
||||
|
||||
//初始化毫米波雷达的中断引脚
|
||||
void MillimeterWaveRadarGpioInit(void);
|
||||
|
||||
// 初始化I2C总线
|
||||
esp_err_t I2CMasterInit(void);
|
||||
|
||||
// 初始化VBAT toVBAT_5V引脚
|
||||
void VbatToVbat5vInit(void);
|
||||
|
||||
// 初始化底座控制串口
|
||||
void BaseBoardControlUartInit(void);
|
||||
|
||||
// 初始化SD卡(推荐使用统一的硬件初始化)
|
||||
esp_err_t InitializeSdcard(void);
|
||||
|
||||
// 获取SD卡初始化状态
|
||||
bool IsSdcardInitialized() const { return is_sdcard_initialized_; }
|
||||
|
||||
// 获取外设管理句柄(供需要访问SD卡的模块使用)
|
||||
esp_periph_set_handle_t GetPeriphSet() const { return periph_set_; }
|
||||
|
||||
// 获取I2C总线句柄
|
||||
i2c_bus_handle_t GetBusHandle() const { return bus_handle_; }
|
||||
|
||||
/**
|
||||
* @brief 统一的硬件初始化接口
|
||||
*
|
||||
* 按照依赖关系顺序初始化所有硬件资源,确保各模块可以安全使用。
|
||||
* 推荐在主程序启动时调用此函数,而不是分别调用各个初始化函数。
|
||||
*
|
||||
* @return esp_err_t 初始化结果,ESP_OK表示全部成功
|
||||
*/
|
||||
esp_err_t InitializeAllHardware(void);
|
||||
|
||||
/**
|
||||
* @brief 完整的统一硬件初始化接口(专为复杂应用优化)
|
||||
*
|
||||
* 包含所有必要外设的完整初始化,适用于demo5等复杂应用场景。
|
||||
* 这个函数会初始化:I2C总线、IO扩展板、SD卡、LCD IO、底座控制等。
|
||||
*
|
||||
* @return esp_err_t 初始化结果,ESP_OK表示全部成功
|
||||
*/
|
||||
esp_err_t InitializeAllHardwareComplete(void);
|
||||
|
||||
/**
|
||||
* @brief 针对特定应用的硬件初始化配置
|
||||
*
|
||||
* 为不同类型的应用提供专门的初始化配置,优化启动流程。
|
||||
*
|
||||
* @param app_type 应用类型(demo5、音频播放器、显示应用等)
|
||||
* @return esp_err_t 初始化结果,ESP_OK表示全部成功
|
||||
*/
|
||||
esp_err_t InitializeHardwareForApplication(int app_type);
|
||||
|
||||
/**
|
||||
* @brief 功耗管理接口 - 进入低功耗模式
|
||||
*
|
||||
* 根据指定的功耗模式,关闭非必要硬件、设置GPIO为低功耗状态、
|
||||
* 调整时钟频率等。支持多种功耗模式以适应不同应用场景。
|
||||
*
|
||||
* @param mode 功耗模式
|
||||
* @return esp_err_t 操作结果
|
||||
*/
|
||||
esp_err_t EnterLowPowerMode(power_mode_t mode);
|
||||
|
||||
/**
|
||||
* @brief 功耗管理接口 - 退出低功耗模式
|
||||
*
|
||||
* 从低功耗模式恢复,重新初始化必要的硬件资源。
|
||||
*
|
||||
* @return esp_err_t 操作结果
|
||||
*/
|
||||
esp_err_t ExitLowPowerMode(void);
|
||||
|
||||
/**
|
||||
* @brief 获取当前功耗模式
|
||||
*
|
||||
* @return power_mode_t 当前功耗模式
|
||||
*/
|
||||
power_mode_t GetPowerMode(void) const { return current_power_mode_; }
|
||||
|
||||
/**
|
||||
* @brief 设置硬件模块电源状态
|
||||
*
|
||||
* 单独控制某个硬件模块的电源状态,用于精细化的功耗管理。
|
||||
*
|
||||
* @param module 硬件模块
|
||||
* @param enable true为开启,false为关闭
|
||||
* @return esp_err_t 操作结果
|
||||
*/
|
||||
esp_err_t SetModulePower(hardware_module_t module, bool enable);
|
||||
};
|
||||
#endif
|
||||
@@ -0,0 +1,186 @@
|
||||
/**
|
||||
* @file board_sweekar_complete_init.cc
|
||||
* @brief 完整的统一硬件初始化实现
|
||||
*
|
||||
* 这个文件提供了完整的统一硬件初始化函数,包含所有必要的硬件初始化步骤。
|
||||
* 专为demo5等复杂应用场景设计。
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief 完整的统一硬件初始化接口(专为demo5优化)
|
||||
*
|
||||
* 按照依赖关系顺序初始化所有硬件资源:
|
||||
* 1. I2C总线(最基础,其他设备依赖)
|
||||
* 2. IO扩展板(控制其他外设)
|
||||
* 3. SD卡(文件系统,供显示和音频使用)
|
||||
* 4. LCD IO引脚(显示相关)
|
||||
* 5. 底座控制串口(通信)
|
||||
* 6. 底座控制模块(业务逻辑)
|
||||
* 7. 其他外设(根据应用需求)
|
||||
*
|
||||
* @return esp_err_t 初始化结果,ESP_OK表示全部成功
|
||||
*/
|
||||
esp_err_t BoardSweekar::InitializeAllHardwareComplete(void)
|
||||
{
|
||||
static const char *HW_INIT_TAG = "HW_INIT_COMPLETE";
|
||||
esp_err_t ret;
|
||||
|
||||
ESP_LOGI(HW_INIT_TAG, "Starting complete hardware initialization...");
|
||||
|
||||
// 1. 初始化I2C总线(最基础,其他设备依赖)
|
||||
ret = I2CMasterInit();
|
||||
if (ret != ESP_OK) {
|
||||
ESP_LOGE(HW_INIT_TAG, "Failed to initialize I2C master: %s", esp_err_to_name(ret));
|
||||
return ret;
|
||||
}
|
||||
ESP_LOGI(HW_INIT_TAG, "✓ I2C master initialized");
|
||||
|
||||
// 2. 创建I2C读任务(IO扩展板需要)
|
||||
io_expansion_.CreateI2cReadTask();
|
||||
ESP_LOGI(HW_INIT_TAG, "✓ I2C read task created");
|
||||
|
||||
// 3. 初始化SD卡(文件系统,供显示和音频使用)
|
||||
ret = InitializeSdcard();
|
||||
if (ret != ESP_OK) {
|
||||
ESP_LOGE(HW_INIT_TAG, "Failed to initialize SD card: %s", esp_err_to_name(ret));
|
||||
// SD卡失败不是致命错误,继续初始化其他硬件
|
||||
ESP_LOGW(HW_INIT_TAG, "⚠ SD card initialization failed, but continuing with other hardware");
|
||||
} else {
|
||||
ESP_LOGI(HW_INIT_TAG, "✓ SD card initialized");
|
||||
}
|
||||
|
||||
// 4. 初始化LCD IO引脚(显示相关)
|
||||
LcdIoInit();
|
||||
ESP_LOGI(HW_INIT_TAG, "✓ LCD IO pins initialized");
|
||||
|
||||
// 5. 初始化底座控制串口(demo5需要)
|
||||
BaseBoardControlUartInit();
|
||||
ESP_LOGI(HW_INIT_TAG, "✓ Base board control UART initialized");
|
||||
|
||||
// 6. 初始化底座控制模块
|
||||
base_board_control_.Init();
|
||||
ESP_LOGI(HW_INIT_TAG, "✓ Base board control initialized");
|
||||
|
||||
// 7. 设置IO扩展板的PA控制模式(demo5需要)
|
||||
io_expansion_.SetPaCtrlMode(true);
|
||||
ESP_LOGI(HW_INIT_TAG, "✓ IO expansion PA control mode set");
|
||||
|
||||
// 8. 可选外设(根据具体应用需求启用)
|
||||
// ESP_LOGI(HW_INIT_TAG, "Initializing optional peripherals...");
|
||||
//
|
||||
// // 毫米波雷达(如需要)
|
||||
// MillimeterWaveRadarUartInit();
|
||||
// MillimeterWaveRadarGpioInit();
|
||||
// ESP_LOGI(HW_INIT_TAG, "✓ Millimeter wave radar initialized");
|
||||
//
|
||||
// // VBAT升压(如需要)
|
||||
// VbatToVbat5vInit();
|
||||
// ESP_LOGI(HW_INIT_TAG, "✓ VBAT to 5V booster initialized");
|
||||
//
|
||||
// // 步进电机(如需要)
|
||||
// StepperMotorInit();
|
||||
// ESP_LOGI(HW_INIT_TAG, "✓ Stepper motor initialized");
|
||||
|
||||
ESP_LOGI(HW_INIT_TAG, "=== Complete hardware initialization finished successfully ===");
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 针对特定应用的硬件初始化配置
|
||||
*
|
||||
* 为不同类型的应用提供专门的初始化配置
|
||||
*/
|
||||
esp_err_t BoardSweekar::InitializeHardwareForApplication(application_type_t app_type) {
|
||||
static const char *APP_INIT_TAG = "APP_HW_INIT";
|
||||
|
||||
ESP_LOGI(APP_INIT_TAG, "Initializing hardware for application type: %d", app_type);
|
||||
|
||||
// 基础硬件初始化(所有应用都需要)
|
||||
esp_err_t ret = InitializeAllHardwareComplete();
|
||||
if (ret != ESP_OK) {
|
||||
ESP_LOGE(APP_INIT_TAG, "Basic hardware initialization failed");
|
||||
return ret;
|
||||
}
|
||||
|
||||
switch (app_type) {
|
||||
case APP_TYPE_DEMO5: // 宠物游戏demo
|
||||
ESP_LOGI(APP_INIT_TAG, "Configuring for Demo5 (Pet Game)...");
|
||||
|
||||
// Demo5需要的额外初始化
|
||||
// 触摸传感器、陀螺仪、RGB LED等会在应用层初始化
|
||||
|
||||
ESP_LOGI(APP_INIT_TAG, "✓ Demo5 hardware configuration complete");
|
||||
break;
|
||||
|
||||
case APP_TYPE_AUDIO_PLAYER: // 音频播放器
|
||||
ESP_LOGI(APP_INIT_TAG, "Configuring for Audio Player...");
|
||||
|
||||
// 音频应用需要确保音频编解码器正确初始化
|
||||
// 这部分通常在AudioPlayer类中处理
|
||||
|
||||
ESP_LOGI(APP_INIT_TAG, "✓ Audio player hardware configuration complete");
|
||||
break;
|
||||
|
||||
case APP_TYPE_DISPLAY_ONLY: // 纯显示应用
|
||||
ESP_LOGI(APP_INIT_TAG, "Configuring for Display Only...");
|
||||
|
||||
// 显示应用需要确保LCD相关硬件正确配置
|
||||
// 这部分通常在Display类中处理
|
||||
|
||||
ESP_LOGI(APP_INIT_TAG, "✓ Display-only hardware configuration complete");
|
||||
break;
|
||||
|
||||
case APP_TYPE_MINIMAL: // 最小化应用
|
||||
ESP_LOGI(APP_INIT_TAG, "Configuring for Minimal Application...");
|
||||
|
||||
// 最小化配置,只保留最基本的功能
|
||||
// 关闭非必要外设以节省功耗
|
||||
|
||||
ESP_LOGI(APP_INIT_TAG, "✓ Minimal hardware configuration complete");
|
||||
break;
|
||||
|
||||
default:
|
||||
ESP_LOGW(APP_INIT_TAG, "Unknown application type, using default configuration");
|
||||
break;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 硬件初始化状态报告
|
||||
*
|
||||
* 提供详细的硬件初始化状态报告,便于调试和问题排查
|
||||
*/
|
||||
void BoardSweekar::ReportHardwareStatus(void) {
|
||||
static const char *STATUS_TAG = "HW_STATUS";
|
||||
|
||||
ESP_LOGI(STATUS_TAG, "=== Hardware Initialization Status Report ===");
|
||||
|
||||
// I2C总线状态
|
||||
ESP_LOGI(STATUS_TAG, "I2C Bus: %s", (bus_handle_ != nullptr) ? "✓ Initialized" : "✗ Not initialized");
|
||||
|
||||
// SD卡状态
|
||||
ESP_LOGI(STATUS_TAG, "SD Card: %s", (is_sdcard_initialized_) ? "✓ Initialized" : "✗ Not initialized");
|
||||
if (is_sdcard_initialized_) {
|
||||
ESP_LOGI(STATUS_TAG, " Peripheral Set: %s", (periph_set_ != nullptr) ? "✓ Available" : "✗ Not available");
|
||||
}
|
||||
|
||||
// IO扩展板状态
|
||||
ESP_LOGI(STATUS_TAG, "IO Expansion Board: %s", (io_expansion_.bus_handle_ != nullptr) ? "✓ Configured" : "✗ Not configured");
|
||||
|
||||
// 底座控制状态
|
||||
ESP_LOGI(STATUS_TAG, "Base Board Control: %s", (base_board_control_.GetUartPort() != 0) ? "✓ Initialized" : "✗ Not initialized");
|
||||
|
||||
// 功耗管理状态
|
||||
ESP_LOGI(STATUS_TAG, "Power Management: %s", (current_power_mode_ == POWER_MODE_NORMAL) ? "✓ Normal mode" : "⚠ Low power mode");
|
||||
ESP_LOGI(STATUS_TAG, " Current Mode: %d", current_power_mode_);
|
||||
ESP_LOGI(STATUS_TAG, " Module Power States: 0x%08X", power_state_flags_);
|
||||
|
||||
// 内存状态
|
||||
ESP_LOGI(STATUS_TAG, "Memory Status:");
|
||||
ESP_LOGI(STATUS_TAG, " Internal RAM Free: %d bytes", heap_caps_get_free_size(MALLOC_CAP_INTERNAL));
|
||||
ESP_LOGI(STATUS_TAG, " PSRAM Free: %d bytes", heap_caps_get_free_size(MALLOC_CAP_SPIRAM));
|
||||
|
||||
ESP_LOGI(STATUS_TAG, "=== End of Hardware Status Report ===");
|
||||
}
|
||||
@@ -0,0 +1,132 @@
|
||||
/* 定义引脚分配 */
|
||||
#ifndef _BOARD_CONFIG_H_
|
||||
#define _BOARD_CONFIG_H_
|
||||
|
||||
/**
|
||||
* @file config.h
|
||||
* @brief 定义了引脚的分配。
|
||||
* @author zouyuhua
|
||||
* @date 2025年8月7日
|
||||
*
|
||||
*/
|
||||
|
||||
#include "driver/gpio.h"
|
||||
#include "driver/i2c_master.h"
|
||||
#include "driver/i2s.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_rom_sys.h" // 用于 esp_rom_delay_us
|
||||
#include "esp_timer.h"
|
||||
#include "esp_mac.h"
|
||||
#include "driver/ledc.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "esp_log.h"
|
||||
#include "driver/timer.h"
|
||||
#include "esp_intr_alloc.h"
|
||||
#include "soc/timer_group_struct.h" // 包含TIMERG0、TIMERG1的结构体定义
|
||||
#include "soc/timer_group_reg.h" // 包含定时器相关寄存器宏定义
|
||||
#include "driver/uart.h"
|
||||
#include "esp_err.h"
|
||||
#include "freertos/queue.h"
|
||||
#include "soc/uart_reg.h"
|
||||
#include "linear_motor.h"
|
||||
#include "gyroscope.h"
|
||||
|
||||
#define TAG_BOARD "SWEEKAR_ESP32"
|
||||
/*I2C总线引脚定义*/
|
||||
#define I2C0_MASTER_PORT I2C_NUM_0
|
||||
#define I2C0_MASTER_SDA_IO GPIO_NUM_2
|
||||
#define I2C0_MASTER_SCL_IO GPIO_NUM_3
|
||||
|
||||
/* 步进电机配置 */
|
||||
#define STEPPER_STEP_IO GPIO_NUM_42 // 步进电机脉冲输入引脚
|
||||
#define STEPPER_TIMER_RES_HZ 1000000 // 步进电机定时器分辨率 1 MHz(1 us 步进)
|
||||
|
||||
/* 定义屏幕驱动控制引脚 */
|
||||
#define ST7789_PIN_CLK GPIO_NUM_48 // SPI时钟引脚
|
||||
#define ST7789_PIN_DC GPIO_NUM_38 // 数据/命令选择引脚RSEL
|
||||
#define ST7789_PIN_MOSI GPIO_NUM_47 // SPI数据输出引脚
|
||||
#define ST7789_PIN_CS GPIO_NUM_46 // SPI片选引脚
|
||||
#define ST7789_PIN_BL GPIO_NUM_45 // 背光引脚
|
||||
#define ST7789_PIN_RST GPIO_NUM_NC // 复位引脚
|
||||
#define LCD_BL_ACTIVE_LEVEL 0 // 背光有效电平:1=高电平有效(NMOS),0=低电平有效(PMOS)
|
||||
|
||||
#define LCD_WIDTH 172 // 屏幕宽度(水平方向像素数)
|
||||
#define LCD_HEIGHT 320 // 屏幕高度(垂直方向像素数)
|
||||
|
||||
/* 毫米波雷达配置参数 */
|
||||
/* 定义毫米波雷达的中断引脚 */
|
||||
#define MILLIMETER_WAVE_RADAR_PIN GPIO_NUM_35
|
||||
// UART 配置参数
|
||||
#define RADAR_UART_NUM UART_NUM_1 // 使用 UART1
|
||||
#define UART_TX_PIN GPIO_NUM_40 // GPIO40 作为 TX(根据实际硬件连接调整)
|
||||
#define UART_RX_PIN GPIO_NUM_39 // GPIO39 作为 RX
|
||||
#define RADAR_BAUD_RATE 9600 // 雷达波特率
|
||||
#define RADAR_BUF_SIZE 100 // 雷达接收缓冲区大小
|
||||
|
||||
/* IO扩展硬件配置常量 */
|
||||
#define I2C_MASTER_FREQ_HZ 100000 // I2C通信频率(100kHz)(可更改至400000)
|
||||
#define I2C_IO_EXPAND_SLAVE_ADDR 0x58 // AW9523BTQR器件地址,v1_1_13的addr1和addr0是0
|
||||
#define GPIO_INPUT_PIN_SEL GPIO_NUM_10 // 中断检测引脚
|
||||
#define ESP_INTR_FLAG_DEFAULT 0 // 中断标志默认值
|
||||
#define IO_EXPAND_RSTN GPIO_NUM_14 // IO扩展板复位引脚
|
||||
|
||||
/* 定义线性马达的I2C从机配置常量 */
|
||||
#define LINEAR_MOTOR_I2C_SLAVE_ADDR 0x5A // 线性马达的I2C从机地址
|
||||
|
||||
/* 定义陀螺仪的I2C从机配置常量 */
|
||||
#define GYROSCOPE_I2C_SLAVE_ADDR 0x6A // 陀螺仪的I2C从机地址
|
||||
#define GYROSCOPE_INPUT_PIN_SEL GPIO_NUM_21 // 陀螺仪中断引脚
|
||||
|
||||
/* 原生触摸引脚配置 */
|
||||
// 触摸按键数量配置
|
||||
#define TOUCH_BUTTON_NUM 3
|
||||
// 触摸通道定义
|
||||
#define TOUCH_PAD_CHANNEL_1 TOUCH_PAD_NUM11 // GPIO11
|
||||
#define TOUCH_PAD_CHANNEL_2 TOUCH_PAD_NUM12 // GPIO12
|
||||
#define TOUCH_PAD_CHANNEL_3 TOUCH_PAD_NUM13 // GPIO13
|
||||
|
||||
/* ES8311音频编解码器配置 (ESP-ADF兼容) */
|
||||
#define AUDIO_INPUT_SAMPLE_RATE 24000
|
||||
#define AUDIO_OUTPUT_SAMPLE_RATE 24000
|
||||
#define AUDIO_INPUT_REFERENCE true
|
||||
|
||||
/* I2S GPIO定义 */
|
||||
#define AUDIO_I2S_GPIO_MCLK GPIO_NUM_15
|
||||
#define AUDIO_I2S_GPIO_WS GPIO_NUM_4
|
||||
#define AUDIO_I2S_GPIO_BCLK GPIO_NUM_5
|
||||
#define AUDIO_I2S_GPIO_DIN GPIO_NUM_6
|
||||
#define AUDIO_I2S_GPIO_DOUT GPIO_NUM_7
|
||||
|
||||
/* PA引脚定义 */
|
||||
#define AUDIO_CODEC_PA_PIN GPIO_NUM_NC
|
||||
|
||||
/* I2C配置 */
|
||||
#define AUDIO_CODEC_I2C_SDA_PIN GPIO_NUM_2
|
||||
#define AUDIO_CODEC_I2C_SCL_PIN GPIO_NUM_3
|
||||
#define AUDIO_CODEC_ES8311_ADDR 0x18
|
||||
#define AUDIO_CODEC_ES7210_ADDR 0x40
|
||||
|
||||
/* WS2812 RGB LED配置 */
|
||||
#define WS2812_PIN GPIO_NUM_41 // WS2812数据引脚
|
||||
#define WS2812_NUM_LEDS 2 // WS2812 LED数量
|
||||
|
||||
/* 创建VBAT to VBAT_5V */
|
||||
#define VBAT_5V_PIN GPIO_NUM_NC // VBAT_5V引脚
|
||||
|
||||
/* 定义按键的中断引脚 */
|
||||
#define BUTTON_PIN GPIO_NUM_0 // 按键中断引脚
|
||||
#define RIGHT_BUTTON_PIN GPIO_NUM_8 // 按键中断引脚
|
||||
|
||||
/* 底座控制命令串口配置 */
|
||||
#define BASE_BOARD_CTL_UART_PORT UART_NUM_0
|
||||
#define BASE_BOARD_CTL_UART_TX_PIN GPIO_NUM_43
|
||||
#define BASE_BOARD_CTL_UART_RX_PIN GPIO_NUM_44
|
||||
#define BASE_BOARD_CTL_UART_BAUDRATE 115200
|
||||
#define BASE_BOARD_CTL_UART_BUF_SIZE 256
|
||||
|
||||
/* 背光控制引脚配置 */
|
||||
#define BL_PIN GPIO_NUM_45
|
||||
|
||||
#endif // _BOARD_CONFIG_H_
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,421 @@
|
||||
#ifndef IO_EXPANSION_BOARD_H
|
||||
#define IO_EXPANSION_BOARD_H
|
||||
|
||||
#include <cstdint>
|
||||
#include <esp_log.h>
|
||||
#include <esp_check.h>
|
||||
#include <esp_timer.h>
|
||||
#include <driver/gpio.h>
|
||||
#include <functional>
|
||||
#include "i2c_bus.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/event_groups.h"
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
#include <freertos/FreeRTOS.h>
|
||||
#include <freertos/task.h>
|
||||
#include <freertos/queue.h>
|
||||
#include <freertos/semphr.h>
|
||||
#include "esp_err.h"
|
||||
#include "config.h"
|
||||
#include "portmacro.h"
|
||||
|
||||
// 前向声明,避免循环引用
|
||||
class MillimeterWaveRadar;
|
||||
class PhotoInterrupter;
|
||||
class AdcBatteryMonitor;
|
||||
|
||||
// 回调函数类型定义
|
||||
typedef std::function<void()> RadarCallback;
|
||||
typedef std::function<void()> PhotoInterrupterStartCallback;
|
||||
typedef std::function<void()> PhotoInterrupterEndCallback;
|
||||
typedef std::function<void()> BatteryChargingCallback;
|
||||
typedef std::function<void()> BatteryFullCallback;
|
||||
typedef std::function<void()> BatteryNotChargingCallback;
|
||||
|
||||
/* 寄存器地址 */
|
||||
#define INPUT_PORT0 0x00 // 输入端口0寄存器
|
||||
#define INPUT_PORT1 0x01 // 输入端口1寄存器 0为低电平(仅支持读取)
|
||||
#define OUTPUT_PORT0 0x02 // 输出端口0寄存器
|
||||
#define OUTPUT_PORT1 0x03 // 输出端口1寄存器 0为低电平
|
||||
#define CONFIG_PORT0 0x04 // 配置端口0寄存器
|
||||
#define CONFIG_PORT1 0x05 // 配置端口1寄存器 0为输出模式
|
||||
#define INT_PORT0 0x06 // 中断端口0寄存器
|
||||
#define INT_PORT1 0x07 // 中断端口1寄存器 0为使能中断(根据手册默认是使能的)
|
||||
#define CTL 0x11 // 全局控制寄存器
|
||||
#define ID 0x23 // 芯片ID寄存器(0x23)
|
||||
|
||||
/***********************************IO扩展板电机引脚配置参数*************************************/
|
||||
/* 设置步进电机方向 */
|
||||
#define STEPPER_MOTOR_LEFT false //步进电机的方向为左转
|
||||
#define STEPPER_MOTOR_RIGHT true //步进电机的方向为右转
|
||||
#define STEPPER_MOTOR_DIR_PORT OUTPUT_PORT0 //步进电机方向引脚挂载在IO扩展板的输出端口OUTPUT_PORT0
|
||||
#define STEPPER_MOTOR_DIR_PIN 4 //步进电机方向引脚对应的IO扩展板引脚P0_4
|
||||
#define STEPPER_MOTOR_DIR_CONFIG CONFIG_PORT0 //步进电机方向引脚配置在P0_4
|
||||
|
||||
/* 设置步进电机细分模式 */
|
||||
#define STEPPER_MOTOR_M0_PIN 5 //步进电机细分模式选择引脚对应IO扩展板引脚P1_5
|
||||
#define STEPPER_MOTOR_M0_MADE_PORT OUTPUT_PORT1 //步进电机模式选择引脚挂载在IO扩展板的输出端口OUTPUT_PORT1
|
||||
#define STEPPER_MOTOR_M0_CONFIG CONFIG_PORT1 //步进电机细分模式选择引脚配置在P1_5
|
||||
|
||||
#define STEPPER_MOTOR_M1_PIN 4 //步进电机细分模式选择引脚对应IO扩展板引脚P1_4
|
||||
#define STEPPER_MOTOR_M1_MADE_PORT OUTPUT_PORT1 //步进电机模式选择引脚挂载在IO扩展板的输出端口OUTPUT_PORT1
|
||||
#define STEPPER_MOTOR_M1_CONFIG CONFIG_PORT1 //步进电机细分模式选择引脚配置在P1_4
|
||||
|
||||
/* 设置步进电机睡眠引脚 */
|
||||
#define STEPPER_MOTOR_SLEEP false //步进电机进入睡眠模式
|
||||
#define STEPPER_MOTOR_WORK true //步进电机进入工作模式
|
||||
#define STEPPER_MOTOR_SLEEP_PIN 6 //步进电机睡眠引脚对应IO扩展板引脚P1_6
|
||||
#define STEPPER_MOTOR_SLEEP_CONFIG CONFIG_PORT1 //步进电机睡眠引脚配置在P1_6
|
||||
#define STEPPER_MOTOR_SLEEP_PORT OUTPUT_PORT1 //步进电机睡眠引脚挂载在IO扩展板的输出端口OUTPUT_PORT1
|
||||
|
||||
/* 设置电机的使能引脚 */
|
||||
#define STEPPER_MOTOR_ENABLE_PIN 7 //电机使能引脚对应IO扩展板引脚P0_7
|
||||
#define STEPPER_MOTOR_ENABLE_PORT OUTPUT_PORT0 //电机使能引脚挂载在IO扩展板的输出端口OUTPUT_PORT0
|
||||
#define STEPPER_MOTOR_ENABLE_CONFIG CONFIG_PORT0 //电机使能引脚配置在P0_7
|
||||
#define STEPPER_MOTOR_ENABLE_ENABLE true //电机使能引脚状态为高电平
|
||||
#define STEPPER_MOTOR_ENABLE_DISABLE false //电机使能引脚状态为低电平
|
||||
|
||||
/* 设置毫米波雷达对应IO扩展板的中断引脚 */
|
||||
#define RADAR_INTERRUPT_PIN 7 //毫米波雷达中断引脚对应IO扩展板引脚P1_7
|
||||
#define RADAR_INTERRUPT_CONFIG CONFIG_PORT1 //毫米波雷达中断引脚挂载在IO扩展板的输入端口
|
||||
#define RADAR_INTERRUPT_INPUT INPUT_PORT1 //毫米波雷达中断引脚输入状态检测在INPUT_PORT1
|
||||
#define RADAR_INTERRUPT_ENABLE true //毫米波雷达中断引脚状态为输入状态
|
||||
#define RADAR_INTERRUPT_DISABLE false //毫米波雷达中断引脚状态为输出状态
|
||||
/* 任务配置常量 */
|
||||
#define WRITE_BUF_SIZE 2 // I2C单次写入字节数
|
||||
#define READ_BUF_SIZE 2 // I2C单次读取字节数
|
||||
#define I2C_TASK_PRIORITY 2 // 任务优先级(中等)
|
||||
#define I2C_TASK_STACK 4096 // 任务栈大小(4KB)
|
||||
|
||||
// 光学传感器引脚定义
|
||||
#define START_PHOTO_INTERRUPTER_PIN 2 // 光学传感器引脚(P0_2)
|
||||
#define START_PHOTO_INTERRUPTER_CONFIG CONFIG_PORT0 // 光学传感器引脚挂载在IO扩展板的输入端口
|
||||
#define START_PHOTO_INTERRUPTER_INPUT INPUT_PORT0 // 光学传感器引脚输入状态检测在INPUT_PORT0
|
||||
#define START_PHOTO_INTERRUPTER_HIGH true // 光学传感器引脚状态为高电平
|
||||
#define START_PHOTO_INTERRUPTER_LOW false // 光学传感器引脚状态为低电平
|
||||
|
||||
#define END_PHOTO_INTERRUPTER_PIN 3 // 光学传感器引脚(P0_3)
|
||||
#define END_PHOTO_INTERRUPTER_PORT_CONFIG CONFIG_PORT0 // 光学传感器引脚挂载在IO扩展板的输入端口
|
||||
#define END_PHOTO_INTERRUPTER_INPUT INPUT_PORT0 // 光学传感器引脚输入状态检测在INPUT_PORT0
|
||||
#define END_PHOTO_INTERRUPTER_HIGH true // 光学传感器引脚状态为高电平
|
||||
#define END_PHOTO_INTERRUPTER_LOW false // 光学传感器引脚状态为低电平
|
||||
|
||||
/***********************************IO扩展板LCD引脚配置参数*************************************/
|
||||
// /* 设置LCD的BL引脚 */
|
||||
// #define LCD_BL_PIN 6 //LCD背光引脚对应IO扩展板引脚P0_6
|
||||
// #define LCD_BL_PORT OUTPUT_PORT0 //LCD背光引脚挂载在IO扩展板的输出端口OUTPUT_PORT0
|
||||
// #define LCD_BL_CONFIG CONFIG_PORT0 //LCD背光引脚配置在P0_6
|
||||
// #define LCD_BL_HIGH true //LCD背光引脚状态为高电平
|
||||
// #define LCD_BL_LOW false //LCD背光引脚状态为低电平
|
||||
|
||||
/* 设置LCD的RST引脚 */
|
||||
#define LCD_RST_PIN 1 //LCD复位引脚对应IO扩展板引脚P1_1
|
||||
#define LCD_RST_CONFIG CONFIG_PORT1 //LCD复位引脚配置在P1_1
|
||||
#define LCD_RST_PORT OUTPUT_PORT1 //LCD复位引脚挂载在IO扩展板的输出端口OUTPUT_PORT1
|
||||
#define LCD_RST_HIGH true //LCD复位引脚状态为高电平
|
||||
#define LCD_RST_LOW false //LCD复位引脚状态为低电平
|
||||
|
||||
/* 设置PA控制引脚 */
|
||||
#define PA_CTRL_PIN 2 //PA控制引脚对应IO扩展板引脚P1_2
|
||||
#define PA_CTRL_CONFIG CONFIG_PORT1 //PA控制引脚配置在P1_2
|
||||
#define PA_CTRL_PORT OUTPUT_PORT1 //PA控制引脚挂载在IO扩展板的输出端口OUTPUT_PORT1
|
||||
#define PA_CTRL_HIGH true //PA控制引脚状态为高电平
|
||||
#define PA_CTRL_LOW false //PA控制引脚状态为低电平
|
||||
|
||||
// 电池充电检测引脚定义
|
||||
#define BATTERY_FULL_INPUT INPUT_PORT1 // 电池充满检测引脚挂载在IO扩展板的输入端口
|
||||
#define BATTERY_FULL_PIN 3 // 电池充满检测引脚对应IO扩展板引脚P1_3
|
||||
#define BATTERY_FULL_CONFIG CONFIG_PORT1 // 电池充满检测引脚配置在P1_3
|
||||
|
||||
#define BATTERY_CHRG_INPUT INPUT_PORT0 // 充电检测引脚挂载在IO扩展板的输入端口
|
||||
#define BATTERY_CHRG_PIN 5 // 充电检测引脚(P0_5)
|
||||
#define BATTERY_CHRG_CONFIG CONFIG_PORT0 // 充电检测引脚挂载在IO扩展板的输入端口
|
||||
|
||||
#define TAG_GPIO_IO_EXPAND_DETECT "GPIO_IO_EXPAND_DETECT" // GPIO中断检测日志标签
|
||||
#define TAG_I2C_IO_EXPAND_TASK "I2C_IO_EXPAND_TASK" // I2CIO扩展板任务日志标签
|
||||
|
||||
// GPIO引脚定义
|
||||
#define GPIO_INPUT_PIN_SEL GPIO_NUM_10 // IO扩展板中断检测引脚
|
||||
// #define IO_EXPAND_RSTN GPIO_NUM_14 // IO扩展板复位引脚
|
||||
|
||||
/**
|
||||
* @class IOExpansionBoard
|
||||
* @brief I/O扩展板驱动类,封装AW9523BTQR芯片操作
|
||||
*/
|
||||
class IOExpansionBoard
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief 构造函数
|
||||
*/
|
||||
IOExpansionBoard();
|
||||
|
||||
/**
|
||||
* @brief 设置毫米波雷达指针
|
||||
* @param radar 毫米波雷达对象指针
|
||||
*/
|
||||
void SetRadar(MillimeterWaveRadar* radar) { radar_ = radar; };
|
||||
|
||||
/**
|
||||
* @brief 设置限位开关指针
|
||||
* @param photo_interrupter 限位开关对象指针
|
||||
*/
|
||||
void setPhotoInterrupter(PhotoInterrupter* photo_interrupter) { photo_interrupter_ = photo_interrupter; };
|
||||
|
||||
/**
|
||||
* @brief 设置电池监控器指针
|
||||
* @param battery_monitor 电池监控器对象指针
|
||||
*/
|
||||
void setBatteryMonitor(AdcBatteryMonitor* battery_monitor) { battery_monitor_ = battery_monitor; };
|
||||
|
||||
/**
|
||||
* @brief 析构函数
|
||||
*/
|
||||
~IOExpansionBoard();
|
||||
|
||||
/**
|
||||
* @brief 初始化GPIO中断检测
|
||||
* @param gpio_num 中断引脚编号
|
||||
* @return esp_err_t 初始化结果
|
||||
*/
|
||||
esp_err_t InterruptGpioInit(gpio_num_t gpio_num);
|
||||
|
||||
/**
|
||||
* @brief 初始化IO扩展板复位引脚
|
||||
* @param gpio_num 复位引脚编号
|
||||
* @return esp_err_t 初始化结果
|
||||
*/
|
||||
esp_err_t ResetGpioInit(gpio_num_t gpio_num);
|
||||
|
||||
/**
|
||||
* @brief 初始化IO扩展板复位引脚
|
||||
* @param gpio_num 复位引脚编号
|
||||
* @return esp_err_t 初始化结果
|
||||
*/
|
||||
esp_err_t ResetIoExpand();
|
||||
|
||||
/**
|
||||
* @brief 初始化I2C主机通信
|
||||
* @return esp_err_t 初始化结果
|
||||
*/
|
||||
// esp_err_t IoExpansionI2cInit();
|
||||
|
||||
/**
|
||||
* @brief 创建I2C数据读取任务
|
||||
*/
|
||||
void CreateI2cReadTask();
|
||||
|
||||
/**
|
||||
* @brief 启动I2C任务(整合初始化和任务创建)
|
||||
* @return esp_err_t 操作结果
|
||||
*/
|
||||
esp_err_t StartTask();
|
||||
|
||||
/**
|
||||
* @brief 写寄存器数据
|
||||
* @param reg_addr 寄存器地址
|
||||
* @param data 要写入的数据
|
||||
* @return esp_err_t 操作结果
|
||||
*/
|
||||
esp_err_t IoexpandWriteReg(uint8_t reg_addr, uint8_t data);
|
||||
|
||||
/**
|
||||
* @brief 读寄存器数据
|
||||
* @param reg_addr 寄存器地址
|
||||
* @param data 要读出的数据
|
||||
* @return esp_err_t 操作结果
|
||||
*/
|
||||
esp_err_t IoexpandReadReg(uint8_t reg_addr, uint8_t *data);
|
||||
|
||||
/**
|
||||
* @brief 读取输入端口0寄存器数据
|
||||
* @param data 输出参数,用于存储读取到的数据
|
||||
* @return esp_err_t 操作结果
|
||||
*/
|
||||
esp_err_t ReadInputPort0(uint8_t *data);
|
||||
|
||||
/**
|
||||
* @brief 读取输入端口1寄存器数据
|
||||
* @param data 输出参数,用于存储读取到的数据
|
||||
* @return esp_err_t 操作结果
|
||||
*/
|
||||
esp_err_t ReadInputPort1(uint8_t *data);
|
||||
|
||||
// /**
|
||||
// * @brief 设置IO扩展板GPIO中断状态 通过读取Input_Port0 和 Input_Port1 寄存器可以清除中断
|
||||
// * @param reg_addr 寄存器地址
|
||||
// * @return esp_err_t 操作结果
|
||||
// */
|
||||
// esp_err_t SetInterruptStatus(bool status);
|
||||
|
||||
/**
|
||||
* @brief 配置IO扩展版上的IO口为输出还是输入,并且设置初始为高电平
|
||||
* @return esp_err_t 操作结果
|
||||
*/
|
||||
esp_err_t IoexpandSetMode();
|
||||
|
||||
/**
|
||||
* @brief 设置步进电机的细分模式
|
||||
* @param mode 模式:1/2/4/8/16/32/64
|
||||
* @return esp_err_t 操作结果
|
||||
*/
|
||||
void SetStepperMicrostepMode(uint8_t mode, uint8_t OUTPUT_PORT_m0, uint8_t m0_pin, uint8_t OUTPUT_PORT_m1, uint8_t m1_pin);
|
||||
|
||||
/**
|
||||
* @brief 设置步进电机的方向
|
||||
* @param dir 方向
|
||||
* @param OUTPUT_PORT 输出端口
|
||||
* @param pin 引脚号
|
||||
* @return esp_err_t 操作结果
|
||||
*/
|
||||
esp_err_t StepperMotorSetDir(bool dir, uint8_t OUTPUT_PORT, uint8_t pin);
|
||||
|
||||
/**
|
||||
* @brief 设置步进电机的睡眠模式
|
||||
* @param 是否进入睡眠模式
|
||||
* @param 输出端口
|
||||
* @param 引脚号
|
||||
* @return esp_err_t 操作结果
|
||||
*/
|
||||
esp_err_t SetMotorSleepMode(bool mode, uint8_t OUTPUT_PORT, uint8_t nsleep_pin);
|
||||
|
||||
/**
|
||||
* @brief 设置步进电机的使能引脚状态
|
||||
* @param 使能状态
|
||||
* @return esp_err_t 操作结果
|
||||
*/
|
||||
esp_err_t SetMotorEnableMode(bool enable, uint8_t OUTPUT_PORT, uint8_t enable_pin);
|
||||
|
||||
/**
|
||||
* @brief 设置LCD的BL引脚状态
|
||||
* @param BL状态
|
||||
* @return esp_err_t 操作结果
|
||||
*/
|
||||
esp_err_t SetLcdBlMode(bool mode, uint8_t OUTPUT_PORT, uint8_t bl_pin);
|
||||
|
||||
esp_err_t SetLedEnMode(bool mode);
|
||||
|
||||
/**
|
||||
* @brief 设置LCD的RST引脚状态
|
||||
* @param RST状态
|
||||
* @return esp_err_t 操作结果
|
||||
*/
|
||||
esp_err_t SetLcdResetMode(bool mode, uint8_t OUTPUT_PORT, uint8_t rst_pin);
|
||||
|
||||
/**
|
||||
* @brief 设置PA控制引脚状态
|
||||
* @param mode PA_CTRL状态(true为高电平,false为低电平)
|
||||
* @return esp_err_t 操作结果
|
||||
*/
|
||||
esp_err_t SetPaCtrlMode(bool mode);
|
||||
|
||||
/**
|
||||
* @brief 设置雷达中断引脚
|
||||
* @param 毫米波雷达的中断引脚模式
|
||||
* @param 输入端口
|
||||
* @param 引脚号
|
||||
* @return esp_err_t 操作结果
|
||||
*/
|
||||
esp_err_t SetRadarInterruptPin(bool mode, uint8_t INPUT_PORT, uint8_t interrupt_pin);
|
||||
|
||||
/**
|
||||
* @brief 计算Port0的字节值
|
||||
* @return uint8_t 操作结果
|
||||
*/
|
||||
uint8_t ByteCalculatePort0();
|
||||
|
||||
/**
|
||||
* @brief 计算Port1的字节值
|
||||
* @return uint8_t 操作结果
|
||||
*/
|
||||
uint8_t ByteCalculatePort1();
|
||||
|
||||
/**
|
||||
* @brief 设置雷达中断回调函数
|
||||
* @param callback 雷达中断回调函数
|
||||
*/
|
||||
void SetRadarCallback(RadarCallback callback) { radar_callback_ = callback; }
|
||||
|
||||
/**
|
||||
* @brief 设置光学传感器开始中断回调函数
|
||||
* @param callback 光学传感器开始中断回调函数
|
||||
*/
|
||||
void SetPhotoInterrupterStartCallback(PhotoInterrupterStartCallback callback) { photo_start_callback_ = callback; }
|
||||
|
||||
/**
|
||||
* @brief 设置光学传感器结束中断回调函数
|
||||
* @param callback 光学传感器结束中断回调函数
|
||||
*/
|
||||
void SetPhotoInterrupterEndCallback(PhotoInterrupterEndCallback callback) { photo_end_callback_ = callback; }
|
||||
|
||||
/**
|
||||
* @brief 设置电池充电中断回调函数
|
||||
* @param callback 电池充电中断回调函数
|
||||
*/
|
||||
void SetBatteryChargingCallback(BatteryChargingCallback callback) { battery_charging_callback_ = callback; }
|
||||
|
||||
/**
|
||||
* @brief 设置电池充满中断回调函数
|
||||
* @param callback 电池充满中断回调函数
|
||||
*/
|
||||
void SetBatteryFullCallback(BatteryFullCallback callback) { battery_full_callback_ = callback; }
|
||||
|
||||
/**
|
||||
* @brief 设置电池非充电中断回调函数
|
||||
* @param callback 电池非充电中断回调函数
|
||||
*/
|
||||
void SetBatteryNotChargingCallback(BatteryNotChargingCallback callback) { battery_not_charging_callback_ = callback; }
|
||||
|
||||
// 公共成员变量
|
||||
i2c_bus_handle_t bus_handle_ = nullptr; // I2C总线句柄
|
||||
uint8_t device_addr_; // I2C设备地址
|
||||
|
||||
private:
|
||||
// 静态成员函数
|
||||
MillimeterWaveRadar* radar_ = nullptr; // 毫米波雷达指针,用于触发回调
|
||||
PhotoInterrupter* photo_interrupter_ = nullptr; // 限位开关指针,用于触发回调
|
||||
AdcBatteryMonitor* battery_monitor_ = nullptr; // 电池监控器指针,用于触发回调
|
||||
static void IRAM_ATTR GpioIsrHandler(void* arg); // 中断处理函数
|
||||
static void I2cReadTask(void* pvParameters); // I2C数据读取任务函数
|
||||
|
||||
// 成员变量用于状态跟踪
|
||||
uint8_t last_port0_state_ = 0; // 上次检测到的Port0状态
|
||||
uint8_t last_port1_state_ = 0; // 上次检测到的Port1状态
|
||||
bool radar_last_state_ = false; // 雷达引脚上一次的状态
|
||||
bool battery_charging_last_state_ = false; // 电池充电状态上一次的状态
|
||||
bool battery_full_last_state_ = false; // 电池充满状态上一次的状态
|
||||
|
||||
// 回调函数成员变量
|
||||
RadarCallback radar_callback_ = nullptr;
|
||||
PhotoInterrupterStartCallback photo_start_callback_ = nullptr;
|
||||
PhotoInterrupterEndCallback photo_end_callback_ = nullptr;
|
||||
BatteryChargingCallback battery_charging_callback_ = nullptr;
|
||||
BatteryFullCallback battery_full_callback_ = nullptr;
|
||||
BatteryNotChargingCallback battery_not_charging_callback_ = nullptr;
|
||||
|
||||
// PhotoInterrupter* photo_interrupter_ = nullptr; // 光学传感器指针,用于触发回调
|
||||
// /**
|
||||
// * @brief 分配静态任务所需的内存
|
||||
// * @return bool 分配是否成功
|
||||
// */
|
||||
// bool AllocateStaticTaskMemory();
|
||||
|
||||
// /**
|
||||
// * @brief 释放静态任务分配的内存
|
||||
// */
|
||||
// void FreeStaticTaskMemory();
|
||||
|
||||
// 实例成员变量
|
||||
EventGroupHandle_t i2c_task_event_group_ = nullptr; // 事件组
|
||||
TaskHandle_t xI2CReadTaskHandle_ = nullptr; // 任务句柄
|
||||
bool is_initialized_ = false; // 初始化状态标记(新增)
|
||||
gpio_num_t interrupt_gpio_ = GPIO_NUM_NC; // 中断引脚
|
||||
gpio_num_t reset_gpio_ = GPIO_NUM_NC; // 复位引脚
|
||||
|
||||
// StackType_t* pI2CReadTaskStackBuffer = nullptr; // 任务栈指针(PSRAM)
|
||||
// StaticTask_t* pxI2CReadTaskBuffer = nullptr; // 任务控制块指针(内部RAM)
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,178 @@
|
||||
/**
|
||||
* @file power_management_config.h
|
||||
* @brief 功耗管理配置和策略定义
|
||||
* @author Embedded Software Expert
|
||||
* @date 2025年1月
|
||||
*
|
||||
* 这个文件定义了功耗管理的配置参数、策略和优化建议,
|
||||
* 为系统提供灵活的功耗管理方案。
|
||||
*/
|
||||
|
||||
#ifndef POWER_MANAGEMENT_CONFIG_H
|
||||
#define POWER_MANAGEMENT_CONFIG_H
|
||||
|
||||
#include "esp_sleep.h"
|
||||
#include "driver/rtc_io.h"
|
||||
#include "esp32/rom/rtc.h"
|
||||
|
||||
/**
|
||||
* @brief 功耗管理配置结构体
|
||||
*/
|
||||
typedef struct {
|
||||
// 睡眠模式配置
|
||||
uint64_t light_sleep_duration_us; // 轻度睡眠持续时间(微秒)
|
||||
uint64_t deep_sleep_duration_us; // 深度睡眠持续时间(微秒)
|
||||
|
||||
// 唤醒源配置
|
||||
bool enable_timer_wakeup; // 启用定时器唤醒
|
||||
bool enable_gpio_wakeup; // 启用GPIO唤醒
|
||||
bool enable_touch_wakeup; // 启用触摸唤醒
|
||||
gpio_num_t wakeup_gpio_num; // 唤醒GPIO编号
|
||||
int wakeup_level; // 唤醒电平(0或1)
|
||||
|
||||
// 功耗优化配置
|
||||
bool disable_bt_in_sleep; // 睡眠时关闭蓝牙
|
||||
bool disable_wifi_in_sleep; // 睡眠时关闭WiFi
|
||||
bool reduce_cpu_frequency; // 降低CPU频率
|
||||
uint32_t cpu_frequency_hz; // CPU频率(Hz)
|
||||
|
||||
// 外设功耗配置
|
||||
bool power_down_sdcard; // 睡眠时关闭SD卡电源
|
||||
bool power_down_display; // 睡眠时关闭显示电源
|
||||
bool power_down_audio; // 睡眠时关闭音频电源
|
||||
bool power_down_motor; // 睡眠时关闭电机电源
|
||||
|
||||
// RTC内存配置
|
||||
bool preserve_rtc_memory; // 保留RTC内存
|
||||
size_t rtc_memory_size; // RTC内存大小
|
||||
} power_management_config_t;
|
||||
|
||||
/**
|
||||
* @brief 默认功耗管理配置
|
||||
*/
|
||||
#define DEFAULT_POWER_CONFIG { \
|
||||
.light_sleep_duration_us = 1000000, /* 1秒 */ \
|
||||
.deep_sleep_duration_us = 30000000, /* 30秒 */ \
|
||||
.enable_timer_wakeup = true, /* 启用定时器唤醒 */ \
|
||||
.enable_gpio_wakeup = false, /* 不启用GPIO唤醒 */ \
|
||||
.enable_touch_wakeup = false, /* 不启用触摸唤醒 */ \
|
||||
.wakeup_gpio_num = GPIO_NUM_NC, /* 无GPIO唤醒 */ \
|
||||
.wakeup_level = 0, /* 低电平唤醒 */ \
|
||||
.disable_bt_in_sleep = true, /* 睡眠时关闭蓝牙 */ \
|
||||
.disable_wifi_in_sleep = true, /* 睡眠时关闭WiFi */ \
|
||||
.reduce_cpu_frequency = true, /* 降低CPU频率 */ \
|
||||
.cpu_frequency_hz = 80000000, /* 80MHz */ \
|
||||
.power_down_sdcard = true, /* 睡眠时关闭SD卡 */ \
|
||||
.power_down_display = true, /* 睡眠时关闭显示 */ \
|
||||
.power_down_audio = true, /* 睡眠时关闭音频 */ \
|
||||
.power_down_motor = true, /* 睡眠时关闭电机 */ \
|
||||
.preserve_rtc_memory = true, /* 保留RTC内存 */ \
|
||||
.rtc_memory_size = 4096, /* 4KB RTC内存 */ \
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 各功耗模式的详细配置
|
||||
*/
|
||||
static const power_management_config_t idle_mode_config = {
|
||||
.light_sleep_duration_us = 500000, // 500ms轻度睡眠
|
||||
.deep_sleep_duration_us = 0, // 不使用深度睡眠
|
||||
.enable_timer_wakeup = true,
|
||||
.enable_gpio_wakeup = true,
|
||||
.wakeup_gpio_num = GPIO_NUM_0, // 按键唤醒
|
||||
.wakeup_level = 0,
|
||||
.disable_bt_in_sleep = false, // 保持蓝牙连接
|
||||
.disable_wifi_in_sleep = false, // 保持WiFi连接
|
||||
.reduce_cpu_frequency = true,
|
||||
.cpu_frequency_hz = 40000000, // 40MHz
|
||||
.power_down_sdcard = false, // 保持SD卡(可能有后台任务)
|
||||
.power_down_display = true, // 关闭显示背光
|
||||
.power_down_audio = true, // 关闭音频
|
||||
.power_down_motor = true, // 关闭电机
|
||||
.preserve_rtc_memory = true,
|
||||
.rtc_memory_size = 2048,
|
||||
};
|
||||
|
||||
static const power_management_config_t light_sleep_config = {
|
||||
.light_sleep_duration_us = 0, // 直接进入轻度睡眠
|
||||
.deep_sleep_duration_us = 0,
|
||||
.enable_timer_wakeup = true,
|
||||
.enable_gpio_wakeup = true,
|
||||
.wakeup_gpio_num = GPIO_NUM_0,
|
||||
.wakeup_level = 0,
|
||||
.disable_bt_in_sleep = true, // 关闭蓝牙
|
||||
.disable_wifi_in_sleep = true, // 关闭WiFi
|
||||
.reduce_cpu_frequency = true,
|
||||
.cpu_frequency_hz = 40000000,
|
||||
.power_down_sdcard = true, // 关闭SD卡
|
||||
.power_down_display = true, // 关闭显示
|
||||
.power_down_audio = true, // 关闭音频
|
||||
.power_down_motor = true, // 关闭电机
|
||||
.preserve_rtc_memory = true,
|
||||
.rtc_memory_size = 4096,
|
||||
};
|
||||
|
||||
static const power_management_config_t deep_sleep_config = {
|
||||
.light_sleep_duration_us = 0,
|
||||
.deep_sleep_duration_us = 60000000, // 60秒深度睡眠
|
||||
.enable_timer_wakeup = true,
|
||||
.enable_gpio_wakeup = true,
|
||||
.wakeup_gpio_num = GPIO_NUM_0,
|
||||
.wakeup_level = 0,
|
||||
.disable_bt_in_sleep = true, // 关闭蓝牙
|
||||
.disable_wifi_in_sleep = true, // 关闭WiFi
|
||||
.reduce_cpu_frequency = true,
|
||||
.cpu_frequency_hz = 10000000, // 10MHz
|
||||
.power_down_sdcard = true, // 关闭SD卡
|
||||
.power_down_display = true, // 关闭显示
|
||||
.power_down_audio = true, // 关闭音频
|
||||
.power_down_motor = true, // 关闭电机
|
||||
.preserve_rtc_memory = true,
|
||||
.rtc_memory_size = 8192,
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 功耗统计和监控结构体
|
||||
*/
|
||||
typedef struct {
|
||||
uint64_t total_sleep_time_us; // 总睡眠时间
|
||||
uint64_t total_wake_time_us; // 总唤醒时间
|
||||
uint32_t sleep_count; // 睡眠次数
|
||||
uint32_t wake_count; // 唤醒次数
|
||||
uint32_t average_sleep_duration_us; // 平均睡眠时长
|
||||
uint32_t average_wake_duration_us; // 平均唤醒时长
|
||||
float estimated_power_saving_percent; // 估计的功耗节省百分比
|
||||
} power_statistics_t;
|
||||
|
||||
/**
|
||||
* @brief 功耗优化建议
|
||||
*
|
||||
* 基于硬件特性和使用模式,提供功耗优化建议
|
||||
*/
|
||||
typedef enum {
|
||||
OPTIMIZATION_NONE = 0,
|
||||
OPTIMIZATION_REDUCE_CPU_FREQ, // 降低CPU频率
|
||||
OPTIMIZATION_DISABLE_UNUSED_PERIPHERALS, // 关闭未使用的外设
|
||||
OPTIMIZATION_USE_LIGHT_SLEEP, // 使用轻度睡眠
|
||||
OPTIMIZATION_USE_DEEP_SLEEP, // 使用深度睡眠
|
||||
OPTIMIZATION_OPTIMIZE_GPIO_STATES, // 优化GPIO状态
|
||||
OPTIMIZATION_USE_RTC_MEMORY, // 使用RTC内存
|
||||
OPTIMIZATION_BATCH_OPERATIONS, // 批量操作
|
||||
} power_optimization_t;
|
||||
|
||||
/**
|
||||
* @brief 功耗管理事件回调
|
||||
*/
|
||||
typedef void (*power_event_callback_t)(power_mode_t old_mode, power_mode_t new_mode, void* user_data);
|
||||
|
||||
/**
|
||||
* @brief 功耗管理事件
|
||||
*/
|
||||
typedef enum {
|
||||
POWER_EVENT_MODE_CHANGE, // 功耗模式改变
|
||||
POWER_EVENT_SLEEP_START, // 睡眠开始
|
||||
POWER_EVENT_SLEEP_END, // 睡眠结束
|
||||
POWER_EVENT_WAKEUP, // 系统唤醒
|
||||
POWER_EVENT_OPTIMIZATION_TRIGGER, // 功耗优化触发
|
||||
} power_event_t;
|
||||
|
||||
#endif // POWER_MANAGEMENT_CONFIG_H
|
||||
@@ -0,0 +1,738 @@
|
||||
/**
|
||||
* @file board.cc
|
||||
* @brief 板级外设初始化类,包含步进电机、毫米波雷达、I2C总线等外设的初始化函数。
|
||||
* @author zouyuhua
|
||||
* @date 2025年8月7日
|
||||
*
|
||||
*/
|
||||
|
||||
extern "C" {
|
||||
#include "esp_log.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "driver/uart.h"
|
||||
#include "driver/ledc.h"
|
||||
#include "driver/gptimer.h"
|
||||
#include "esp_err.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "hal/gpio_types.h"
|
||||
#include "hal/uart_types.h"
|
||||
#include "esp_check.h"
|
||||
#include "sdkconfig.h"
|
||||
#include "i2c_bus.h"
|
||||
#include "esp_peripherals.h"
|
||||
#include "periph_sdcard.h"
|
||||
#include "esp_sleep.h"
|
||||
#include "driver/rtc_io.h"
|
||||
}
|
||||
|
||||
#include "board_sweekar.h"
|
||||
#include "config.h"
|
||||
#include "board.h" // 添加board.h以获取audio_board_sdcard_init函数声明
|
||||
#include "drv8428.h"
|
||||
#include "aw8646.h"
|
||||
|
||||
#define TAG "board_sweekar"
|
||||
|
||||
BoardSweekar::BoardSweekar()
|
||||
{
|
||||
#ifdef CONFIG_STEPPER_DRIVER_AW8646
|
||||
stepper_driver_ = new Aw8646Driver(io_expansion_);
|
||||
#else
|
||||
stepper_driver_ = new Drv8428Driver(io_expansion_);
|
||||
#endif
|
||||
|
||||
// Initialize Shutdown Control Pin (GPIO_NUM_13) and pull it HIGH
|
||||
// This is required to keep the main power on.
|
||||
#ifdef SHUTDOWN_CTRL_PIN
|
||||
gpio_config_t io_conf = {};
|
||||
io_conf.intr_type = GPIO_INTR_DISABLE;
|
||||
io_conf.mode = GPIO_MODE_OUTPUT;
|
||||
io_conf.pin_bit_mask = (1ULL << SHUTDOWN_CTRL_PIN);
|
||||
io_conf.pull_down_en = GPIO_PULLDOWN_DISABLE;
|
||||
io_conf.pull_up_en = GPIO_PULLUP_ENABLE;
|
||||
gpio_config(&io_conf);
|
||||
gpio_set_level(SHUTDOWN_CTRL_PIN, 1);
|
||||
ESP_LOGI(TAG, "Initialized SHUTDOWN_CTRL_PIN (%d) to HIGH", SHUTDOWN_CTRL_PIN);
|
||||
#endif
|
||||
}
|
||||
|
||||
BoardSweekar::~BoardSweekar()
|
||||
{
|
||||
if (stepper_driver_) {
|
||||
delete stepper_driver_;
|
||||
stepper_driver_ = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
/*========================== 步进电机相关驱动 ==========================*/
|
||||
|
||||
/**
|
||||
* @brief 步进电机初始化函数
|
||||
* 配置步进电机所需的GPIO引脚模式,通过IO扩展板设置步进驱动芯片的工作模式
|
||||
* 在 stepper_motor.cc 中完成 GPTimer + GPIO 翻转 STEP 脉冲的初始化
|
||||
*/
|
||||
void BoardSweekar::StepperMotorInit(void)
|
||||
{
|
||||
esp_err_t err = ESP_OK;
|
||||
|
||||
// 1) STEP 引脚改为普通 GPIO(不再用 LEDC)
|
||||
gpio_config_t io_cfg;
|
||||
io_cfg.pin_bit_mask = 1ULL << STEPPER_STEP_IO;
|
||||
io_cfg.mode = GPIO_MODE_OUTPUT;
|
||||
io_cfg.pull_up_en = GPIO_PULLUP_DISABLE;
|
||||
io_cfg.pull_down_en = GPIO_PULLDOWN_DISABLE;
|
||||
io_cfg.intr_type = GPIO_INTR_DISABLE;
|
||||
err = gpio_config(&io_cfg);
|
||||
if (err != ESP_OK)
|
||||
{
|
||||
ESP_LOGE(TAG_BOARD, "步进电机 STEP GPIO 配置失败, 错误码: 0x%x", err);
|
||||
}
|
||||
|
||||
// 初始电平拉低,保证上电不乱跳
|
||||
gpio_set_level(STEPPER_STEP_IO, 0);
|
||||
|
||||
// 2) 检查 I2C 总线是否已初始化
|
||||
if (bus_handle_ == nullptr)
|
||||
{
|
||||
ESP_LOGE(TAG_BOARD, "I2C总线未初始化,请先调用I2CMasterInit()");
|
||||
return;
|
||||
}
|
||||
|
||||
// 3) 初始化驱动对象并初始化
|
||||
if (stepper_driver_) {
|
||||
err = stepper_driver_->Init();
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG_BOARD, "步进电机驱动初始化失败, 错误码: 0x%x", err);
|
||||
}
|
||||
} else {
|
||||
ESP_LOGE(TAG_BOARD, "步进电机驱动创建失败");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief LCD IO引脚初始化函数(消除与步进电机的耦合)
|
||||
*
|
||||
* 配置LCD所需的IO扩展板寄存器,确保LCD复位引脚正常工作
|
||||
* 此函数独立于步进电机初始化,专门处理LCD相关的IO配置
|
||||
*/
|
||||
void BoardSweekar::LcdIoInit(void)
|
||||
{
|
||||
esp_err_t err = ESP_OK;
|
||||
|
||||
// 1) 检查I2C总线是否已初始化
|
||||
if (bus_handle_ == nullptr)
|
||||
{
|
||||
ESP_LOGE(TAG_BOARD, "I2C总线未初始化,请先调用I2CMasterInit()");
|
||||
return;
|
||||
}
|
||||
|
||||
// 2) 执行硬件复位,确保IO扩展板处于已知状态
|
||||
err = io_expansion_.ResetIoExpand();
|
||||
if (err != ESP_OK)
|
||||
{
|
||||
ESP_LOGE(TAG_BOARD, "IO扩展板硬件复位失败, 错误码: 0x%x", err);
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
ESP_LOGI(TAG_BOARD, "IO扩展板硬件复位成功");
|
||||
}
|
||||
|
||||
// 3) 配置IO扩展板模式(端口方向等)
|
||||
err = io_expansion_.IoexpandSetMode();
|
||||
if (err != ESP_OK)
|
||||
{
|
||||
ESP_LOGE(TAG_BOARD, "IO扩展板模式配置失败, 错误码: 0x%x", err);
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
ESP_LOGI(TAG_BOARD, "IO扩展板模式配置成功");
|
||||
}
|
||||
|
||||
// 4) 初始化LCD复位引脚:设置为高电平
|
||||
err = io_expansion_.SetLcdResetMode(LCD_RST_HIGH, LCD_RST_PORT, LCD_RST_PIN);
|
||||
if (err != ESP_OK)
|
||||
{
|
||||
ESP_LOGE(TAG_BOARD, "LCD复位引脚高电平设置失败, 错误码: 0x%x", err);
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
ESP_LOGI(TAG_BOARD, "LCD复位引脚高电平设置成功");
|
||||
}
|
||||
}
|
||||
|
||||
/*========================== 毫米波雷达相关驱动 ==========================*/
|
||||
|
||||
/**
|
||||
* @brief 毫米波雷达串口初始化函数
|
||||
*
|
||||
* 配置毫米波雷达所使用的串口参数(波特率、数据位、校验位、停止位等),设置串口引脚,
|
||||
* 并安装串口驱动。采用较大的RX/TX FIFO深度以处理突发数据,禁用驱动自带事件队列以避免
|
||||
* 与自定义中断冲突。
|
||||
*/
|
||||
void BoardSweekar::MillimeterWaveRadarUartInit(void)
|
||||
{
|
||||
uart_config_t uart_config = {
|
||||
.baud_rate = RADAR_BAUD_RATE,
|
||||
.data_bits = UART_DATA_8_BITS,
|
||||
.parity = UART_PARITY_DISABLE,
|
||||
.stop_bits = UART_STOP_BITS_1,
|
||||
.flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
|
||||
.source_clk = UART_SCLK_DEFAULT,
|
||||
.flags = {
|
||||
.allow_pd = 0,
|
||||
.backup_before_sleep = 0,
|
||||
},
|
||||
};
|
||||
|
||||
// 1. 设置串口参数
|
||||
ESP_ERROR_CHECK(uart_param_config(RADAR_UART_NUM, &uart_config));
|
||||
|
||||
// 2. 设置 UART 引脚
|
||||
ESP_ERROR_CHECK(uart_set_pin(RADAR_UART_NUM, UART_TX_PIN, UART_RX_PIN,
|
||||
UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE));
|
||||
|
||||
// 3. 安装 UART 驱动(禁用驱动自带事件队列,避免与自定义中断冲突)
|
||||
// 增加 RX/TX FIFO 深度以处理突发数据
|
||||
ESP_ERROR_CHECK(uart_driver_install(RADAR_UART_NUM, RADAR_BUF_SIZE * 4, RADAR_BUF_SIZE * 4,
|
||||
0, NULL, 0));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 执行系统关机(拉高 SHUTDOWN_CTRL_PIN 切断电源)
|
||||
*/
|
||||
void BoardSweekar::SystemShutdown(void)
|
||||
{
|
||||
#ifdef SHUTDOWN_CTRL_PIN
|
||||
ESP_LOGI(TAG, "Executing System Shutdown... Pulling SHUTDOWN_CTRL_PIN (%d) HIGH", SHUTDOWN_CTRL_PIN);
|
||||
gpio_set_level(SHUTDOWN_CTRL_PIN, 1);
|
||||
vTaskDelay(pdMS_TO_TICKS(1000));
|
||||
#else
|
||||
ESP_LOGW(TAG, "SHUTDOWN_CTRL_PIN is not defined. Cannot execute hardware shutdown.");
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 毫米波雷达中断引脚初始化函数
|
||||
*
|
||||
* 配置毫米波雷达中断引脚为输入模式,禁用上拉电阻,使能下拉电阻,初始禁用中断功能
|
||||
* (如需使用中断需单独进行配置)。
|
||||
*/
|
||||
void BoardSweekar::MillimeterWaveRadarGpioInit(void)
|
||||
{
|
||||
// GPIO配置结构体
|
||||
gpio_config_t io_conf = {
|
||||
.pin_bit_mask = (1ULL << MILLIMETER_WAVE_RADAR_PIN), // 选择GPIO引脚
|
||||
.mode = GPIO_MODE_INPUT, // 设置为输入模式
|
||||
.pull_up_en = GPIO_PULLUP_DISABLE,
|
||||
.pull_down_en = GPIO_PULLDOWN_ENABLE, // 使能下拉
|
||||
.intr_type = GPIO_INTR_DISABLE // 禁用中断(如需中断需单独配置)
|
||||
};
|
||||
|
||||
// 配置GPIO
|
||||
gpio_config(&io_conf);
|
||||
}
|
||||
|
||||
/*========================== I2C总线及挂载的从设备相关驱动 ==========================*/
|
||||
|
||||
/**
|
||||
* @brief I2C总线及从机设备初始化函数
|
||||
*
|
||||
* 首先配置并创建I2C主机总线,然后依次添加IO扩展板和线性马达作为I2C从机设备到总线上。
|
||||
* 若总线创建或设备添加失败,会输出错误信息并进行相应的资源清理(删除已创建的总线)。
|
||||
* 初始化成功后,会通过ESP_LOGI输出IO扩展板和线性马达的从机地址信息。
|
||||
*
|
||||
* @return esp_err_t 初始化结果,ESP_OK表示成功,其他错误码表示相应的失败原因
|
||||
*/
|
||||
esp_err_t BoardSweekar::I2CMasterInit(void)
|
||||
{
|
||||
static const char *I2C_INIT = "I2C_INIT";
|
||||
|
||||
// 初始化IO扩展板复位引脚
|
||||
gpio_config_t reset_io_conf = {
|
||||
.pin_bit_mask = (1ULL << IO_EXPAND_RSTN),
|
||||
.mode = GPIO_MODE_OUTPUT,
|
||||
.pull_up_en = GPIO_PULLUP_ENABLE, // 使能上拉
|
||||
.pull_down_en = GPIO_PULLDOWN_DISABLE,
|
||||
.intr_type = GPIO_INTR_DISABLE
|
||||
};
|
||||
gpio_config(&reset_io_conf);
|
||||
|
||||
// 执行复位时序:先拉低100ms,再拉高并等待100ms
|
||||
gpio_set_level(IO_EXPAND_RSTN, 0); // 拉低复位
|
||||
vTaskDelay(pdMS_TO_TICKS(100)); // 等待100ms
|
||||
gpio_set_level(IO_EXPAND_RSTN, 1); // 释放复位
|
||||
vTaskDelay(pdMS_TO_TICKS(100)); // 等待设备启动
|
||||
|
||||
ESP_LOGI(I2C_INIT, "IO扩展板复位完成");
|
||||
|
||||
// 创建统一的I2C总线(使用ESP-ADF的i2c_bus)
|
||||
i2c_config_t i2c_cfg = {
|
||||
.mode = I2C_MODE_MASTER,
|
||||
.sda_io_num = I2C0_MASTER_SDA_IO,
|
||||
.scl_io_num = I2C0_MASTER_SCL_IO,
|
||||
.sda_pullup_en = GPIO_PULLUP_ENABLE,
|
||||
.scl_pullup_en = GPIO_PULLUP_ENABLE,
|
||||
.master = {
|
||||
.clk_speed = 100000,
|
||||
},
|
||||
};
|
||||
|
||||
// 创建I2C总线(ESP-ADF的audio_board_init会复用这个总线)
|
||||
bus_handle_ = i2c_bus_create(I2C0_MASTER_PORT, &i2c_cfg);
|
||||
if (bus_handle_ == NULL) {
|
||||
ESP_LOGE(TAG, "Failed to create I2C bus");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
vTaskDelay(pdMS_TO_TICKS(100)); // 等待设备启动
|
||||
// ESP-ADF的i2c_bus不需要单独添加设备,直接通过总线句柄和设备地址进行通信
|
||||
|
||||
// 验证线性马达设备是否存在
|
||||
esp_err_t err = i2c_bus_probe_addr(bus_handle_, LINEAR_MOTOR_I2C_SLAVE_ADDR << 1);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(I2C_INIT, "线性马达设备未找到(地址:0x%02X),错误码: 0x%x", LINEAR_MOTOR_I2C_SLAVE_ADDR, err);
|
||||
// 不返回错误,继续初始化
|
||||
} else {
|
||||
ESP_LOGI(I2C_INIT, "线性马达设备检测成功(地址:0x%02X)", LINEAR_MOTOR_I2C_SLAVE_ADDR);
|
||||
}
|
||||
// 验证IO扩展板设备是否存在
|
||||
err = i2c_bus_probe_addr(bus_handle_, I2C_IO_EXPAND_SLAVE_ADDR << 1);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(I2C_INIT, "IO扩展板设备未找到(地址:0x%02X),错误码: 0x%x", I2C_IO_EXPAND_SLAVE_ADDR, err);
|
||||
// 不返回错误,继续初始化其他设备
|
||||
} else {
|
||||
ESP_LOGI(I2C_INIT, "IO扩展板设备检测成功(地址:0x%02X)", I2C_IO_EXPAND_SLAVE_ADDR);
|
||||
}
|
||||
// 验证陀螺仪设备是否存在
|
||||
err = i2c_bus_probe_addr(bus_handle_, GYROSCOPE_I2C_SLAVE_ADDR << 1);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(I2C_INIT, "陀螺仪设备未找到(地址:0x%02X),错误码: 0x%x", GYROSCOPE_I2C_SLAVE_ADDR, err);
|
||||
// 不返回错误,继续初始化
|
||||
} else {
|
||||
ESP_LOGI(I2C_INIT, "陀螺仪设备检测成功(地址:0x%02X)", GYROSCOPE_I2C_SLAVE_ADDR);
|
||||
}
|
||||
|
||||
// 为IO扩展板设置总线句柄和设备地址(使用7位地址)
|
||||
io_expansion_.bus_handle_ = bus_handle_;
|
||||
io_expansion_.device_addr_ = I2C_IO_EXPAND_SLAVE_ADDR << 1;
|
||||
|
||||
// 线性马达的初始化已移至 InitializeAllHardware 中统一调用 Init 方法
|
||||
// linear_motor_ 的参数传递将在那里完成,不再此处直接赋值,提高内聚性
|
||||
|
||||
ESP_LOGI(I2C_INIT, "I2C总线初始化完成");
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
/*========================== VBAT to VBAT_5V相关驱动 ==========================*/
|
||||
|
||||
/**
|
||||
* @brief 开启VBAT to VBAT_5V
|
||||
*
|
||||
* 创建开启升压的电源管理单元
|
||||
*
|
||||
*/
|
||||
void BoardSweekar::VbatToVbat5vInit(void)
|
||||
{
|
||||
// 配置VBAT_5V引脚为输出模式
|
||||
gpio_config_t io_conf = {
|
||||
.pin_bit_mask = (1ULL << VBAT_5V_PIN),
|
||||
.mode = GPIO_MODE_OUTPUT,
|
||||
.pull_up_en = GPIO_PULLUP_DISABLE,
|
||||
.pull_down_en = GPIO_PULLDOWN_DISABLE,
|
||||
.intr_type = GPIO_INTR_DISABLE
|
||||
};
|
||||
gpio_config(&io_conf);
|
||||
// 使能VBAT_5V
|
||||
gpio_set_level(VBAT_5V_PIN, 1);
|
||||
}
|
||||
|
||||
/*========================== 底座控制串口相关驱动 ==========================*/
|
||||
|
||||
/**
|
||||
* @brief 底座控制命令串口初始化函数
|
||||
*/
|
||||
// 根据配置选择通信方式的HAL头文件
|
||||
#ifdef CONFIG_BASE_BOARD_COMM_I2C
|
||||
#include "base_board_hal_i2c.h"
|
||||
#else
|
||||
#include "base_board_hal_uart.h"
|
||||
#endif
|
||||
|
||||
void BoardSweekar::BaseBoardControlInit(void)
|
||||
{
|
||||
#ifdef CONFIG_BASE_BOARD_COMM_I2C
|
||||
// I2C Mode
|
||||
if (bus_handle_ == nullptr) {
|
||||
ESP_LOGE(TAG, "I2C bus not initialized before BaseBoardControlInit");
|
||||
return;
|
||||
}
|
||||
|
||||
// 创建 I2C HAL 实例
|
||||
BaseBoardHalI2c *hal = new BaseBoardHalI2c(bus_handle_);
|
||||
base_board_control_.Init(hal);
|
||||
ESP_LOGI(TAG, "BaseBoardControl I2C initialized");
|
||||
#else
|
||||
// UART Mode
|
||||
uart_config_t uart_config = {
|
||||
.baud_rate = BASE_BOARD_CTL_UART_BAUDRATE,
|
||||
.data_bits = UART_DATA_8_BITS,
|
||||
.parity = UART_PARITY_DISABLE,
|
||||
.stop_bits = UART_STOP_BITS_1,
|
||||
.flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
|
||||
.source_clk = UART_SCLK_DEFAULT,
|
||||
.flags = {
|
||||
.allow_pd = 0,
|
||||
.backup_before_sleep = 0,
|
||||
},
|
||||
};
|
||||
|
||||
// 1. 设置串口参数
|
||||
ESP_ERROR_CHECK(uart_param_config(BASE_BOARD_CTL_UART_PORT, &uart_config));
|
||||
|
||||
// 2. 设置 UART 引脚
|
||||
ESP_ERROR_CHECK(uart_set_pin(BASE_BOARD_CTL_UART_PORT, BASE_BOARD_CTL_UART_TX_PIN, BASE_BOARD_CTL_UART_RX_PIN,
|
||||
UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE));
|
||||
|
||||
// 3. 安装 UART 驱动
|
||||
ESP_ERROR_CHECK(uart_driver_install(BASE_BOARD_CTL_UART_PORT,
|
||||
BASE_BOARD_CTL_UART_BUF_SIZE,
|
||||
BASE_BOARD_CTL_UART_BUF_SIZE,
|
||||
0, NULL, 0));
|
||||
|
||||
BaseBoardHalUart *hal = new BaseBoardHalUart(BASE_BOARD_CTL_UART_PORT);
|
||||
base_board_control_.Init(hal);
|
||||
ESP_LOGI(TAG, "BaseBoardControl UART initialized");
|
||||
#endif
|
||||
}
|
||||
|
||||
/*========================== SD卡相关驱动 ==========================*/
|
||||
|
||||
/**
|
||||
* @brief SD卡初始化函数
|
||||
*
|
||||
* 初始化SD卡外设,使用1线模式进行通信。该函数负责初始化外设管理器
|
||||
* 并配置SD卡,为后续的文件系统操作做准备。
|
||||
*
|
||||
* @return esp_err_t 初始化结果,ESP_OK表示成功,其他错误码表示失败原因
|
||||
*/
|
||||
esp_err_t BoardSweekar::InitializeSdcard(void)
|
||||
{
|
||||
static const char *SDCARD_TAG = "SDCARD_INIT";
|
||||
esp_err_t ret;
|
||||
|
||||
ESP_LOGI(SDCARD_TAG, "Initializing SD card");
|
||||
|
||||
if (is_sdcard_initialized_) {
|
||||
ESP_LOGW(SDCARD_TAG, "SD card already initialized");
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
// 初始化外设管理
|
||||
esp_periph_config_t periph_cfg = DEFAULT_ESP_PERIPH_SET_CONFIG();
|
||||
periph_cfg.extern_stack = true; // 将任务栈分配到 PSRAM 以节省 Internal SRAM
|
||||
periph_set_ = esp_periph_set_init(&periph_cfg);
|
||||
if (!periph_set_) {
|
||||
ESP_LOGE(SDCARD_TAG, "Failed to initialize peripheral set");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
// 初始化SD卡外设
|
||||
ret = audio_board_sdcard_init(periph_set_, SD_MODE_1_LINE);
|
||||
if (ret != ESP_OK) {
|
||||
ESP_LOGE(SDCARD_TAG, "Failed to initialize SD card: %s", esp_err_to_name(ret));
|
||||
return ret;
|
||||
}
|
||||
|
||||
is_sdcard_initialized_ = true;
|
||||
ESP_LOGI(SDCARD_TAG, "SD card initialized successfully");
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 统一的硬件初始化接口实现
|
||||
*
|
||||
* 按照依赖关系顺序初始化所有硬件资源:
|
||||
* 1. I2C总线(最基础,其他设备可能依赖)
|
||||
* 2. IO扩展板(可能影响其他设备)
|
||||
* 3. SD卡(文件系统,供显示和音频使用)
|
||||
* 4. 其他外设
|
||||
*
|
||||
* @return esp_err_t 初始化结果,ESP_OK表示全部成功
|
||||
*/
|
||||
esp_err_t BoardSweekar::InitializeAllHardware(void)
|
||||
{
|
||||
static const char *HW_INIT_TAG = "HW_INIT";
|
||||
esp_err_t ret;
|
||||
|
||||
ESP_LOGI(HW_INIT_TAG, "Starting unified hardware initialization...");
|
||||
|
||||
// 1. 初始化I2C总线(最基础)
|
||||
ret = I2CMasterInit();
|
||||
if (ret != ESP_OK) {
|
||||
ESP_LOGE(HW_INIT_TAG, "Failed to initialize I2C master: %s", esp_err_to_name(ret));
|
||||
return ret;
|
||||
}
|
||||
ESP_LOGI(HW_INIT_TAG, "I2C master initialized");
|
||||
|
||||
// 2. 创建I2C读任务(IO扩展板需要)
|
||||
io_expansion_.CreateI2cReadTask();
|
||||
ESP_LOGI(HW_INIT_TAG, "I2C read task created");
|
||||
|
||||
// 3. 初始化SD卡(文件系统,供显示和音频使用)
|
||||
ret = InitializeSdcard();
|
||||
if (ret != ESP_OK) {
|
||||
ESP_LOGE(HW_INIT_TAG, "Failed to initialize SD card: %s", esp_err_to_name(ret));
|
||||
// SD卡失败不是致命错误,继续初始化其他硬件
|
||||
ESP_LOGW(HW_INIT_TAG, "SD card initialization failed, but continuing with other hardware");
|
||||
} else {
|
||||
ESP_LOGI(HW_INIT_TAG, "SD card initialized");
|
||||
}
|
||||
|
||||
// 4. 初始化LCD IO引脚
|
||||
LcdIoInit();
|
||||
ESP_LOGI(HW_INIT_TAG, "LCD IO pins initialized");
|
||||
|
||||
// 5. 初始化其他必要外设
|
||||
// BaseBoardControlUartInit(); // 底座控制串口(demo5需要)
|
||||
// ESP_LOGI(HW_INIT_TAG, "Base board control UART initialized");
|
||||
|
||||
// 初始化底座控制
|
||||
// base_board_control_.Init();
|
||||
// ESP_LOGI(HW_INIT_TAG, "Base board control initialized");
|
||||
|
||||
// 可选外设(根据具体应用需求)
|
||||
// MillimeterWaveRadarUartInit();
|
||||
// MillimeterWaveRadarGpioInit();
|
||||
StepperMotorInit();
|
||||
|
||||
|
||||
|
||||
ESP_LOGI(HW_INIT_TAG, "Unified hardware initialization completed successfully");
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 进入低功耗模式
|
||||
*
|
||||
* 根据指定的功耗模式,执行相应的功耗优化策略:
|
||||
* - IDLE模式:关闭非必要外设,保持快速响应
|
||||
* - LIGHT_SLEEP模式:进入轻度睡眠,CPU暂停,外设断电
|
||||
* - DEEP_SLEEP模式:深度睡眠,仅RTC运行,功耗最低
|
||||
*/
|
||||
esp_err_t BoardSweekar::EnterLowPowerMode(power_mode_t mode) {
|
||||
static const char *POWER_TAG = "POWER_MGMT";
|
||||
esp_err_t ret = ESP_OK;
|
||||
|
||||
ESP_LOGI(POWER_TAG, "Entering power mode: %d", mode);
|
||||
|
||||
if (mode == current_power_mode_) {
|
||||
ESP_LOGW(POWER_TAG, "Already in power mode %d", mode);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
// 保存当前模式,以便恢复
|
||||
power_mode_t previous_mode = current_power_mode_;
|
||||
|
||||
switch (mode) {
|
||||
case POWER_MODE_NORMAL:
|
||||
// 正常模式,不需要特殊处理
|
||||
break;
|
||||
|
||||
case POWER_MODE_IDLE:
|
||||
// 空闲模式:关闭非必要外设
|
||||
ESP_LOGI(POWER_TAG, "Idle mode: disabling non-essential peripherals");
|
||||
|
||||
// 关闭SD卡(如果正在使用,需要先卸载)
|
||||
if (is_sdcard_initialized_) {
|
||||
// 注意:这里只是示例,实际应用中需要确保没有文件操作
|
||||
ESP_LOGW(POWER_TAG, "SD card still active in idle mode");
|
||||
}
|
||||
|
||||
// 关闭显示背光
|
||||
// 关闭非必要GPIO的上拉/下拉
|
||||
// 降低I2C时钟频率
|
||||
break;
|
||||
|
||||
case POWER_MODE_LIGHT_SLEEP:
|
||||
// 轻度睡眠
|
||||
ESP_LOGI(POWER_TAG, "Light sleep mode: preparing for sleep");
|
||||
|
||||
// 设置唤醒源(需要根据具体需求配置)
|
||||
// esp_sleep_enable_timer_wakeup(1000000); // 1秒后唤醒
|
||||
// esp_sleep_enable_ext0_wakeup(GPIO_NUM_XX, 0); // 外部中断唤醒
|
||||
|
||||
// 进入轻度睡眠
|
||||
// ret = esp_light_sleep_start();
|
||||
if (ret != ESP_OK) {
|
||||
ESP_LOGE(POWER_TAG, "Failed to enter light sleep: %s", esp_err_to_name(ret));
|
||||
current_power_mode_ = previous_mode;
|
||||
return ret;
|
||||
}
|
||||
break;
|
||||
|
||||
case POWER_MODE_DEEP_SLEEP:
|
||||
// 深度睡眠
|
||||
ESP_LOGI(POWER_TAG, "Deep sleep mode: system will restart after wake-up");
|
||||
|
||||
// 保存必要的RTC数据
|
||||
// rtc_gpio_isolate(GPIO_NUM_XX); // 隔离GPIO
|
||||
|
||||
// 设置深度睡眠唤醒源
|
||||
// esp_sleep_enable_timer_wakeup(60000000); // 60秒后唤醒
|
||||
|
||||
// 进入深度睡眠
|
||||
// esp_deep_sleep_start();
|
||||
// 注意:深度睡眠后系统会重启,不会返回
|
||||
break;
|
||||
|
||||
default:
|
||||
ESP_LOGE(POWER_TAG, "Invalid power mode: %d", mode);
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
current_power_mode_ = mode;
|
||||
ESP_LOGI(POWER_TAG, "Successfully entered power mode: %d", mode);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 退出低功耗模式
|
||||
*
|
||||
* 从低功耗模式恢复到正常运行模式,重新初始化必要的硬件资源。
|
||||
*/
|
||||
esp_err_t BoardSweekar::ExitLowPowerMode(void) {
|
||||
static const char *POWER_TAG = "POWER_MGMT";
|
||||
|
||||
ESP_LOGI(POWER_TAG, "Exiting low power mode");
|
||||
|
||||
if (current_power_mode_ == POWER_MODE_NORMAL) {
|
||||
ESP_LOGW(POWER_TAG, "Already in normal mode");
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
// 根据之前的功耗模式执行相应的恢复操作
|
||||
switch (current_power_mode_) {
|
||||
case POWER_MODE_IDLE:
|
||||
// 恢复空闲模式
|
||||
ESP_LOGI(POWER_TAG, "Restoring from idle mode");
|
||||
|
||||
// 重新初始化必要的外设
|
||||
// 恢复I2C时钟频率
|
||||
// 重新开启显示背光
|
||||
break;
|
||||
|
||||
case POWER_MODE_LIGHT_SLEEP:
|
||||
// 轻度睡眠唤醒后会自动继续执行
|
||||
ESP_LOGI(POWER_TAG, "Woken up from light sleep");
|
||||
|
||||
// 重新配置时钟(如果需要)
|
||||
// 重新初始化外设
|
||||
break;
|
||||
|
||||
case POWER_MODE_DEEP_SLEEP:
|
||||
// 深度睡眠后系统会重启,不会执行到这里
|
||||
ESP_LOGW(POWER_TAG, "Deep sleep recovery should not reach here");
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// 恢复到正常模式
|
||||
current_power_mode_ = POWER_MODE_NORMAL;
|
||||
ESP_LOGI(POWER_TAG, "Successfully exited low power mode");
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 设置硬件模块电源状态
|
||||
*
|
||||
* 提供精细化的电源管理,可以单独控制各个硬件模块的电源状态。
|
||||
*/
|
||||
esp_err_t BoardSweekar::SetModulePower(hardware_module_t module, bool enable) {
|
||||
static const char *POWER_TAG = "POWER_MODULE";
|
||||
esp_err_t ret = ESP_OK;
|
||||
|
||||
ESP_LOGI(POWER_TAG, "%s module %d", enable ? "Enabling" : "Disabling", module);
|
||||
|
||||
// 更新电源状态位图
|
||||
if (enable) {
|
||||
power_state_flags_ |= (1 << module);
|
||||
} else {
|
||||
power_state_flags_ &= ~(1 << module);
|
||||
}
|
||||
|
||||
switch (module) {
|
||||
case HW_MODULE_I2C:
|
||||
if (!enable && bus_handle_) {
|
||||
// 注意:I2C总线通常不建议完全关闭,可能影响多个设备
|
||||
ESP_LOGW(POWER_TAG, "I2C bus power control not recommended");
|
||||
}
|
||||
break;
|
||||
|
||||
case HW_MODULE_SDCARD:
|
||||
if (enable && !is_sdcard_initialized_) {
|
||||
ret = InitializeSdcard();
|
||||
} else if (!enable && is_sdcard_initialized_) {
|
||||
// 卸载SD卡文件系统
|
||||
// 注意:需要确保没有打开的文件
|
||||
ESP_LOGW(POWER_TAG, "SD card power down requires file system cleanup");
|
||||
}
|
||||
break;
|
||||
|
||||
case HW_MODULE_LCD:
|
||||
// LCD背光控制
|
||||
// LCD电源引脚控制(如果有)
|
||||
break;
|
||||
|
||||
case HW_MODULE_AUDIO:
|
||||
// 音频编解码器电源控制
|
||||
// 需要与AudioPlayer协调
|
||||
break;
|
||||
|
||||
case HW_MODULE_MOTOR:
|
||||
// 步进电机驱动器电源控制
|
||||
// 电机睡眠模式
|
||||
break;
|
||||
|
||||
case HW_MODULE_GYROSCOPE:
|
||||
// 陀螺仪电源控制
|
||||
// 设置陀螺仪为低功耗模式
|
||||
break;
|
||||
|
||||
case HW_MODULE_TOUCH:
|
||||
// 触摸传感器电源控制
|
||||
// 设置触摸传感器为睡眠模式
|
||||
break;
|
||||
|
||||
case HW_MODULE_RADAR:
|
||||
// 毫米波雷达电源控制
|
||||
// 设置雷达为低功耗模式
|
||||
break;
|
||||
|
||||
case HW_MODULE_IO_EXPAND:
|
||||
// IO扩展板电源控制
|
||||
// 设置扩展板为低功耗模式
|
||||
break;
|
||||
|
||||
default:
|
||||
ESP_LOGE(POWER_TAG, "Unknown hardware module: %d", module);
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
if (ret == ESP_OK) {
|
||||
ESP_LOGI(POWER_TAG, "Module %d power %s successfully", module, enable ? "enabled" : "disabled");
|
||||
} else {
|
||||
ESP_LOGE(POWER_TAG, "Failed to %s module %d: %s", enable ? "enable" : "disable", module, esp_err_to_name(ret));
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,174 @@
|
||||
#ifndef __BOARD_H__
|
||||
#define __BOARD_H__
|
||||
#include "config.h"
|
||||
#include "io_expansion_board.h"
|
||||
// #include "stepper_motor.h" // !
|
||||
#include "stepper_driver.h"
|
||||
#include "i2c_bus.h"
|
||||
#include "gyroscope.h"
|
||||
// #include "touch_sensor.h" // !
|
||||
#include "base_board_control.h"
|
||||
#include "esp_peripherals.h"
|
||||
#include "periph_sdcard.h"
|
||||
#include "esp_sleep.h"
|
||||
#include "driver/rtc_io.h"
|
||||
|
||||
/**
|
||||
* @brief 功耗模式枚举
|
||||
*/
|
||||
typedef enum {
|
||||
POWER_MODE_NORMAL, // 正常运行模式,所有硬件可用
|
||||
POWER_MODE_IDLE, // 空闲模式,关闭非必要外设
|
||||
POWER_MODE_LIGHT_SLEEP, // 轻度睡眠,快速唤醒
|
||||
POWER_MODE_DEEP_SLEEP, // 深度睡眠,仅RTC运行
|
||||
} power_mode_t;
|
||||
|
||||
/**
|
||||
* @brief 硬件模块枚举,用于精细化电源管理
|
||||
*/
|
||||
typedef enum {
|
||||
HW_MODULE_I2C, // I2C总线
|
||||
HW_MODULE_SDCARD, // SD卡
|
||||
HW_MODULE_LCD, // LCD显示
|
||||
HW_MODULE_AUDIO, // 音频编解码器
|
||||
HW_MODULE_MOTOR, // 步进电机
|
||||
HW_MODULE_GYROSCOPE, // 陀螺仪
|
||||
HW_MODULE_TOUCH, // 触摸传感器
|
||||
HW_MODULE_RADAR, // 毫米波雷达
|
||||
HW_MODULE_IO_EXPAND, // IO扩展板
|
||||
} hardware_module_t;
|
||||
|
||||
/**
|
||||
* @brief 硬件板级管理器
|
||||
*
|
||||
* 采用高内聚低耦合设计原则,统一管理所有硬件资源。
|
||||
* 提供统一的硬件初始化接口和资源访问,避免各模块重复初始化。
|
||||
*/
|
||||
class BoardSweekar
|
||||
{
|
||||
private:
|
||||
i2c_bus_handle_t bus_handle_ = nullptr; // 使用ESP-ADF的I2C总线句柄
|
||||
esp_periph_set_handle_t periph_set_ = nullptr; // 外设管理句柄
|
||||
bool is_sdcard_initialized_ = false; // SD卡初始化状态
|
||||
power_mode_t current_power_mode_ = POWER_MODE_NORMAL; // 当前功耗模式
|
||||
uint32_t power_state_flags_ = 0xFFFFFFFF; // 各模块电源状态位图(1为开启)
|
||||
|
||||
public:
|
||||
BoardSweekar();
|
||||
~BoardSweekar();
|
||||
|
||||
IOExpansionBoard io_expansion_; // IO扩展板对象
|
||||
Gyroscope gyroscope_; // 陀螺仪对象
|
||||
// TouchSensor touch_sensor_; // 触摸传感器对象 //!
|
||||
BaseBoardControl base_board_control_; // 底座控制对象
|
||||
StepperDriver* stepper_driver_ = nullptr; // 步进电机驱动对象
|
||||
|
||||
StepperDriver* GetStepperDriver() const { return stepper_driver_; }
|
||||
|
||||
// 初始化步进电机
|
||||
void StepperMotorInit(void);
|
||||
|
||||
// 初始化LCD IO引脚(消除与步进电机的耦合)
|
||||
void LcdIoInit(void);
|
||||
|
||||
// 初始化串口
|
||||
void MillimeterWaveRadarUartInit(void);
|
||||
|
||||
//初始化毫米波雷达的中断引脚
|
||||
void MillimeterWaveRadarGpioInit(void);
|
||||
|
||||
// 初始化I2C总线
|
||||
esp_err_t I2CMasterInit(void);
|
||||
|
||||
// 初始化VBAT toVBAT_5V引脚
|
||||
void VbatToVbat5vInit(void);
|
||||
|
||||
// 初始化底座控制串口
|
||||
void BaseBoardControlInit(void);
|
||||
|
||||
// 初始化SD卡(推荐使用统一的硬件初始化)
|
||||
esp_err_t InitializeSdcard(void);
|
||||
|
||||
// 获取SD卡初始化状态
|
||||
bool IsSdcardInitialized() const { return is_sdcard_initialized_; }
|
||||
|
||||
// 获取外设管理句柄(供需要访问SD卡的模块使用)
|
||||
esp_periph_set_handle_t GetPeriphSet() const { return periph_set_; }
|
||||
|
||||
// 获取I2C总线句柄
|
||||
i2c_bus_handle_t GetBusHandle() const { return bus_handle_; }
|
||||
|
||||
/**
|
||||
* @brief 统一的硬件初始化接口
|
||||
*
|
||||
* 按照依赖关系顺序初始化所有硬件资源,确保各模块可以安全使用。
|
||||
* 推荐在主程序启动时调用此函数,而不是分别调用各个初始化函数。
|
||||
*
|
||||
* @return esp_err_t 初始化结果,ESP_OK表示全部成功
|
||||
*/
|
||||
esp_err_t InitializeAllHardware(void);
|
||||
|
||||
/**
|
||||
* @brief 完整的统一硬件初始化接口(专为复杂应用优化)
|
||||
*
|
||||
* 包含所有必要外设的完整初始化,适用于demo5等复杂应用场景。
|
||||
* 这个函数会初始化:I2C总线、IO扩展板、SD卡、LCD IO、底座控制等。
|
||||
*
|
||||
* @return esp_err_t 初始化结果,ESP_OK表示全部成功
|
||||
*/
|
||||
esp_err_t InitializeAllHardwareComplete(void);
|
||||
|
||||
/**
|
||||
* @brief 针对特定应用的硬件初始化配置
|
||||
*
|
||||
* 为不同类型的应用提供专门的初始化配置,优化启动流程。
|
||||
*
|
||||
* @param app_type 应用类型(demo5、音频播放器、显示应用等)
|
||||
* @return esp_err_t 初始化结果,ESP_OK表示全部成功
|
||||
*/
|
||||
esp_err_t InitializeHardwareForApplication(int app_type);
|
||||
|
||||
/**
|
||||
* @brief 功耗管理接口 - 进入低功耗模式
|
||||
*
|
||||
* 根据指定的功耗模式,关闭非必要硬件、设置GPIO为低功耗状态、
|
||||
* 调整时钟频率等。支持多种功耗模式以适应不同应用场景。
|
||||
*
|
||||
* @param mode 功耗模式
|
||||
* @return esp_err_t 操作结果
|
||||
*/
|
||||
esp_err_t EnterLowPowerMode(power_mode_t mode);
|
||||
|
||||
/**
|
||||
* @brief 功耗管理接口 - 退出低功耗模式
|
||||
*
|
||||
* 从低功耗模式恢复,重新初始化必要的硬件资源。
|
||||
*
|
||||
* @return esp_err_t 操作结果
|
||||
*/
|
||||
esp_err_t ExitLowPowerMode(void);
|
||||
|
||||
/**
|
||||
* @brief 获取当前功耗模式
|
||||
*
|
||||
* @return power_mode_t 当前功耗模式
|
||||
*/
|
||||
power_mode_t GetPowerMode(void) const { return current_power_mode_; }
|
||||
|
||||
/**
|
||||
* @brief 设置硬件模块电源状态
|
||||
*
|
||||
* 单独控制某个硬件模块的电源状态,用于精细化的功耗管理。
|
||||
*
|
||||
* @param module 硬件模块
|
||||
* @param enable true为开启,false为关闭
|
||||
* @return esp_err_t 操作结果
|
||||
*/
|
||||
esp_err_t SetModulePower(hardware_module_t module, bool enable);
|
||||
|
||||
/**
|
||||
* @brief 执行系统关机(拉高 SHUTDOWN_CTRL_PIN)
|
||||
*/
|
||||
void SystemShutdown(void);
|
||||
};
|
||||
#endif
|
||||
@@ -0,0 +1,186 @@
|
||||
/**
|
||||
* @file board_sweekar_complete_init.cc
|
||||
* @brief 完整的统一硬件初始化实现
|
||||
*
|
||||
* 这个文件提供了完整的统一硬件初始化函数,包含所有必要的硬件初始化步骤。
|
||||
* 专为demo5等复杂应用场景设计。
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief 完整的统一硬件初始化接口(专为demo5优化)
|
||||
*
|
||||
* 按照依赖关系顺序初始化所有硬件资源:
|
||||
* 1. I2C总线(最基础,其他设备依赖)
|
||||
* 2. IO扩展板(控制其他外设)
|
||||
* 3. SD卡(文件系统,供显示和音频使用)
|
||||
* 4. LCD IO引脚(显示相关)
|
||||
* 5. 底座控制串口(通信)
|
||||
* 6. 底座控制模块(业务逻辑)
|
||||
* 7. 其他外设(根据应用需求)
|
||||
*
|
||||
* @return esp_err_t 初始化结果,ESP_OK表示全部成功
|
||||
*/
|
||||
esp_err_t BoardSweekar::InitializeAllHardwareComplete(void)
|
||||
{
|
||||
static const char *HW_INIT_TAG = "HW_INIT_COMPLETE";
|
||||
esp_err_t ret;
|
||||
|
||||
ESP_LOGI(HW_INIT_TAG, "Starting complete hardware initialization...");
|
||||
|
||||
// 1. 初始化I2C总线(最基础,其他设备依赖)
|
||||
ret = I2CMasterInit();
|
||||
if (ret != ESP_OK) {
|
||||
ESP_LOGE(HW_INIT_TAG, "Failed to initialize I2C master: %s", esp_err_to_name(ret));
|
||||
return ret;
|
||||
}
|
||||
ESP_LOGI(HW_INIT_TAG, "✓ I2C master initialized");
|
||||
|
||||
// 2. 创建I2C读任务(IO扩展板需要)
|
||||
io_expansion_.CreateI2cReadTask();
|
||||
ESP_LOGI(HW_INIT_TAG, "✓ I2C read task created");
|
||||
|
||||
// 3. 初始化SD卡(文件系统,供显示和音频使用)
|
||||
ret = InitializeSdcard();
|
||||
if (ret != ESP_OK) {
|
||||
ESP_LOGE(HW_INIT_TAG, "Failed to initialize SD card: %s", esp_err_to_name(ret));
|
||||
// SD卡失败不是致命错误,继续初始化其他硬件
|
||||
ESP_LOGW(HW_INIT_TAG, "⚠ SD card initialization failed, but continuing with other hardware");
|
||||
} else {
|
||||
ESP_LOGI(HW_INIT_TAG, "✓ SD card initialized");
|
||||
}
|
||||
|
||||
// 4. 初始化LCD IO引脚(显示相关)
|
||||
LcdIoInit();
|
||||
ESP_LOGI(HW_INIT_TAG, "✓ LCD IO pins initialized");
|
||||
|
||||
// 5. 初始化底座控制串口(demo5需要)
|
||||
BaseBoardControlUartInit();
|
||||
ESP_LOGI(HW_INIT_TAG, "✓ Base board control UART initialized");
|
||||
|
||||
// 6. 初始化底座控制模块
|
||||
base_board_control_.Init();
|
||||
ESP_LOGI(HW_INIT_TAG, "✓ Base board control initialized");
|
||||
|
||||
// 7. 设置IO扩展板的PA控制模式(demo5需要)
|
||||
io_expansion_.SetPaCtrlMode(true);
|
||||
ESP_LOGI(HW_INIT_TAG, "✓ IO expansion PA control mode set");
|
||||
|
||||
// 8. 可选外设(根据具体应用需求启用)
|
||||
// ESP_LOGI(HW_INIT_TAG, "Initializing optional peripherals...");
|
||||
//
|
||||
// // 毫米波雷达(如需要)
|
||||
// MillimeterWaveRadarUartInit();
|
||||
// MillimeterWaveRadarGpioInit();
|
||||
// ESP_LOGI(HW_INIT_TAG, "✓ Millimeter wave radar initialized");
|
||||
//
|
||||
// // VBAT升压(如需要)
|
||||
// VbatToVbat5vInit();
|
||||
// ESP_LOGI(HW_INIT_TAG, "✓ VBAT to 5V booster initialized");
|
||||
//
|
||||
// // 步进电机(如需要)
|
||||
// StepperMotorInit();
|
||||
// ESP_LOGI(HW_INIT_TAG, "✓ Stepper motor initialized");
|
||||
|
||||
ESP_LOGI(HW_INIT_TAG, "=== Complete hardware initialization finished successfully ===");
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 针对特定应用的硬件初始化配置
|
||||
*
|
||||
* 为不同类型的应用提供专门的初始化配置
|
||||
*/
|
||||
esp_err_t BoardSweekar::InitializeHardwareForApplication(application_type_t app_type) {
|
||||
static const char *APP_INIT_TAG = "APP_HW_INIT";
|
||||
|
||||
ESP_LOGI(APP_INIT_TAG, "Initializing hardware for application type: %d", app_type);
|
||||
|
||||
// 基础硬件初始化(所有应用都需要)
|
||||
esp_err_t ret = InitializeAllHardwareComplete();
|
||||
if (ret != ESP_OK) {
|
||||
ESP_LOGE(APP_INIT_TAG, "Basic hardware initialization failed");
|
||||
return ret;
|
||||
}
|
||||
|
||||
switch (app_type) {
|
||||
case APP_TYPE_DEMO5: // 宠物游戏demo
|
||||
ESP_LOGI(APP_INIT_TAG, "Configuring for Demo5 (Pet Game)...");
|
||||
|
||||
// Demo5需要的额外初始化
|
||||
// 触摸传感器、陀螺仪、RGB LED等会在应用层初始化
|
||||
|
||||
ESP_LOGI(APP_INIT_TAG, "✓ Demo5 hardware configuration complete");
|
||||
break;
|
||||
|
||||
case APP_TYPE_AUDIO_PLAYER: // 音频播放器
|
||||
ESP_LOGI(APP_INIT_TAG, "Configuring for Audio Player...");
|
||||
|
||||
// 音频应用需要确保音频编解码器正确初始化
|
||||
// 这部分通常在AudioPlayer类中处理
|
||||
|
||||
ESP_LOGI(APP_INIT_TAG, "✓ Audio player hardware configuration complete");
|
||||
break;
|
||||
|
||||
case APP_TYPE_DISPLAY_ONLY: // 纯显示应用
|
||||
ESP_LOGI(APP_INIT_TAG, "Configuring for Display Only...");
|
||||
|
||||
// 显示应用需要确保LCD相关硬件正确配置
|
||||
// 这部分通常在Display类中处理
|
||||
|
||||
ESP_LOGI(APP_INIT_TAG, "✓ Display-only hardware configuration complete");
|
||||
break;
|
||||
|
||||
case APP_TYPE_MINIMAL: // 最小化应用
|
||||
ESP_LOGI(APP_INIT_TAG, "Configuring for Minimal Application...");
|
||||
|
||||
// 最小化配置,只保留最基本的功能
|
||||
// 关闭非必要外设以节省功耗
|
||||
|
||||
ESP_LOGI(APP_INIT_TAG, "✓ Minimal hardware configuration complete");
|
||||
break;
|
||||
|
||||
default:
|
||||
ESP_LOGW(APP_INIT_TAG, "Unknown application type, using default configuration");
|
||||
break;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 硬件初始化状态报告
|
||||
*
|
||||
* 提供详细的硬件初始化状态报告,便于调试和问题排查
|
||||
*/
|
||||
void BoardSweekar::ReportHardwareStatus(void) {
|
||||
static const char *STATUS_TAG = "HW_STATUS";
|
||||
|
||||
ESP_LOGI(STATUS_TAG, "=== Hardware Initialization Status Report ===");
|
||||
|
||||
// I2C总线状态
|
||||
ESP_LOGI(STATUS_TAG, "I2C Bus: %s", (bus_handle_ != nullptr) ? "✓ Initialized" : "✗ Not initialized");
|
||||
|
||||
// SD卡状态
|
||||
ESP_LOGI(STATUS_TAG, "SD Card: %s", (is_sdcard_initialized_) ? "✓ Initialized" : "✗ Not initialized");
|
||||
if (is_sdcard_initialized_) {
|
||||
ESP_LOGI(STATUS_TAG, " Peripheral Set: %s", (periph_set_ != nullptr) ? "✓ Available" : "✗ Not available");
|
||||
}
|
||||
|
||||
// IO扩展板状态
|
||||
ESP_LOGI(STATUS_TAG, "IO Expansion Board: %s", (io_expansion_.bus_handle_ != nullptr) ? "✓ Configured" : "✗ Not configured");
|
||||
|
||||
// 底座控制状态
|
||||
ESP_LOGI(STATUS_TAG, "Base Board Control: %s", (base_board_control_.GetUartPort() != 0) ? "✓ Initialized" : "✗ Not initialized");
|
||||
|
||||
// 功耗管理状态
|
||||
ESP_LOGI(STATUS_TAG, "Power Management: %s", (current_power_mode_ == POWER_MODE_NORMAL) ? "✓ Normal mode" : "⚠ Low power mode");
|
||||
ESP_LOGI(STATUS_TAG, " Current Mode: %d", current_power_mode_);
|
||||
ESP_LOGI(STATUS_TAG, " Module Power States: 0x%08X", power_state_flags_);
|
||||
|
||||
// 内存状态
|
||||
ESP_LOGI(STATUS_TAG, "Memory Status:");
|
||||
ESP_LOGI(STATUS_TAG, " Internal RAM Free: %d bytes", heap_caps_get_free_size(MALLOC_CAP_INTERNAL));
|
||||
ESP_LOGI(STATUS_TAG, " PSRAM Free: %d bytes", heap_caps_get_free_size(MALLOC_CAP_SPIRAM));
|
||||
|
||||
ESP_LOGI(STATUS_TAG, "=== End of Hardware Status Report ===");
|
||||
}
|
||||
@@ -0,0 +1,138 @@
|
||||
/* 定义引脚分配 */
|
||||
#ifndef _BOARD_CONFIG_H_
|
||||
#define _BOARD_CONFIG_H_
|
||||
|
||||
/**
|
||||
* @file config.h
|
||||
* @brief 定义了引脚的分配。
|
||||
* @author zouyuhua
|
||||
* @date 2025年8月7日
|
||||
*
|
||||
*/
|
||||
|
||||
#include "driver/gpio.h"
|
||||
#include "driver/i2c_master.h"
|
||||
#include "driver/i2s.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_rom_sys.h" // 用于 esp_rom_delay_us
|
||||
#include "esp_timer.h"
|
||||
#include "esp_mac.h"
|
||||
#include "driver/ledc.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "esp_log.h"
|
||||
#include "driver/timer.h"
|
||||
#include "esp_intr_alloc.h"
|
||||
#include "soc/timer_group_struct.h" // 包含TIMERG0、TIMERG1的结构体定义
|
||||
#include "soc/timer_group_reg.h" // 包含定时器相关寄存器宏定义
|
||||
#include "driver/uart.h"
|
||||
#include "esp_err.h"
|
||||
#include "freertos/queue.h"
|
||||
#include "soc/uart_reg.h"
|
||||
// #include "linear_motor.h"
|
||||
#include "gyroscope.h"
|
||||
|
||||
#define TAG_BOARD "SWEEKAR_ESP32"
|
||||
/*I2C总线引脚定义*/
|
||||
#define I2C0_MASTER_PORT I2C_NUM_0
|
||||
#define I2C0_MASTER_SDA_IO GPIO_NUM_2
|
||||
#define I2C0_MASTER_SCL_IO GPIO_NUM_3
|
||||
|
||||
/* 步进电机配置 */
|
||||
#define STEPPER_STEP_IO GPIO_NUM_42 // 步进电机脉冲输入引脚
|
||||
#define STEPPER_TIMER_RES_HZ 1000000 // 步进电机定时器分辨率 1 MHz(1 us 步进)
|
||||
|
||||
/* 定义屏幕驱动控制引脚 */
|
||||
#define ST7789_PIN_CLK GPIO_NUM_48 // SPI时钟引脚
|
||||
#define ST7789_PIN_DC GPIO_NUM_38 // 数据/命令选择引脚RSEL
|
||||
#define ST7789_PIN_MOSI GPIO_NUM_47 // SPI数据输出引脚
|
||||
#define ST7789_PIN_CS GPIO_NUM_46 // SPI片选引脚
|
||||
#define ST7789_PIN_BL GPIO_NUM_45 // 背光引脚
|
||||
#define ST7789_PIN_RST GPIO_NUM_NC // 复位引脚
|
||||
#define LCD_BL_ACTIVE_LEVEL 1 // 背光有效电平:1=高电平有效(NMOS),0=低电平有效(PMOS)
|
||||
|
||||
#define LCD_WIDTH 172 // 屏幕宽度(水平方向像素数)
|
||||
#define LCD_HEIGHT 320 // 屏幕高度(垂直方向像素数)
|
||||
|
||||
/* 毫米波雷达配置参数 */
|
||||
/* 定义毫米波雷达的中断引脚 */
|
||||
#define MILLIMETER_WAVE_RADAR_PIN GPIO_NUM_35
|
||||
// UART 配置参数
|
||||
#define RADAR_UART_NUM UART_NUM_1 // 使用 UART1
|
||||
#define UART_TX_PIN GPIO_NUM_40 // GPIO40 作为 TX(根据实际硬件连接调整)
|
||||
#define UART_RX_PIN GPIO_NUM_39 // GPIO39 作为 RX
|
||||
#define RADAR_BAUD_RATE 9600 // 雷达波特率
|
||||
#define RADAR_BUF_SIZE 100 // 雷达接收缓冲区大小
|
||||
|
||||
/* IO扩展硬件配置常量 */
|
||||
#define I2C_MASTER_FREQ_HZ 100000 // I2C通信频率(100kHz)(可更改至400000)
|
||||
#define I2C_IO_EXPAND_SLAVE_ADDR 0x58 // AW9523BTQR器件地址,v1_1_13的addr1和addr0是0
|
||||
#define GPIO_INPUT_PIN_SEL GPIO_NUM_10 // 中断检测引脚
|
||||
#define ESP_INTR_FLAG_DEFAULT 0 // 中断标志默认值
|
||||
#define IO_EXPAND_RSTN GPIO_NUM_14 // IO扩展板复位引脚
|
||||
|
||||
/* 定义线性马达的I2C从机配置常量 */
|
||||
#define LINEAR_MOTOR_I2C_SLAVE_ADDR 0x5A // 线性马达的I2C从机地址
|
||||
|
||||
/* 定义陀螺仪的I2C从机配置常量 */
|
||||
#define GYROSCOPE_I2C_SLAVE_ADDR 0x6A // 陀螺仪的I2C从机地址
|
||||
#define GYROSCOPE_INPUT_PIN_SEL GPIO_NUM_21 // 陀螺仪中断引脚
|
||||
|
||||
/* AW触摸芯片配置 */
|
||||
#define AW_TOUCH_IRQ_PIN GPIO_NUM_11 // AW触摸芯片中断引脚
|
||||
#define NFC_RST_PIN GPIO_NUM_12 // NFC复位引脚
|
||||
#define SHUTDOWN_CTRL_PIN GPIO_NUM_13 // 关机控制引脚
|
||||
|
||||
/* 原生触摸引脚配置 (v1.1.16已改为上述功能,保留定义需谨慎) */
|
||||
// 触摸按键数量配置
|
||||
#define TOUCH_BUTTON_NUM 3
|
||||
// 触摸通道定义 - 注意:v1.1.16如果不使用ESP32原生触摸,这些定义可能不再适用
|
||||
// 但为了兼容编译,可以保留或注释
|
||||
#define TOUCH_PAD_CHANNEL_1 TOUCH_PAD_NUM11 // GPIO11 (Now AW_IRQ)
|
||||
#define TOUCH_PAD_CHANNEL_2 TOUCH_PAD_NUM12 // GPIO12 (Now NFC_RST)
|
||||
#define TOUCH_PAD_CHANNEL_3 TOUCH_PAD_NUM13 // GPIO13 (Now SHUTDOWN)
|
||||
|
||||
/* ES8311音频编解码器配置 (ESP-ADF兼容) */
|
||||
#define AUDIO_INPUT_SAMPLE_RATE 24000
|
||||
#define AUDIO_OUTPUT_SAMPLE_RATE 24000
|
||||
#define AUDIO_INPUT_REFERENCE true
|
||||
|
||||
/* I2S GPIO定义 */
|
||||
#define AUDIO_I2S_GPIO_MCLK GPIO_NUM_15
|
||||
#define AUDIO_I2S_GPIO_WS GPIO_NUM_4
|
||||
#define AUDIO_I2S_GPIO_BCLK GPIO_NUM_5
|
||||
#define AUDIO_I2S_GPIO_DIN GPIO_NUM_6
|
||||
#define AUDIO_I2S_GPIO_DOUT GPIO_NUM_7
|
||||
|
||||
/* PA引脚定义 */
|
||||
#define AUDIO_CODEC_PA_PIN GPIO_NUM_NC
|
||||
|
||||
/* I2C配置 */
|
||||
#define AUDIO_CODEC_I2C_SDA_PIN GPIO_NUM_2
|
||||
#define AUDIO_CODEC_I2C_SCL_PIN GPIO_NUM_3
|
||||
#define AUDIO_CODEC_ES8311_ADDR 0x18
|
||||
#define AUDIO_CODEC_ES7210_ADDR 0x40
|
||||
|
||||
/* WS2812 RGB LED配置 */
|
||||
#define WS2812_PIN GPIO_NUM_41 // WS2812数据引脚
|
||||
#define WS2812_NUM_LEDS 2 // WS2812 LED数量
|
||||
|
||||
/* 创建VBAT to VBAT_5V */
|
||||
#define VBAT_5V_PIN GPIO_NUM_NC // VBAT_5V引脚
|
||||
|
||||
/* 定义按键的中断引脚 */
|
||||
#define BUTTON_PIN GPIO_NUM_0 // 按键中断引脚
|
||||
#define RIGHT_BUTTON_PIN GPIO_NUM_8 // 按键中断引脚
|
||||
|
||||
/* 底座控制命令串口配置 */
|
||||
#define BASE_BOARD_CTL_UART_PORT UART_NUM_0
|
||||
#define BASE_BOARD_CTL_UART_TX_PIN GPIO_NUM_43
|
||||
#define BASE_BOARD_CTL_UART_RX_PIN GPIO_NUM_44
|
||||
#define BASE_BOARD_CTL_UART_BAUDRATE 115200
|
||||
#define BASE_BOARD_CTL_UART_BUF_SIZE 256
|
||||
|
||||
/* 背光控制引脚配置 */
|
||||
#define BL_PIN GPIO_NUM_45
|
||||
|
||||
#endif // _BOARD_CONFIG_H_
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,432 @@
|
||||
#ifndef IO_EXPANSION_BOARD_H
|
||||
#define IO_EXPANSION_BOARD_H
|
||||
|
||||
#include <cstdint>
|
||||
#include <esp_log.h>
|
||||
#include <esp_check.h>
|
||||
#include <esp_timer.h>
|
||||
#include <driver/gpio.h>
|
||||
#include <functional>
|
||||
#include "i2c_bus.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/event_groups.h"
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
#include <freertos/FreeRTOS.h>
|
||||
#include <freertos/task.h>
|
||||
#include <freertos/queue.h>
|
||||
#include <freertos/semphr.h>
|
||||
#include "esp_err.h"
|
||||
#include "config.h"
|
||||
#include "portmacro.h"
|
||||
|
||||
// 前向声明,避免循环引用
|
||||
class MillimeterWaveRadar;
|
||||
class PhotoInterrupter;
|
||||
class AdcBatteryMonitor;
|
||||
|
||||
// 回调函数类型定义
|
||||
typedef std::function<void()> RadarCallback;
|
||||
typedef std::function<void()> PhotoInterrupterStartCallback;
|
||||
typedef std::function<void()> PhotoInterrupterEndCallback;
|
||||
typedef std::function<void()> BatteryChargingCallback;
|
||||
typedef std::function<void()> BatteryFullCallback;
|
||||
typedef std::function<void()> BatteryNotChargingCallback;
|
||||
|
||||
/* 寄存器地址 */
|
||||
#define INPUT_PORT0 0x00 // 输入端口0寄存器
|
||||
#define INPUT_PORT1 0x01 // 输入端口1寄存器 0为低电平(仅支持读取)
|
||||
#define OUTPUT_PORT0 0x02 // 输出端口0寄存器
|
||||
#define OUTPUT_PORT1 0x03 // 输出端口1寄存器 0为低电平
|
||||
#define CONFIG_PORT0 0x04 // 配置端口0寄存器
|
||||
#define CONFIG_PORT1 0x05 // 配置端口1寄存器 0为输出模式
|
||||
#define INT_PORT0 0x06 // 中断端口0寄存器
|
||||
#define INT_PORT1 0x07 // 中断端口1寄存器 0为使能中断(根据手册默认是使能的)
|
||||
#define CTL 0x11 // 全局控制寄存器
|
||||
#define ID 0x23 // 芯片ID寄存器(0x23)
|
||||
|
||||
/***********************************IO扩展板电机引脚配置参数*************************************/
|
||||
/* 设置步进电机方向 */
|
||||
#define STEPPER_MOTOR_LEFT false //步进电机的方向为左转
|
||||
#define STEPPER_MOTOR_RIGHT true //步进电机的方向为右转
|
||||
#define STEPPER_MOTOR_DIR_PORT OUTPUT_PORT0 //步进电机方向引脚挂载在IO扩展板的输出端口OUTPUT_PORT0
|
||||
#define STEPPER_MOTOR_DIR_PIN 4 //步进电机方向引脚对应的IO扩展板引脚P0_4
|
||||
#define STEPPER_MOTOR_DIR_CONFIG CONFIG_PORT0 //步进电机方向引脚配置在P0_4
|
||||
|
||||
/* 设置步进电机细分模式 */
|
||||
#define STEPPER_MOTOR_M0_PIN 5 //步进电机细分模式选择引脚对应IO扩展板引脚P1_5
|
||||
#define STEPPER_MOTOR_M0_MADE_PORT OUTPUT_PORT1 //步进电机模式选择引脚挂载在IO扩展板的输出端口OUTPUT_PORT1
|
||||
#define STEPPER_MOTOR_M0_CONFIG CONFIG_PORT1 //步进电机细分模式选择引脚配置在P1_5
|
||||
|
||||
#define STEPPER_MOTOR_M1_PIN 4 //步进电机细分模式选择引脚对应IO扩展板引脚P1_4
|
||||
#define STEPPER_MOTOR_M1_MADE_PORT OUTPUT_PORT1 //步进电机模式选择引脚挂载在IO扩展板的输出端口OUTPUT_PORT1
|
||||
#define STEPPER_MOTOR_M1_CONFIG CONFIG_PORT1 //步进电机细分模式选择引脚配置在P1_4
|
||||
|
||||
/* 设置步进电机睡眠引脚 */
|
||||
#define STEPPER_MOTOR_SLEEP false //步进电机进入睡眠模式
|
||||
#define STEPPER_MOTOR_WORK true //步进电机进入工作模式
|
||||
#define STEPPER_MOTOR_SLEEP_PIN 6 //步进电机睡眠引脚对应IO扩展板引脚P1_6
|
||||
#define STEPPER_MOTOR_SLEEP_CONFIG CONFIG_PORT1 //步进电机睡眠引脚配置在P1_6
|
||||
#define STEPPER_MOTOR_SLEEP_PORT OUTPUT_PORT1 //步进电机睡眠引脚挂载在IO扩展板的输出端口OUTPUT_PORT1
|
||||
|
||||
/* 设置电机的使能引脚 */
|
||||
#define STEPPER_MOTOR_ENABLE_PIN 7 //电机使能引脚对应IO扩展板引脚P0_7
|
||||
#define STEPPER_MOTOR_ENABLE_PORT OUTPUT_PORT0 //电机使能引脚挂载在IO扩展板的输出端口OUTPUT_PORT0
|
||||
#define STEPPER_MOTOR_ENABLE_CONFIG CONFIG_PORT0 //电机使能引脚配置在P0_7
|
||||
#define STEPPER_MOTOR_ENABLE_ENABLE true //电机使能引脚状态为高电平
|
||||
#define STEPPER_MOTOR_ENABLE_DISABLE false //电机使能引脚状态为低电平
|
||||
|
||||
/* 设置毫米波雷达对应IO扩展板的中断引脚 */
|
||||
#define RADAR_INTERRUPT_PIN 7 //毫米波雷达中断引脚对应IO扩展板引脚P1_7
|
||||
#define RADAR_INTERRUPT_CONFIG CONFIG_PORT1 //毫米波雷达中断引脚挂载在IO扩展板的输入端口
|
||||
#define RADAR_INTERRUPT_INPUT INPUT_PORT1 //毫米波雷达中断引脚输入状态检测在INPUT_PORT1
|
||||
#define RADAR_INTERRUPT_ENABLE true //毫米波雷达中断引脚状态为输入状态
|
||||
#define RADAR_INTERRUPT_DISABLE false //毫米波雷达中断引脚状态为输出状态
|
||||
/* 任务配置常量 */
|
||||
#define WRITE_BUF_SIZE 2 // I2C单次写入字节数
|
||||
#define READ_BUF_SIZE 2 // I2C单次读取字节数
|
||||
#define I2C_TASK_PRIORITY 2 // 任务优先级(中等)
|
||||
#define I2C_TASK_STACK 4096 // 任务栈大小(4KB)
|
||||
|
||||
// 光学传感器引脚定义
|
||||
#define START_PHOTO_INTERRUPTER_PIN 2 // 光学传感器引脚(P0_2)
|
||||
#define START_PHOTO_INTERRUPTER_CONFIG CONFIG_PORT0 // 光学传感器引脚挂载在IO扩展板的输入端口
|
||||
#define START_PHOTO_INTERRUPTER_INPUT INPUT_PORT0 // 光学传感器引脚输入状态检测在INPUT_PORT0
|
||||
#define START_PHOTO_INTERRUPTER_HIGH true // 光学传感器引脚状态为高电平
|
||||
#define START_PHOTO_INTERRUPTER_LOW false // 光学传感器引脚状态为低电平
|
||||
|
||||
#define END_PHOTO_INTERRUPTER_PIN 3 // 光学传感器引脚(P0_3)
|
||||
#define END_PHOTO_INTERRUPTER_PORT_CONFIG CONFIG_PORT0 // 光学传感器引脚挂载在IO扩展板的输入端口
|
||||
#define END_PHOTO_INTERRUPTER_INPUT INPUT_PORT0 // 光学传感器引脚输入状态检测在INPUT_PORT0
|
||||
#define END_PHOTO_INTERRUPTER_HIGH true // 光学传感器引脚状态为高电平
|
||||
#define END_PHOTO_INTERRUPTER_LOW false // 光学传感器引脚状态为低电平
|
||||
|
||||
/***********************************LED_EN 电源控制(WS2812/背光等)*************************************/
|
||||
// v1.1.16: LED_EN 高电平有效,低电平无效;端口为 IO 扩展 P0_1
|
||||
#define LED_EN_PIN 1
|
||||
#define LED_EN_PORT OUTPUT_PORT0
|
||||
#define LED_EN_CONFIG CONFIG_PORT0
|
||||
|
||||
/***********************************IO扩展板LCD引脚配置参数*************************************/
|
||||
// /* 设置LCD的BL引脚 */
|
||||
// #define LCD_BL_PIN 6 //LCD背光引脚对应IO扩展板引脚P0_6
|
||||
// #define LCD_BL_PORT OUTPUT_PORT0 //LCD背光引脚挂载在IO扩展板的输出端口OUTPUT_PORT0
|
||||
// #define LCD_BL_CONFIG CONFIG_PORT0 //LCD背光引脚配置在P0_6
|
||||
// #define LCD_BL_HIGH true //LCD背光引脚状态为高电平
|
||||
// #define LCD_BL_LOW false //LCD背光引脚状态为低电平
|
||||
|
||||
/* 设置LCD的RST引脚 */
|
||||
#define LCD_RST_PIN 1 //LCD复位引脚对应IO扩展板引脚P1_1
|
||||
#define LCD_RST_CONFIG CONFIG_PORT1 //LCD复位引脚配置在P1_1
|
||||
#define LCD_RST_PORT OUTPUT_PORT1 //LCD复位引脚挂载在IO扩展板的输出端口OUTPUT_PORT1
|
||||
#define LCD_RST_HIGH true //LCD复位引脚状态为高电平
|
||||
#define LCD_RST_LOW false //LCD复位引脚状态为低电平
|
||||
|
||||
/* 设置PA控制引脚 */
|
||||
#define PA_CTRL_PIN 2 //PA控制引脚对应IO扩展板引脚P1_2
|
||||
#define PA_CTRL_CONFIG CONFIG_PORT1 //PA控制引脚配置在P1_2
|
||||
#define PA_CTRL_PORT OUTPUT_PORT1 //PA控制引脚挂载在IO扩展板的输出端口OUTPUT_PORT1
|
||||
#define PA_CTRL_HIGH true //PA控制引脚状态为高电平
|
||||
#define PA_CTRL_LOW false //PA控制引脚状态为低电平
|
||||
|
||||
// 电池充电检测引脚定义
|
||||
#define BATTERY_FULL_INPUT INPUT_PORT1 // 电池充满检测引脚挂载在IO扩展板的输入端口
|
||||
#define BATTERY_FULL_PIN 3 // 电池充满检测引脚对应IO扩展板引脚P1_3
|
||||
#define BATTERY_FULL_CONFIG CONFIG_PORT1 // 电池充满检测引脚配置在P1_3
|
||||
|
||||
#define BATTERY_CHRG_INPUT INPUT_PORT0 // 充电检测引脚挂载在IO扩展板的输入端口
|
||||
#define BATTERY_CHRG_PIN 5 // 充电检测引脚(P0_5)
|
||||
#define BATTERY_CHRG_CONFIG CONFIG_PORT0 // 充电检测引脚挂载在IO扩展板的输入端口
|
||||
|
||||
#define TAG_GPIO_IO_EXPAND_DETECT "GPIO_IO_EXPAND_DETECT" // GPIO中断检测日志标签
|
||||
#define TAG_I2C_IO_EXPAND_TASK "I2C_IO_EXPAND_TASK" // I2CIO扩展板任务日志标签
|
||||
|
||||
// GPIO引脚定义
|
||||
#define GPIO_INPUT_PIN_SEL GPIO_NUM_10 // IO扩展板中断检测引脚
|
||||
// #define IO_EXPAND_RSTN GPIO_NUM_14 // IO扩展板复位引脚
|
||||
|
||||
/**
|
||||
* @class IOExpansionBoard
|
||||
* @brief I/O扩展板驱动类,封装AW9523BTQR芯片操作
|
||||
*/
|
||||
class IOExpansionBoard
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief 构造函数
|
||||
*/
|
||||
IOExpansionBoard();
|
||||
|
||||
/**
|
||||
* @brief 设置毫米波雷达指针
|
||||
* @param radar 毫米波雷达对象指针
|
||||
*/
|
||||
void SetRadar(MillimeterWaveRadar* radar) { radar_ = radar; };
|
||||
|
||||
/**
|
||||
* @brief 设置限位开关指针
|
||||
* @param photo_interrupter 限位开关对象指针
|
||||
*/
|
||||
void setPhotoInterrupter(PhotoInterrupter* photo_interrupter) { photo_interrupter_ = photo_interrupter; };
|
||||
|
||||
/**
|
||||
* @brief 设置电池监控器指针
|
||||
* @param battery_monitor 电池监控器对象指针
|
||||
*/
|
||||
void setBatteryMonitor(AdcBatteryMonitor* battery_monitor) { battery_monitor_ = battery_monitor; };
|
||||
|
||||
/**
|
||||
* @brief 析构函数
|
||||
*/
|
||||
~IOExpansionBoard();
|
||||
|
||||
/**
|
||||
* @brief 初始化GPIO中断检测
|
||||
* @param gpio_num 中断引脚编号
|
||||
* @return esp_err_t 初始化结果
|
||||
*/
|
||||
esp_err_t InterruptGpioInit(gpio_num_t gpio_num);
|
||||
|
||||
/**
|
||||
* @brief 初始化IO扩展板复位引脚
|
||||
* @param gpio_num 复位引脚编号
|
||||
* @return esp_err_t 初始化结果
|
||||
*/
|
||||
esp_err_t ResetGpioInit(gpio_num_t gpio_num);
|
||||
|
||||
/**
|
||||
* @brief 初始化IO扩展板复位引脚
|
||||
* @param gpio_num 复位引脚编号
|
||||
* @return esp_err_t 初始化结果
|
||||
*/
|
||||
esp_err_t ResetIoExpand();
|
||||
|
||||
/**
|
||||
* @brief 初始化I2C主机通信
|
||||
* @return esp_err_t 初始化结果
|
||||
*/
|
||||
// esp_err_t IoExpansionI2cInit();
|
||||
|
||||
/**
|
||||
* @brief 创建I2C数据读取任务
|
||||
*/
|
||||
void CreateI2cReadTask();
|
||||
|
||||
/**
|
||||
* @brief 启动I2C任务(整合初始化和任务创建)
|
||||
* @return esp_err_t 操作结果
|
||||
*/
|
||||
esp_err_t StartTask();
|
||||
|
||||
/**
|
||||
* @brief 写寄存器数据
|
||||
* @param reg_addr 寄存器地址
|
||||
* @param data 要写入的数据
|
||||
* @return esp_err_t 操作结果
|
||||
*/
|
||||
esp_err_t IoexpandWriteReg(uint8_t reg_addr, uint8_t data);
|
||||
|
||||
/**
|
||||
* @brief 读寄存器数据
|
||||
* @param reg_addr 寄存器地址
|
||||
* @param data 要读出的数据
|
||||
* @return esp_err_t 操作结果
|
||||
*/
|
||||
esp_err_t IoexpandReadReg(uint8_t reg_addr, uint8_t *data);
|
||||
|
||||
/**
|
||||
* @brief 读取输入端口0寄存器数据
|
||||
* @param data 输出参数,用于存储读取到的数据
|
||||
* @return esp_err_t 操作结果
|
||||
*/
|
||||
esp_err_t ReadInputPort0(uint8_t *data);
|
||||
|
||||
/**
|
||||
* @brief 读取输入端口1寄存器数据
|
||||
* @param data 输出参数,用于存储读取到的数据
|
||||
* @return esp_err_t 操作结果
|
||||
*/
|
||||
esp_err_t ReadInputPort1(uint8_t *data);
|
||||
|
||||
// /**
|
||||
// * @brief 设置IO扩展板GPIO中断状态 通过读取Input_Port0 和 Input_Port1 寄存器可以清除中断
|
||||
// * @param reg_addr 寄存器地址
|
||||
// * @return esp_err_t 操作结果
|
||||
// */
|
||||
// esp_err_t SetInterruptStatus(bool status);
|
||||
|
||||
/**
|
||||
* @brief 配置IO扩展版上的IO口为输出还是输入,并且设置初始为高电平
|
||||
* @return esp_err_t 操作结果
|
||||
*/
|
||||
esp_err_t IoexpandSetMode();
|
||||
|
||||
/**
|
||||
* @brief 设置步进电机的细分模式
|
||||
* @param mode 模式:1/2/4/8/16/32/64
|
||||
* @return esp_err_t 操作结果
|
||||
*/
|
||||
void SetStepperMicrostepMode(uint8_t mode, uint8_t OUTPUT_PORT_m0, uint8_t m0_pin, uint8_t OUTPUT_PORT_m1, uint8_t m1_pin);
|
||||
|
||||
/**
|
||||
* @brief 设置步进电机的方向
|
||||
* @param dir 方向
|
||||
* @param OUTPUT_PORT 输出端口
|
||||
* @param pin 引脚号
|
||||
* @return esp_err_t 操作结果
|
||||
*/
|
||||
esp_err_t StepperMotorSetDir(bool dir, uint8_t OUTPUT_PORT, uint8_t pin);
|
||||
|
||||
/**
|
||||
* @brief 设置步进电机的睡眠模式
|
||||
* @param 是否进入睡眠模式
|
||||
* @param 输出端口
|
||||
* @param 引脚号
|
||||
* @return esp_err_t 操作结果
|
||||
*/
|
||||
esp_err_t SetMotorSleepMode(bool mode, uint8_t OUTPUT_PORT, uint8_t nsleep_pin);
|
||||
|
||||
/**
|
||||
* @brief 设置步进电机的使能引脚状态
|
||||
* @param 使能状态
|
||||
* @return esp_err_t 操作结果
|
||||
*/
|
||||
esp_err_t SetMotorEnableMode(bool enable, uint8_t OUTPUT_PORT, uint8_t enable_pin);
|
||||
|
||||
/**
|
||||
* @brief 设置LCD的BL引脚状态
|
||||
* @param BL状态
|
||||
* @return esp_err_t 操作结果
|
||||
*/
|
||||
esp_err_t SetLcdBlMode(bool mode, uint8_t OUTPUT_PORT, uint8_t bl_pin);
|
||||
|
||||
/**
|
||||
* @brief 设置LCD的RST引脚状态
|
||||
* @param RST状态
|
||||
* @return esp_err_t 操作结果
|
||||
*/
|
||||
esp_err_t SetLcdResetMode(bool mode, uint8_t OUTPUT_PORT, uint8_t rst_pin);
|
||||
|
||||
/**
|
||||
* @brief 设置 LED_EN 引脚状态(v1.1.16:高电平有效,低电平无效)
|
||||
* @param enable true: 开启(置高),false: 关闭(置低)
|
||||
* @return esp_err_t 操作结果
|
||||
*/
|
||||
esp_err_t SetLedEnMode(bool enable);
|
||||
|
||||
/**
|
||||
* @brief 设置PA控制引脚状态
|
||||
* @param mode PA_CTRL状态(true为高电平,false为低电平)
|
||||
* @return esp_err_t 操作结果
|
||||
*/
|
||||
esp_err_t SetPaCtrlMode(bool mode);
|
||||
|
||||
/**
|
||||
* @brief 设置雷达中断引脚
|
||||
* @param 毫米波雷达的中断引脚模式
|
||||
* @param 输入端口
|
||||
* @param 引脚号
|
||||
* @return esp_err_t 操作结果
|
||||
*/
|
||||
esp_err_t SetRadarInterruptPin(bool mode, uint8_t INPUT_PORT, uint8_t interrupt_pin);
|
||||
|
||||
/**
|
||||
* @brief 计算Port0的字节值
|
||||
* @return uint8_t 操作结果
|
||||
*/
|
||||
uint8_t ByteCalculatePort0();
|
||||
|
||||
/**
|
||||
* @brief 计算Port1的字节值
|
||||
* @return uint8_t 操作结果
|
||||
*/
|
||||
uint8_t ByteCalculatePort1();
|
||||
|
||||
/**
|
||||
* @brief 设置雷达中断回调函数
|
||||
* @param callback 雷达中断回调函数
|
||||
*/
|
||||
void SetRadarCallback(RadarCallback callback) { radar_callback_ = callback; }
|
||||
|
||||
/**
|
||||
* @brief 设置光学传感器开始中断回调函数
|
||||
* @param callback 光学传感器开始中断回调函数
|
||||
*/
|
||||
void SetPhotoInterrupterStartCallback(PhotoInterrupterStartCallback callback) { photo_start_callback_ = callback; }
|
||||
|
||||
/**
|
||||
* @brief 设置光学传感器结束中断回调函数
|
||||
* @param callback 光学传感器结束中断回调函数
|
||||
*/
|
||||
void SetPhotoInterrupterEndCallback(PhotoInterrupterEndCallback callback) { photo_end_callback_ = callback; }
|
||||
|
||||
/**
|
||||
* @brief 设置电池充电中断回调函数
|
||||
* @param callback 电池充电中断回调函数
|
||||
*/
|
||||
void SetBatteryChargingCallback(BatteryChargingCallback callback) { battery_charging_callback_ = callback; }
|
||||
|
||||
/**
|
||||
* @brief 设置电池充满中断回调函数
|
||||
* @param callback 电池充满中断回调函数
|
||||
*/
|
||||
void SetBatteryFullCallback(BatteryFullCallback callback) { battery_full_callback_ = callback; }
|
||||
|
||||
/**
|
||||
* @brief 设置电池非充电中断回调函数
|
||||
* @param callback 电池非充电中断回调函数
|
||||
*/
|
||||
void SetBatteryNotChargingCallback(BatteryNotChargingCallback callback) { battery_not_charging_callback_ = callback; }
|
||||
|
||||
// 公共成员变量
|
||||
i2c_bus_handle_t bus_handle_ = nullptr; // I2C总线句柄
|
||||
uint8_t device_addr_; // I2C设备地址
|
||||
|
||||
private:
|
||||
// 静态成员函数
|
||||
MillimeterWaveRadar* radar_ = nullptr; // 毫米波雷达指针,用于触发回调
|
||||
PhotoInterrupter* photo_interrupter_ = nullptr; // 限位开关指针,用于触发回调
|
||||
AdcBatteryMonitor* battery_monitor_ = nullptr; // 电池监控器指针,用于触发回调
|
||||
static void IRAM_ATTR GpioIsrHandler(void* arg); // 中断处理函数
|
||||
static void I2cReadTask(void* pvParameters); // I2C数据读取任务函数
|
||||
|
||||
// 成员变量用于状态跟踪
|
||||
uint8_t last_port0_state_ = 0; // 上次检测到的Port0状态
|
||||
uint8_t last_port1_state_ = 0; // 上次检测到的Port1状态
|
||||
bool radar_last_state_ = false; // 雷达引脚上一次的状态
|
||||
bool battery_charging_last_state_ = false; // 电池充电状态上一次的状态
|
||||
bool battery_full_last_state_ = false; // 电池充满状态上一次的状态
|
||||
|
||||
// 回调函数成员变量
|
||||
RadarCallback radar_callback_ = nullptr;
|
||||
PhotoInterrupterStartCallback photo_start_callback_ = nullptr;
|
||||
PhotoInterrupterEndCallback photo_end_callback_ = nullptr;
|
||||
BatteryChargingCallback battery_charging_callback_ = nullptr;
|
||||
BatteryFullCallback battery_full_callback_ = nullptr;
|
||||
BatteryNotChargingCallback battery_not_charging_callback_ = nullptr;
|
||||
|
||||
// PhotoInterrupter* photo_interrupter_ = nullptr; // 光学传感器指针,用于触发回调
|
||||
// /**
|
||||
// * @brief 分配静态任务所需的内存
|
||||
// * @return bool 分配是否成功
|
||||
// */
|
||||
// bool AllocateStaticTaskMemory();
|
||||
|
||||
// /**
|
||||
// * @brief 释放静态任务分配的内存
|
||||
// */
|
||||
// void FreeStaticTaskMemory();
|
||||
|
||||
// 实例成员变量
|
||||
EventGroupHandle_t i2c_task_event_group_ = nullptr; // 事件组
|
||||
TaskHandle_t xI2CReadTaskHandle_ = nullptr; // 任务句柄
|
||||
bool is_initialized_ = false; // 初始化状态标记(新增)
|
||||
gpio_num_t interrupt_gpio_ = GPIO_NUM_NC; // 中断引脚
|
||||
gpio_num_t reset_gpio_ = GPIO_NUM_NC; // 复位引脚
|
||||
|
||||
// StackType_t* pI2CReadTaskStackBuffer = nullptr; // 任务栈指针(PSRAM)
|
||||
// StaticTask_t* pxI2CReadTaskBuffer = nullptr; // 任务控制块指针(内部RAM)
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,178 @@
|
||||
/**
|
||||
* @file power_management_config.h
|
||||
* @brief 功耗管理配置和策略定义
|
||||
* @author Embedded Software Expert
|
||||
* @date 2025年1月
|
||||
*
|
||||
* 这个文件定义了功耗管理的配置参数、策略和优化建议,
|
||||
* 为系统提供灵活的功耗管理方案。
|
||||
*/
|
||||
|
||||
#ifndef POWER_MANAGEMENT_CONFIG_H
|
||||
#define POWER_MANAGEMENT_CONFIG_H
|
||||
|
||||
#include "esp_sleep.h"
|
||||
#include "driver/rtc_io.h"
|
||||
#include "esp32/rom/rtc.h"
|
||||
|
||||
/**
|
||||
* @brief 功耗管理配置结构体
|
||||
*/
|
||||
typedef struct {
|
||||
// 睡眠模式配置
|
||||
uint64_t light_sleep_duration_us; // 轻度睡眠持续时间(微秒)
|
||||
uint64_t deep_sleep_duration_us; // 深度睡眠持续时间(微秒)
|
||||
|
||||
// 唤醒源配置
|
||||
bool enable_timer_wakeup; // 启用定时器唤醒
|
||||
bool enable_gpio_wakeup; // 启用GPIO唤醒
|
||||
bool enable_touch_wakeup; // 启用触摸唤醒
|
||||
gpio_num_t wakeup_gpio_num; // 唤醒GPIO编号
|
||||
int wakeup_level; // 唤醒电平(0或1)
|
||||
|
||||
// 功耗优化配置
|
||||
bool disable_bt_in_sleep; // 睡眠时关闭蓝牙
|
||||
bool disable_wifi_in_sleep; // 睡眠时关闭WiFi
|
||||
bool reduce_cpu_frequency; // 降低CPU频率
|
||||
uint32_t cpu_frequency_hz; // CPU频率(Hz)
|
||||
|
||||
// 外设功耗配置
|
||||
bool power_down_sdcard; // 睡眠时关闭SD卡电源
|
||||
bool power_down_display; // 睡眠时关闭显示电源
|
||||
bool power_down_audio; // 睡眠时关闭音频电源
|
||||
bool power_down_motor; // 睡眠时关闭电机电源
|
||||
|
||||
// RTC内存配置
|
||||
bool preserve_rtc_memory; // 保留RTC内存
|
||||
size_t rtc_memory_size; // RTC内存大小
|
||||
} power_management_config_t;
|
||||
|
||||
/**
|
||||
* @brief 默认功耗管理配置
|
||||
*/
|
||||
#define DEFAULT_POWER_CONFIG { \
|
||||
.light_sleep_duration_us = 1000000, /* 1秒 */ \
|
||||
.deep_sleep_duration_us = 30000000, /* 30秒 */ \
|
||||
.enable_timer_wakeup = true, /* 启用定时器唤醒 */ \
|
||||
.enable_gpio_wakeup = false, /* 不启用GPIO唤醒 */ \
|
||||
.enable_touch_wakeup = false, /* 不启用触摸唤醒 */ \
|
||||
.wakeup_gpio_num = GPIO_NUM_NC, /* 无GPIO唤醒 */ \
|
||||
.wakeup_level = 0, /* 低电平唤醒 */ \
|
||||
.disable_bt_in_sleep = true, /* 睡眠时关闭蓝牙 */ \
|
||||
.disable_wifi_in_sleep = true, /* 睡眠时关闭WiFi */ \
|
||||
.reduce_cpu_frequency = true, /* 降低CPU频率 */ \
|
||||
.cpu_frequency_hz = 80000000, /* 80MHz */ \
|
||||
.power_down_sdcard = true, /* 睡眠时关闭SD卡 */ \
|
||||
.power_down_display = true, /* 睡眠时关闭显示 */ \
|
||||
.power_down_audio = true, /* 睡眠时关闭音频 */ \
|
||||
.power_down_motor = true, /* 睡眠时关闭电机 */ \
|
||||
.preserve_rtc_memory = true, /* 保留RTC内存 */ \
|
||||
.rtc_memory_size = 4096, /* 4KB RTC内存 */ \
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 各功耗模式的详细配置
|
||||
*/
|
||||
static const power_management_config_t idle_mode_config = {
|
||||
.light_sleep_duration_us = 500000, // 500ms轻度睡眠
|
||||
.deep_sleep_duration_us = 0, // 不使用深度睡眠
|
||||
.enable_timer_wakeup = true,
|
||||
.enable_gpio_wakeup = true,
|
||||
.wakeup_gpio_num = GPIO_NUM_0, // 按键唤醒
|
||||
.wakeup_level = 0,
|
||||
.disable_bt_in_sleep = false, // 保持蓝牙连接
|
||||
.disable_wifi_in_sleep = false, // 保持WiFi连接
|
||||
.reduce_cpu_frequency = true,
|
||||
.cpu_frequency_hz = 40000000, // 40MHz
|
||||
.power_down_sdcard = false, // 保持SD卡(可能有后台任务)
|
||||
.power_down_display = true, // 关闭显示背光
|
||||
.power_down_audio = true, // 关闭音频
|
||||
.power_down_motor = true, // 关闭电机
|
||||
.preserve_rtc_memory = true,
|
||||
.rtc_memory_size = 2048,
|
||||
};
|
||||
|
||||
static const power_management_config_t light_sleep_config = {
|
||||
.light_sleep_duration_us = 0, // 直接进入轻度睡眠
|
||||
.deep_sleep_duration_us = 0,
|
||||
.enable_timer_wakeup = true,
|
||||
.enable_gpio_wakeup = true,
|
||||
.wakeup_gpio_num = GPIO_NUM_0,
|
||||
.wakeup_level = 0,
|
||||
.disable_bt_in_sleep = true, // 关闭蓝牙
|
||||
.disable_wifi_in_sleep = true, // 关闭WiFi
|
||||
.reduce_cpu_frequency = true,
|
||||
.cpu_frequency_hz = 40000000,
|
||||
.power_down_sdcard = true, // 关闭SD卡
|
||||
.power_down_display = true, // 关闭显示
|
||||
.power_down_audio = true, // 关闭音频
|
||||
.power_down_motor = true, // 关闭电机
|
||||
.preserve_rtc_memory = true,
|
||||
.rtc_memory_size = 4096,
|
||||
};
|
||||
|
||||
static const power_management_config_t deep_sleep_config = {
|
||||
.light_sleep_duration_us = 0,
|
||||
.deep_sleep_duration_us = 60000000, // 60秒深度睡眠
|
||||
.enable_timer_wakeup = true,
|
||||
.enable_gpio_wakeup = true,
|
||||
.wakeup_gpio_num = GPIO_NUM_0,
|
||||
.wakeup_level = 0,
|
||||
.disable_bt_in_sleep = true, // 关闭蓝牙
|
||||
.disable_wifi_in_sleep = true, // 关闭WiFi
|
||||
.reduce_cpu_frequency = true,
|
||||
.cpu_frequency_hz = 10000000, // 10MHz
|
||||
.power_down_sdcard = true, // 关闭SD卡
|
||||
.power_down_display = true, // 关闭显示
|
||||
.power_down_audio = true, // 关闭音频
|
||||
.power_down_motor = true, // 关闭电机
|
||||
.preserve_rtc_memory = true,
|
||||
.rtc_memory_size = 8192,
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 功耗统计和监控结构体
|
||||
*/
|
||||
typedef struct {
|
||||
uint64_t total_sleep_time_us; // 总睡眠时间
|
||||
uint64_t total_wake_time_us; // 总唤醒时间
|
||||
uint32_t sleep_count; // 睡眠次数
|
||||
uint32_t wake_count; // 唤醒次数
|
||||
uint32_t average_sleep_duration_us; // 平均睡眠时长
|
||||
uint32_t average_wake_duration_us; // 平均唤醒时长
|
||||
float estimated_power_saving_percent; // 估计的功耗节省百分比
|
||||
} power_statistics_t;
|
||||
|
||||
/**
|
||||
* @brief 功耗优化建议
|
||||
*
|
||||
* 基于硬件特性和使用模式,提供功耗优化建议
|
||||
*/
|
||||
typedef enum {
|
||||
OPTIMIZATION_NONE = 0,
|
||||
OPTIMIZATION_REDUCE_CPU_FREQ, // 降低CPU频率
|
||||
OPTIMIZATION_DISABLE_UNUSED_PERIPHERALS, // 关闭未使用的外设
|
||||
OPTIMIZATION_USE_LIGHT_SLEEP, // 使用轻度睡眠
|
||||
OPTIMIZATION_USE_DEEP_SLEEP, // 使用深度睡眠
|
||||
OPTIMIZATION_OPTIMIZE_GPIO_STATES, // 优化GPIO状态
|
||||
OPTIMIZATION_USE_RTC_MEMORY, // 使用RTC内存
|
||||
OPTIMIZATION_BATCH_OPERATIONS, // 批量操作
|
||||
} power_optimization_t;
|
||||
|
||||
/**
|
||||
* @brief 功耗管理事件回调
|
||||
*/
|
||||
typedef void (*power_event_callback_t)(power_mode_t old_mode, power_mode_t new_mode, void* user_data);
|
||||
|
||||
/**
|
||||
* @brief 功耗管理事件
|
||||
*/
|
||||
typedef enum {
|
||||
POWER_EVENT_MODE_CHANGE, // 功耗模式改变
|
||||
POWER_EVENT_SLEEP_START, // 睡眠开始
|
||||
POWER_EVENT_SLEEP_END, // 睡眠结束
|
||||
POWER_EVENT_WAKEUP, // 系统唤醒
|
||||
POWER_EVENT_OPTIMIZATION_TRIGGER, // 功耗优化触发
|
||||
} power_event_t;
|
||||
|
||||
#endif // POWER_MANAGEMENT_CONFIG_H
|
||||
@@ -0,0 +1,780 @@
|
||||
/**
|
||||
* @file board.cc
|
||||
* @brief 板级外设初始化类,包含步进电机、毫米波雷达、I2C总线等外设的初始化函数。
|
||||
* @author zouyuhua
|
||||
* @date 2025年8月7日
|
||||
*
|
||||
*/
|
||||
|
||||
extern "C" {
|
||||
#include "esp_log.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "driver/uart.h"
|
||||
#include "driver/ledc.h"
|
||||
#include "driver/gptimer.h"
|
||||
#include "esp_err.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "hal/gpio_types.h"
|
||||
#include "hal/uart_types.h"
|
||||
#include "esp_check.h"
|
||||
#include "sdkconfig.h"
|
||||
#include "i2c_bus.h"
|
||||
#include "esp_peripherals.h"
|
||||
#include "periph_sdcard.h"
|
||||
#include "esp_sleep.h"
|
||||
#include "driver/rtc_io.h"
|
||||
}
|
||||
|
||||
#include "board_sweekar.h"
|
||||
#include "config.h"
|
||||
#include "board.h" // 添加board.h以获取audio_board_sdcard_init函数声明
|
||||
#include "drv8428.h"
|
||||
#include "aw8646.h"
|
||||
#include "esp_vfs_fat.h"
|
||||
#include "audio_mem.h"
|
||||
#include "esp_timer.h"
|
||||
#include "base_board_hal_i2c.h"
|
||||
|
||||
#define TAG "board_sweekar"
|
||||
|
||||
static BoardSweekar* s_board_instance = nullptr;
|
||||
|
||||
BoardSweekar* BoardSweekar::GetInstance()
|
||||
{
|
||||
if (s_board_instance == nullptr) {
|
||||
static BoardSweekar global_board;
|
||||
s_board_instance = &global_board;
|
||||
}
|
||||
return s_board_instance;
|
||||
}
|
||||
|
||||
BoardSweekar::BoardSweekar()
|
||||
{
|
||||
#ifdef CONFIG_STEPPER_DRIVER_AW8646
|
||||
stepper_driver_ = new Aw8646Driver(io_expansion_);
|
||||
#else
|
||||
stepper_driver_ = new Drv8428Driver(io_expansion_);
|
||||
#endif
|
||||
|
||||
// Initialize Shutdown Control Pin (GPIO_NUM_13) and pull it HIGH
|
||||
// This is required to keep the main power on.
|
||||
#ifdef SHUTDOWN_CTRL_PIN
|
||||
gpio_config_t io_conf = {};
|
||||
io_conf.intr_type = GPIO_INTR_DISABLE;
|
||||
io_conf.mode = GPIO_MODE_OUTPUT;
|
||||
io_conf.pin_bit_mask = (1ULL << SHUTDOWN_CTRL_PIN);
|
||||
io_conf.pull_down_en = GPIO_PULLDOWN_DISABLE;
|
||||
io_conf.pull_up_en = GPIO_PULLUP_ENABLE;
|
||||
gpio_config(&io_conf);
|
||||
// 拉低开机
|
||||
gpio_set_level(SHUTDOWN_CTRL_PIN, 0);
|
||||
ESP_LOGI(TAG, "Initialized SHUTDOWN_CTRL_PIN (%d) to LOW (Power ON)", SHUTDOWN_CTRL_PIN);
|
||||
#endif
|
||||
}
|
||||
|
||||
BoardSweekar::~BoardSweekar()
|
||||
{
|
||||
if (stepper_driver_) {
|
||||
delete stepper_driver_;
|
||||
stepper_driver_ = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void BoardSweekar::SetAudioAmplifier(bool enable) {
|
||||
// 隐藏具体的硬件实现细节(比如当前版本是通过 IO 扩展板控制的)
|
||||
io_expansion_.SetPaCtrlMode(enable);
|
||||
ESP_LOGI(TAG, "Audio Amplifier %s", enable ? "ENABLED" : "DISABLED");
|
||||
}
|
||||
|
||||
/*========================== 步进电机相关驱动 ==========================*/
|
||||
|
||||
/**
|
||||
* @brief 步进电机初始化函数
|
||||
* 配置步进电机所需的GPIO引脚模式,通过IO扩展板设置步进驱动芯片的工作模式
|
||||
* 在 stepper_motor.cc 中完成 GPTimer + GPIO 翻转 STEP 脉冲的初始化
|
||||
*/
|
||||
void BoardSweekar::StepperMotorInit(void)
|
||||
{
|
||||
esp_err_t err = ESP_OK;
|
||||
|
||||
// 1) STEP 引脚改为普通 GPIO(不再用 LEDC)
|
||||
gpio_config_t io_cfg;
|
||||
io_cfg.pin_bit_mask = 1ULL << STEPPER_STEP_IO;
|
||||
io_cfg.mode = GPIO_MODE_OUTPUT;
|
||||
io_cfg.pull_up_en = GPIO_PULLUP_DISABLE;
|
||||
io_cfg.pull_down_en = GPIO_PULLDOWN_DISABLE;
|
||||
io_cfg.intr_type = GPIO_INTR_DISABLE;
|
||||
err = gpio_config(&io_cfg);
|
||||
if (err != ESP_OK)
|
||||
{
|
||||
ESP_LOGE(TAG_BOARD, "步进电机 STEP GPIO 配置失败, 错误码: 0x%x", err);
|
||||
}
|
||||
|
||||
// 初始电平拉低,保证上电不乱跳
|
||||
gpio_set_level(STEPPER_STEP_IO, 0);
|
||||
|
||||
// 2) 检查 I2C 总线是否已初始化
|
||||
if (bus_handle_ == nullptr)
|
||||
{
|
||||
ESP_LOGE(TAG_BOARD, "I2C总线未初始化,请先调用I2CMasterInit()");
|
||||
return;
|
||||
}
|
||||
|
||||
// 3) 初始化驱动对象并初始化
|
||||
if (stepper_driver_) {
|
||||
err = stepper_driver_->Init();
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG_BOARD, "步进电机驱动初始化失败, 错误码: 0x%x", err);
|
||||
}
|
||||
} else {
|
||||
ESP_LOGE(TAG_BOARD, "步进电机驱动创建失败");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief LCD IO引脚初始化函数(消除与步进电机的耦合)
|
||||
*
|
||||
* 配置LCD所需的IO扩展板寄存器,确保LCD复位引脚正常工作
|
||||
* 此函数独立于步进电机初始化,专门处理LCD相关的IO配置
|
||||
*/
|
||||
void BoardSweekar::LcdIoInit(void)
|
||||
{
|
||||
esp_err_t err = ESP_OK;
|
||||
|
||||
// 1) 检查I2C总线是否已初始化
|
||||
if (bus_handle_ == nullptr)
|
||||
{
|
||||
ESP_LOGE(TAG_BOARD, "I2C总线未初始化,请先调用I2CMasterInit()");
|
||||
return;
|
||||
}
|
||||
|
||||
// 2) 执行硬件复位,确保IO扩展板处于已知状态
|
||||
err = io_expansion_.ResetIoExpand();
|
||||
if (err != ESP_OK)
|
||||
{
|
||||
ESP_LOGE(TAG_BOARD, "IO扩展板硬件复位失败, 错误码: 0x%x", err);
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
ESP_LOGI(TAG_BOARD, "IO扩展板硬件复位成功");
|
||||
}
|
||||
|
||||
// 3) 配置IO扩展板模式(端口方向等)
|
||||
err = io_expansion_.IoexpandSetMode();
|
||||
if (err != ESP_OK)
|
||||
{
|
||||
ESP_LOGE(TAG_BOARD, "IO扩展板模式配置失败, 错误码: 0x%x", err);
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
ESP_LOGI(TAG_BOARD, "IO扩展板模式配置成功");
|
||||
}
|
||||
|
||||
// 4) 初始化LCD复位引脚:设置为高电平
|
||||
err = io_expansion_.SetLcdResetMode(LCD_RST_HIGH, LCD_RST_PORT, LCD_RST_PIN);
|
||||
if (err != ESP_OK)
|
||||
{
|
||||
ESP_LOGE(TAG_BOARD, "LCD复位引脚高电平设置失败, 错误码: 0x%x", err);
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
ESP_LOGI(TAG_BOARD, "LCD复位引脚高电平设置成功");
|
||||
}
|
||||
|
||||
// 5) 初始化LED_EN电源为关闭状态 (PMOS高电平关)
|
||||
// 只有在需要亮灯时,由ActuatorActor主动开启,避免平静状态下常亮
|
||||
err = io_expansion_.SetLedEnMode(false);
|
||||
if (err != ESP_OK)
|
||||
{
|
||||
ESP_LOGE(TAG_BOARD, "初始化LED_EN电源(关闭)失败, 错误码: 0x%x", err);
|
||||
}
|
||||
else
|
||||
{
|
||||
ESP_LOGI(TAG_BOARD, "初始化LED_EN电源(关闭)成功");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 执行系统关机
|
||||
* 内部拉高 SHUTDOWN_CTRL_PIN 引脚切断电源
|
||||
*/
|
||||
void BoardSweekar::SystemShutdown(void)
|
||||
{
|
||||
#ifdef SHUTDOWN_CTRL_PIN
|
||||
ESP_LOGI(TAG, "Executing System Shutdown... Pulling SHUTDOWN_CTRL_PIN (%d) HIGH", SHUTDOWN_CTRL_PIN);
|
||||
// 用户指定:拉高可以完成关机动作
|
||||
gpio_set_level(SHUTDOWN_CTRL_PIN, 1);
|
||||
|
||||
// 给一点时间让电源完全断开
|
||||
vTaskDelay(pdMS_TO_TICKS(1000));
|
||||
#else
|
||||
ESP_LOGW(TAG, "SHUTDOWN_CTRL_PIN is not defined. Cannot execute hardware shutdown.");
|
||||
#endif
|
||||
}
|
||||
|
||||
/*========================== 毫米波雷达相关驱动 ==========================*/
|
||||
|
||||
/**
|
||||
* @brief 毫米波雷达串口初始化函数
|
||||
*
|
||||
* 配置毫米波雷达所使用的串口参数(波特率、数据位、校验位、停止位等),设置串口引脚,
|
||||
* 并安装串口驱动。采用较大的RX/TX FIFO深度以处理突发数据,禁用驱动自带事件队列以避免
|
||||
* 与自定义中断冲突。
|
||||
*/
|
||||
void BoardSweekar::MillimeterWaveRadarUartInit(void)
|
||||
{
|
||||
uart_config_t uart_config = {
|
||||
.baud_rate = RADAR_BAUD_RATE,
|
||||
.data_bits = UART_DATA_8_BITS,
|
||||
.parity = UART_PARITY_DISABLE,
|
||||
.stop_bits = UART_STOP_BITS_1,
|
||||
.flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
|
||||
.source_clk = UART_SCLK_DEFAULT,
|
||||
.flags = {
|
||||
.allow_pd = 0,
|
||||
.backup_before_sleep = 0,
|
||||
},
|
||||
};
|
||||
|
||||
// 1. 设置串口参数
|
||||
ESP_ERROR_CHECK(uart_param_config(RADAR_UART_NUM, &uart_config));
|
||||
|
||||
// 2. 设置 UART 引脚
|
||||
ESP_ERROR_CHECK(uart_set_pin(RADAR_UART_NUM, UART_TX_PIN, UART_RX_PIN,
|
||||
UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE));
|
||||
|
||||
// 3. 安装 UART 驱动(禁用驱动自带事件队列,避免与自定义中断冲突)
|
||||
// 增加 RX/TX FIFO 深度以处理突发数据
|
||||
ESP_ERROR_CHECK(uart_driver_install(RADAR_UART_NUM, RADAR_BUF_SIZE * 4, RADAR_BUF_SIZE * 4,
|
||||
0, NULL, 0));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 毫米波雷达中断引脚初始化函数
|
||||
*
|
||||
* 配置毫米波雷达中断引脚为输入模式,禁用上拉电阻,使能下拉电阻,初始禁用中断功能
|
||||
* (如需使用中断需单独进行配置)。
|
||||
*/
|
||||
void BoardSweekar::MillimeterWaveRadarGpioInit(void)
|
||||
{
|
||||
// GPIO配置结构体
|
||||
gpio_config_t io_conf = {
|
||||
.pin_bit_mask = (1ULL << MILLIMETER_WAVE_RADAR_PIN), // 选择GPIO引脚
|
||||
.mode = GPIO_MODE_INPUT, // 设置为输入模式
|
||||
.pull_up_en = GPIO_PULLUP_DISABLE,
|
||||
.pull_down_en = GPIO_PULLDOWN_ENABLE, // 使能下拉
|
||||
.intr_type = GPIO_INTR_DISABLE // 禁用中断(如需中断需单独配置)
|
||||
};
|
||||
|
||||
// 配置GPIO
|
||||
gpio_config(&io_conf);
|
||||
}
|
||||
|
||||
/*========================== I2C总线及挂载的从设备相关驱动 ==========================*/
|
||||
|
||||
/**
|
||||
* @brief I2C总线及从机设备初始化函数
|
||||
*
|
||||
* 首先配置并创建I2C主机总线,然后依次添加IO扩展板和线性马达作为I2C从机设备到总线上。
|
||||
* 若总线创建或设备添加失败,会输出错误信息并进行相应的资源清理(删除已创建的总线)。
|
||||
* 初始化成功后,会通过ESP_LOGI输出IO扩展板和线性马达的从机地址信息。
|
||||
*
|
||||
* @return esp_err_t 初始化结果,ESP_OK表示成功,其他错误码表示相应的失败原因
|
||||
*/
|
||||
esp_err_t BoardSweekar::I2CMasterInit(void)
|
||||
{
|
||||
static const char *I2C_INIT = "I2C_INIT";
|
||||
|
||||
// 初始化IO扩展板复位引脚
|
||||
gpio_config_t reset_io_conf = {
|
||||
.pin_bit_mask = (1ULL << IO_EXPAND_RSTN),
|
||||
.mode = GPIO_MODE_OUTPUT,
|
||||
.pull_up_en = GPIO_PULLUP_ENABLE, // 使能上拉
|
||||
.pull_down_en = GPIO_PULLDOWN_DISABLE,
|
||||
.intr_type = GPIO_INTR_DISABLE
|
||||
};
|
||||
gpio_config(&reset_io_conf);
|
||||
|
||||
// 执行复位时序:先拉低100ms,再拉高并等待100ms
|
||||
gpio_set_level(IO_EXPAND_RSTN, 0); // 拉低复位
|
||||
vTaskDelay(pdMS_TO_TICKS(100)); // 等待100ms
|
||||
gpio_set_level(IO_EXPAND_RSTN, 1); // 释放复位
|
||||
vTaskDelay(pdMS_TO_TICKS(100)); // 等待设备启动
|
||||
|
||||
ESP_LOGI(I2C_INIT, "IO扩展板复位完成");
|
||||
|
||||
// 创建统一的I2C总线(使用ESP-ADF的i2c_bus)
|
||||
i2c_config_t i2c_cfg = {
|
||||
.mode = I2C_MODE_MASTER,
|
||||
.sda_io_num = I2C0_MASTER_SDA_IO,
|
||||
.scl_io_num = I2C0_MASTER_SCL_IO,
|
||||
.sda_pullup_en = GPIO_PULLUP_ENABLE,
|
||||
.scl_pullup_en = GPIO_PULLUP_ENABLE,
|
||||
.master = {
|
||||
.clk_speed = 100000,
|
||||
},
|
||||
};
|
||||
|
||||
// 创建I2C总线(ESP-ADF的audio_board_init会复用这个总线)
|
||||
bus_handle_ = i2c_bus_create(I2C0_MASTER_PORT, &i2c_cfg);
|
||||
if (bus_handle_ == NULL) {
|
||||
ESP_LOGE(TAG, "Failed to create I2C bus");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
vTaskDelay(pdMS_TO_TICKS(100)); // 等待设备启动
|
||||
// ESP-ADF的i2c_bus不需要单独添加设备,直接通过总线句柄和设备地址进行通信
|
||||
|
||||
// 验证线性马达设备是否存在
|
||||
esp_err_t err = i2c_bus_probe_addr(bus_handle_, LINEAR_MOTOR_I2C_SLAVE_ADDR << 1);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(I2C_INIT, "线性马达设备未找到(地址:0x%02X),错误码: 0x%x", LINEAR_MOTOR_I2C_SLAVE_ADDR, err);
|
||||
// 不返回错误,继续初始化
|
||||
} else {
|
||||
ESP_LOGI(I2C_INIT, "线性马达设备检测成功(地址:0x%02X)", LINEAR_MOTOR_I2C_SLAVE_ADDR);
|
||||
}
|
||||
// 验证IO扩展板设备是否存在
|
||||
err = i2c_bus_probe_addr(bus_handle_, I2C_IO_EXPAND_SLAVE_ADDR << 1);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(I2C_INIT, "IO扩展板设备未找到(地址:0x%02X),错误码: 0x%x", I2C_IO_EXPAND_SLAVE_ADDR, err);
|
||||
// 不返回错误,继续初始化其他设备
|
||||
} else {
|
||||
ESP_LOGI(I2C_INIT, "IO扩展板设备检测成功(地址:0x%02X)", I2C_IO_EXPAND_SLAVE_ADDR);
|
||||
}
|
||||
// 验证陀螺仪设备是否存在
|
||||
err = i2c_bus_probe_addr(bus_handle_, GYROSCOPE_I2C_SLAVE_ADDR << 1);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(I2C_INIT, "陀螺仪设备未找到(地址:0x%02X),错误码: 0x%x", GYROSCOPE_I2C_SLAVE_ADDR, err);
|
||||
// 不返回错误,继续初始化
|
||||
} else {
|
||||
ESP_LOGI(I2C_INIT, "陀螺仪设备检测成功(地址:0x%02X)", GYROSCOPE_I2C_SLAVE_ADDR);
|
||||
}
|
||||
|
||||
// 为IO扩展板设置总线句柄和设备地址(使用7位地址)
|
||||
io_expansion_.bus_handle_ = bus_handle_;
|
||||
io_expansion_.device_addr_ = I2C_IO_EXPAND_SLAVE_ADDR << 1;
|
||||
|
||||
// 线性马达的初始化已移至 InitializeAllHardware 中统一调用 Init 方法
|
||||
// linear_motor_ 的参数传递将在那里完成,不再此处直接赋值,提高内聚性
|
||||
|
||||
ESP_LOGI(I2C_INIT, "I2C总线初始化完成");
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
/*========================== VBAT to VBAT_5V相关驱动 ==========================*/
|
||||
|
||||
/**
|
||||
* @brief 开启VBAT to VBAT_5V
|
||||
*
|
||||
* 创建开启升压的电源管理单元
|
||||
*
|
||||
*/
|
||||
void BoardSweekar::VbatToVbat5vInit(void)
|
||||
{
|
||||
// 配置VBAT_5V引脚为输出模式
|
||||
gpio_config_t io_conf = {
|
||||
.pin_bit_mask = (1ULL << VBAT_5V_PIN),
|
||||
.mode = GPIO_MODE_OUTPUT,
|
||||
.pull_up_en = GPIO_PULLUP_DISABLE,
|
||||
.pull_down_en = GPIO_PULLDOWN_DISABLE,
|
||||
.intr_type = GPIO_INTR_DISABLE
|
||||
};
|
||||
gpio_config(&io_conf);
|
||||
// 使能VBAT_5V
|
||||
gpio_set_level(VBAT_5V_PIN, 1);
|
||||
}
|
||||
|
||||
/*========================== 底座控制串口相关驱动 ==========================*/
|
||||
|
||||
/**
|
||||
* @brief 底座控制命令串口初始化函数
|
||||
*/
|
||||
// 根据配置选择通信方式的HAL头文件
|
||||
#ifdef CONFIG_BASE_BOARD_COMM_I2C
|
||||
#include "base_board_hal_i2c.h"
|
||||
#else
|
||||
#include "base_board_hal_uart.h"
|
||||
#endif
|
||||
|
||||
void BoardSweekar::BaseBoardControlInit(void)
|
||||
{
|
||||
#ifdef CONFIG_BASE_BOARD_COMM_I2C
|
||||
// I2C Mode
|
||||
if (bus_handle_ == nullptr) {
|
||||
ESP_LOGE(TAG, "I2C bus not initialized before BaseBoardControlInit");
|
||||
return;
|
||||
}
|
||||
|
||||
// 创建 I2C HAL 实例
|
||||
BaseBoardHalI2c *hal = new BaseBoardHalI2c(bus_handle_);
|
||||
base_board_control_.Init(hal);
|
||||
ESP_LOGI(TAG, "BaseBoardControl I2C initialized");
|
||||
#else
|
||||
// UART Mode
|
||||
uart_config_t uart_config = {
|
||||
.baud_rate = BASE_BOARD_CTL_UART_BAUDRATE,
|
||||
.data_bits = UART_DATA_8_BITS,
|
||||
.parity = UART_PARITY_DISABLE,
|
||||
.stop_bits = UART_STOP_BITS_1,
|
||||
.flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
|
||||
.source_clk = UART_SCLK_DEFAULT,
|
||||
.flags = {
|
||||
.allow_pd = 0,
|
||||
.backup_before_sleep = 0,
|
||||
},
|
||||
};
|
||||
|
||||
// 1. 设置串口参数
|
||||
ESP_ERROR_CHECK(uart_param_config(BASE_BOARD_CTL_UART_PORT, &uart_config));
|
||||
|
||||
// 2. 设置 UART 引脚
|
||||
ESP_ERROR_CHECK(uart_set_pin(BASE_BOARD_CTL_UART_PORT, BASE_BOARD_CTL_UART_TX_PIN, BASE_BOARD_CTL_UART_RX_PIN,
|
||||
UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE));
|
||||
|
||||
// 3. 安装 UART 驱动
|
||||
ESP_ERROR_CHECK(uart_driver_install(BASE_BOARD_CTL_UART_PORT,
|
||||
BASE_BOARD_CTL_UART_BUF_SIZE,
|
||||
BASE_BOARD_CTL_UART_BUF_SIZE,
|
||||
0, NULL, 0));
|
||||
|
||||
BaseBoardHalUart *hal = new BaseBoardHalUart(BASE_BOARD_CTL_UART_PORT);
|
||||
base_board_control_.Init(hal);
|
||||
ESP_LOGI(TAG, "BaseBoardControl UART initialized");
|
||||
#endif
|
||||
}
|
||||
|
||||
/*========================== SD卡相关驱动 ==========================*/
|
||||
|
||||
/**
|
||||
* @brief SD卡初始化函数
|
||||
*
|
||||
* 初始化SD卡外设,使用1线模式进行通信。该函数负责初始化外设管理器
|
||||
* 并配置SD卡,为后续的文件系统操作做准备。
|
||||
*
|
||||
* @return esp_err_t 初始化结果,ESP_OK表示成功,其他错误码表示失败原因
|
||||
*/
|
||||
esp_err_t BoardSweekar::InitializeSdcard(void)
|
||||
{
|
||||
static const char *SDCARD_TAG = "SDCARD_INIT";
|
||||
esp_err_t ret;
|
||||
|
||||
ESP_LOGI(SDCARD_TAG, "Initializing SD card");
|
||||
|
||||
if (is_sdcard_initialized_) {
|
||||
ESP_LOGW(SDCARD_TAG, "SD card already initialized");
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
// 初始化外设管理
|
||||
esp_periph_config_t periph_cfg = DEFAULT_ESP_PERIPH_SET_CONFIG();
|
||||
periph_cfg.extern_stack = true; // 将任务栈分配到 PSRAM 以节省 Internal SRAM
|
||||
periph_set_ = esp_periph_set_init(&periph_cfg);
|
||||
if (!periph_set_) {
|
||||
ESP_LOGE(SDCARD_TAG, "Failed to initialize peripheral set");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
// 初始化SD卡外设
|
||||
ret = audio_board_sdcard_init(periph_set_, SD_MODE_1_LINE);
|
||||
if (ret != ESP_OK) {
|
||||
ESP_LOGE(SDCARD_TAG, "Failed to initialize SD card: %s", esp_err_to_name(ret));
|
||||
return ret;
|
||||
}
|
||||
|
||||
is_sdcard_initialized_ = true;
|
||||
ESP_LOGI(SDCARD_TAG, "SD card initialized successfully");
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 统一的硬件初始化接口实现
|
||||
*
|
||||
* 按照依赖关系顺序初始化所有硬件资源:
|
||||
* 1. I2C总线(最基础,其他设备可能依赖)
|
||||
* 2. IO扩展板(可能影响其他设备)
|
||||
* 3. SD卡(文件系统,供显示和音频使用)
|
||||
* 4. 其他外设
|
||||
*
|
||||
* @return esp_err_t 初始化结果,ESP_OK表示全部成功
|
||||
*/
|
||||
esp_err_t BoardSweekar::InitializeAllHardware(void)
|
||||
{
|
||||
static const char *HW_INIT_TAG = "HW_INIT";
|
||||
esp_err_t ret;
|
||||
|
||||
ESP_LOGI(HW_INIT_TAG, "Starting unified hardware initialization...");
|
||||
|
||||
// 1. 初始化I2C总线(最基础)
|
||||
ret = I2CMasterInit();
|
||||
if (ret != ESP_OK) {
|
||||
ESP_LOGE(HW_INIT_TAG, "Failed to initialize I2C master: %s", esp_err_to_name(ret));
|
||||
return ret;
|
||||
}
|
||||
ESP_LOGI(HW_INIT_TAG, "I2C master initialized");
|
||||
|
||||
// 2. 创建I2C读任务(IO扩展板需要)
|
||||
io_expansion_.CreateI2cReadTask();
|
||||
ESP_LOGI(HW_INIT_TAG, "I2C read task created");
|
||||
|
||||
// 3. 初始化SD卡(文件系统,供显示和音频使用)
|
||||
ret = InitializeSdcard();
|
||||
if (ret != ESP_OK) {
|
||||
ESP_LOGE(HW_INIT_TAG, "Failed to initialize SD card: %s", esp_err_to_name(ret));
|
||||
// SD卡失败不是致命错误,继续初始化其他硬件
|
||||
ESP_LOGW(HW_INIT_TAG, "SD card initialization failed, but continuing with other hardware");
|
||||
} else {
|
||||
ESP_LOGI(HW_INIT_TAG, "SD card initialized");
|
||||
}
|
||||
|
||||
// 4. 初始化LCD IO引脚
|
||||
LcdIoInit();
|
||||
ESP_LOGI(HW_INIT_TAG, "LCD IO pins initialized");
|
||||
|
||||
// 5. 初始化底座控制
|
||||
if (bus_handle_ != nullptr) {
|
||||
BaseBoardHalI2c *hal_i2c = new BaseBoardHalI2c(bus_handle_);
|
||||
base_board_control_.Init(hal_i2c);
|
||||
ESP_LOGI(HW_INIT_TAG, "Base board control initialized with I2C handle");
|
||||
} else {
|
||||
ESP_LOGE(HW_INIT_TAG, "Failed to initialize base board control: I2C bus is null");
|
||||
}
|
||||
|
||||
// 6. 可选外设(根据具体应用需求)
|
||||
// BaseBoardControlUartInit(); // 底座控制串口(demo5需要)
|
||||
// ESP_LOGI(HW_INIT_TAG, "Base board control UART initialized");
|
||||
|
||||
// MillimeterWaveRadarUartInit();
|
||||
// MillimeterWaveRadarGpioInit();
|
||||
StepperMotorInit();
|
||||
|
||||
|
||||
|
||||
ESP_LOGI(HW_INIT_TAG, "Unified hardware initialization completed successfully");
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 进入低功耗模式
|
||||
*
|
||||
* 根据指定的功耗模式,执行相应的功耗优化策略:
|
||||
* - IDLE模式:关闭非必要外设,保持快速响应
|
||||
* - LIGHT_SLEEP模式:进入轻度睡眠,CPU暂停,外设断电
|
||||
* - DEEP_SLEEP模式:深度睡眠,仅RTC运行,功耗最低
|
||||
*/
|
||||
esp_err_t BoardSweekar::EnterLowPowerMode(power_mode_t mode) {
|
||||
static const char *POWER_TAG = "POWER_MGMT";
|
||||
esp_err_t ret = ESP_OK;
|
||||
|
||||
ESP_LOGI(POWER_TAG, "Entering power mode: %d", mode);
|
||||
|
||||
if (mode == current_power_mode_) {
|
||||
ESP_LOGW(POWER_TAG, "Already in power mode %d", mode);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
// 保存当前模式,以便恢复
|
||||
power_mode_t previous_mode = current_power_mode_;
|
||||
|
||||
switch (mode) {
|
||||
case POWER_MODE_NORMAL:
|
||||
// 正常模式,不需要特殊处理
|
||||
break;
|
||||
|
||||
case POWER_MODE_IDLE:
|
||||
// 空闲模式:关闭非必要外设
|
||||
ESP_LOGI(POWER_TAG, "Idle mode: disabling non-essential peripherals");
|
||||
|
||||
// 关闭SD卡(如果正在使用,需要先卸载)
|
||||
if (is_sdcard_initialized_) {
|
||||
// 注意:这里只是示例,实际应用中需要确保没有文件操作
|
||||
ESP_LOGW(POWER_TAG, "SD card still active in idle mode");
|
||||
}
|
||||
|
||||
// 关闭显示背光
|
||||
// 关闭非必要GPIO的上拉/下拉
|
||||
// 降低I2C时钟频率
|
||||
break;
|
||||
|
||||
case POWER_MODE_LIGHT_SLEEP:
|
||||
// 轻度睡眠
|
||||
ESP_LOGI(POWER_TAG, "Light sleep mode: preparing for sleep");
|
||||
|
||||
// 设置唤醒源(需要根据具体需求配置)
|
||||
// esp_sleep_enable_timer_wakeup(1000000); // 1秒后唤醒
|
||||
// esp_sleep_enable_ext0_wakeup(GPIO_NUM_XX, 0); // 外部中断唤醒
|
||||
|
||||
// 进入轻度睡眠
|
||||
// ret = esp_light_sleep_start();
|
||||
if (ret != ESP_OK) {
|
||||
ESP_LOGE(POWER_TAG, "Failed to enter light sleep: %s", esp_err_to_name(ret));
|
||||
current_power_mode_ = previous_mode;
|
||||
return ret;
|
||||
}
|
||||
break;
|
||||
|
||||
case POWER_MODE_DEEP_SLEEP:
|
||||
// 深度睡眠
|
||||
ESP_LOGI(POWER_TAG, "Deep sleep mode: system will restart after wake-up");
|
||||
|
||||
// 保存必要的RTC数据
|
||||
// rtc_gpio_isolate(GPIO_NUM_XX); // 隔离GPIO
|
||||
|
||||
// 设置深度睡眠唤醒源
|
||||
// esp_sleep_enable_timer_wakeup(60000000); // 60秒后唤醒
|
||||
|
||||
// 进入深度睡眠
|
||||
// esp_deep_sleep_start();
|
||||
// 注意:深度睡眠后系统会重启,不会返回
|
||||
break;
|
||||
|
||||
default:
|
||||
ESP_LOGE(POWER_TAG, "Invalid power mode: %d", mode);
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
current_power_mode_ = mode;
|
||||
ESP_LOGI(POWER_TAG, "Successfully entered power mode: %d", mode);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 退出低功耗模式
|
||||
*
|
||||
* 从低功耗模式恢复到正常运行模式,重新初始化必要的硬件资源。
|
||||
*/
|
||||
esp_err_t BoardSweekar::ExitLowPowerMode(void) {
|
||||
static const char *POWER_TAG = "POWER_MGMT";
|
||||
|
||||
ESP_LOGI(POWER_TAG, "Exiting low power mode");
|
||||
|
||||
if (current_power_mode_ == POWER_MODE_NORMAL) {
|
||||
ESP_LOGW(POWER_TAG, "Already in normal mode");
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
// 根据之前的功耗模式执行相应的恢复操作
|
||||
switch (current_power_mode_) {
|
||||
case POWER_MODE_IDLE:
|
||||
// 恢复空闲模式
|
||||
ESP_LOGI(POWER_TAG, "Restoring from idle mode");
|
||||
|
||||
// 重新初始化必要的外设
|
||||
// 恢复I2C时钟频率
|
||||
// 重新开启显示背光
|
||||
break;
|
||||
|
||||
case POWER_MODE_LIGHT_SLEEP:
|
||||
// 轻度睡眠唤醒后会自动继续执行
|
||||
ESP_LOGI(POWER_TAG, "Woken up from light sleep");
|
||||
|
||||
// 重新配置时钟(如果需要)
|
||||
// 重新初始化外设
|
||||
break;
|
||||
|
||||
case POWER_MODE_DEEP_SLEEP:
|
||||
// 深度睡眠后系统会重启,不会执行到这里
|
||||
ESP_LOGW(POWER_TAG, "Deep sleep recovery should not reach here");
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// 恢复到正常模式
|
||||
current_power_mode_ = POWER_MODE_NORMAL;
|
||||
ESP_LOGI(POWER_TAG, "Successfully exited low power mode");
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 设置硬件模块电源状态
|
||||
*
|
||||
* 提供精细化的电源管理,可以单独控制各个硬件模块的电源状态。
|
||||
*/
|
||||
esp_err_t BoardSweekar::SetModulePower(hardware_module_t module, bool enable) {
|
||||
static const char *POWER_TAG = "POWER_MODULE";
|
||||
esp_err_t ret = ESP_OK;
|
||||
|
||||
ESP_LOGI(POWER_TAG, "%s module %d", enable ? "Enabling" : "Disabling", module);
|
||||
|
||||
// 更新电源状态位图
|
||||
if (enable) {
|
||||
power_state_flags_ |= (1 << module);
|
||||
} else {
|
||||
power_state_flags_ &= ~(1 << module);
|
||||
}
|
||||
|
||||
switch (module) {
|
||||
case HW_MODULE_I2C:
|
||||
if (!enable && bus_handle_) {
|
||||
// 注意:I2C总线通常不建议完全关闭,可能影响多个设备
|
||||
ESP_LOGW(POWER_TAG, "I2C bus power control not recommended");
|
||||
}
|
||||
break;
|
||||
|
||||
case HW_MODULE_SDCARD:
|
||||
if (enable && !is_sdcard_initialized_) {
|
||||
ret = InitializeSdcard();
|
||||
} else if (!enable && is_sdcard_initialized_) {
|
||||
// 卸载SD卡文件系统
|
||||
// 注意:需要确保没有打开的文件
|
||||
ESP_LOGW(POWER_TAG, "SD card power down requires file system cleanup");
|
||||
}
|
||||
break;
|
||||
|
||||
case HW_MODULE_LCD:
|
||||
// LCD背光控制
|
||||
// LCD电源引脚控制(如果有)
|
||||
break;
|
||||
|
||||
case HW_MODULE_AUDIO:
|
||||
// 音频编解码器电源控制
|
||||
// 需要与AudioPlayer协调
|
||||
break;
|
||||
|
||||
case HW_MODULE_MOTOR:
|
||||
// 步进电机驱动器电源控制
|
||||
// 电机睡眠模式
|
||||
break;
|
||||
|
||||
case HW_MODULE_GYROSCOPE:
|
||||
// 陀螺仪电源控制
|
||||
// 设置陀螺仪为低功耗模式
|
||||
break;
|
||||
|
||||
case HW_MODULE_TOUCH:
|
||||
// 触摸传感器电源控制
|
||||
// 设置触摸传感器为睡眠模式
|
||||
break;
|
||||
|
||||
case HW_MODULE_RADAR:
|
||||
// 毫米波雷达电源控制
|
||||
// 设置雷达为低功耗模式
|
||||
break;
|
||||
|
||||
case HW_MODULE_IO_EXPAND:
|
||||
// IO扩展板电源控制
|
||||
// 设置扩展板为低功耗模式
|
||||
break;
|
||||
|
||||
default:
|
||||
ESP_LOGE(POWER_TAG, "Unknown hardware module: %d", module);
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
if (ret == ESP_OK) {
|
||||
ESP_LOGI(POWER_TAG, "Module %d power %s successfully", module, enable ? "enabled" : "disabled");
|
||||
} else {
|
||||
ESP_LOGE(POWER_TAG, "Failed to %s module %d: %s", enable ? "enable" : "disable", module, esp_err_to_name(ret));
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,181 @@
|
||||
#ifndef __BOARD_H__
|
||||
#define __BOARD_H__
|
||||
#include "config.h"
|
||||
#include "io_expansion_board.h"
|
||||
#include "stepper_motor.h"
|
||||
#include "stepper_driver.h"
|
||||
#include "i2c_bus.h"
|
||||
#include "gyroscope.h"
|
||||
#include "touch_sensor.h"
|
||||
#include "base_board_control.h"
|
||||
#include "esp_peripherals.h"
|
||||
#include "periph_sdcard.h"
|
||||
#include "esp_sleep.h"
|
||||
#include "driver/rtc_io.h"
|
||||
|
||||
/**
|
||||
* @brief 功耗模式枚举
|
||||
*/
|
||||
typedef enum {
|
||||
POWER_MODE_NORMAL, // 正常运行模式,所有硬件可用
|
||||
POWER_MODE_IDLE, // 空闲模式,关闭非必要外设
|
||||
POWER_MODE_LIGHT_SLEEP, // 轻度睡眠,快速唤醒
|
||||
POWER_MODE_DEEP_SLEEP, // 深度睡眠,仅RTC运行
|
||||
} power_mode_t;
|
||||
|
||||
/**
|
||||
* @brief 硬件模块枚举,用于精细化电源管理
|
||||
*/
|
||||
typedef enum {
|
||||
HW_MODULE_I2C, // I2C总线
|
||||
HW_MODULE_SDCARD, // SD卡
|
||||
HW_MODULE_LCD, // LCD显示
|
||||
HW_MODULE_AUDIO, // 音频编解码器
|
||||
HW_MODULE_MOTOR, // 步进电机
|
||||
HW_MODULE_GYROSCOPE, // 陀螺仪
|
||||
HW_MODULE_TOUCH, // 触摸传感器
|
||||
HW_MODULE_RADAR, // 毫米波雷达
|
||||
HW_MODULE_IO_EXPAND, // IO扩展板
|
||||
} hardware_module_t;
|
||||
|
||||
/**
|
||||
* @brief 硬件板级管理器
|
||||
*
|
||||
* 采用高内聚低耦合设计原则,统一管理所有硬件资源。
|
||||
* 提供统一的硬件初始化接口和资源访问,避免各模块重复初始化。
|
||||
*/
|
||||
class BoardSweekar
|
||||
{
|
||||
private:
|
||||
i2c_bus_handle_t bus_handle_ = nullptr; // 使用ESP-ADF的I2C总线句柄
|
||||
esp_periph_set_handle_t periph_set_ = nullptr; // 外设管理句柄
|
||||
bool is_sdcard_initialized_ = false; // SD卡初始化状态
|
||||
power_mode_t current_power_mode_ = POWER_MODE_NORMAL; // 当前功耗模式
|
||||
uint32_t power_state_flags_ = 0xFFFFFFFF; // 各模块电源状态位图(1为开启)
|
||||
|
||||
public:
|
||||
BoardSweekar();
|
||||
~BoardSweekar();
|
||||
|
||||
static BoardSweekar* GetInstance();
|
||||
|
||||
// --- 语义化的高层 API:音频与功放控制 ---
|
||||
// 开启或关闭外放功放 (PA),供上层 AudioActor/AudioPlayer 调用,屏蔽底层引脚实现
|
||||
void SetAudioAmplifier(bool enable);
|
||||
|
||||
IOExpansionBoard io_expansion_; // IO扩展板对象
|
||||
Gyroscope gyroscope_; // 陀螺仪对象
|
||||
TouchSensor touch_sensor_; // 触摸传感器对象
|
||||
BaseBoardControl base_board_control_; // 底座控制对象
|
||||
StepperDriver* stepper_driver_ = nullptr; // 步进电机驱动对象
|
||||
|
||||
StepperDriver* GetStepperDriver() const { return stepper_driver_; }
|
||||
|
||||
// 初始化步进电机
|
||||
void StepperMotorInit(void);
|
||||
|
||||
// 初始化LCD IO引脚(消除与步进电机的耦合)
|
||||
void LcdIoInit(void);
|
||||
|
||||
// 初始化串口
|
||||
void MillimeterWaveRadarUartInit(void);
|
||||
|
||||
//初始化毫米波雷达的中断引脚
|
||||
void MillimeterWaveRadarGpioInit(void);
|
||||
|
||||
/**
|
||||
* @brief 执行系统关机
|
||||
* 内部拉高/拉低 SHUTDOWN_CTRL_PIN 引脚切断电源
|
||||
*/
|
||||
void SystemShutdown(void);
|
||||
|
||||
// 初始化I2C总线
|
||||
esp_err_t I2CMasterInit(void);
|
||||
|
||||
// 初始化VBAT toVBAT_5V引脚
|
||||
void VbatToVbat5vInit(void);
|
||||
|
||||
// 初始化底座控制串口
|
||||
void BaseBoardControlInit(void);
|
||||
|
||||
// 初始化SD卡(推荐使用统一的硬件初始化)
|
||||
esp_err_t InitializeSdcard(void);
|
||||
|
||||
// 获取SD卡初始化状态
|
||||
bool IsSdcardInitialized() const { return is_sdcard_initialized_; }
|
||||
|
||||
// 获取外设管理句柄(供需要访问SD卡的模块使用)
|
||||
esp_periph_set_handle_t GetPeriphSet() const { return periph_set_; }
|
||||
|
||||
// 获取I2C总线句柄
|
||||
i2c_bus_handle_t GetBusHandle() const { return bus_handle_; }
|
||||
|
||||
/**
|
||||
* @brief 统一的硬件初始化接口
|
||||
*
|
||||
* 按照依赖关系顺序初始化所有硬件资源,确保各模块可以安全使用。
|
||||
* 推荐在主程序启动时调用此函数,而不是分别调用各个初始化函数。
|
||||
*
|
||||
* @return esp_err_t 初始化结果,ESP_OK表示全部成功
|
||||
*/
|
||||
esp_err_t InitializeAllHardware(void);
|
||||
|
||||
/**
|
||||
* @brief 完整的统一硬件初始化接口(专为复杂应用优化)
|
||||
*
|
||||
* 包含所有必要外设的完整初始化,适用于demo5等复杂应用场景。
|
||||
* 这个函数会初始化:I2C总线、IO扩展板、SD卡、LCD IO、底座控制等。
|
||||
*
|
||||
* @return esp_err_t 初始化结果,ESP_OK表示全部成功
|
||||
*/
|
||||
esp_err_t InitializeAllHardwareComplete(void);
|
||||
|
||||
/**
|
||||
* @brief 针对特定应用的硬件初始化配置
|
||||
*
|
||||
* 为不同类型的应用提供专门的初始化配置,优化启动流程。
|
||||
*
|
||||
* @param app_type 应用类型(demo5、音频播放器、显示应用等)
|
||||
* @return esp_err_t 初始化结果,ESP_OK表示全部成功
|
||||
*/
|
||||
esp_err_t InitializeHardwareForApplication(int app_type);
|
||||
|
||||
/**
|
||||
* @brief 功耗管理接口 - 进入低功耗模式
|
||||
*
|
||||
* 根据指定的功耗模式,关闭非必要硬件、设置GPIO为低功耗状态、
|
||||
* 调整时钟频率等。支持多种功耗模式以适应不同应用场景。
|
||||
*
|
||||
* @param mode 功耗模式
|
||||
* @return esp_err_t 操作结果
|
||||
*/
|
||||
esp_err_t EnterLowPowerMode(power_mode_t mode);
|
||||
|
||||
/**
|
||||
* @brief 功耗管理接口 - 退出低功耗模式
|
||||
*
|
||||
* 从低功耗模式恢复,重新初始化必要的硬件资源。
|
||||
*
|
||||
* @return esp_err_t 操作结果
|
||||
*/
|
||||
esp_err_t ExitLowPowerMode(void);
|
||||
|
||||
/**
|
||||
* @brief 获取当前功耗模式
|
||||
*
|
||||
* @return power_mode_t 当前功耗模式
|
||||
*/
|
||||
power_mode_t GetPowerMode(void) const { return current_power_mode_; }
|
||||
|
||||
/**
|
||||
* @brief 设置硬件模块电源状态
|
||||
*
|
||||
* 单独控制某个硬件模块的电源状态,用于精细化的功耗管理。
|
||||
*
|
||||
* @param module 硬件模块
|
||||
* @param enable true为开启,false为关闭
|
||||
* @return esp_err_t 操作结果
|
||||
*/
|
||||
esp_err_t SetModulePower(hardware_module_t module, bool enable);
|
||||
};
|
||||
#endif
|
||||
@@ -0,0 +1,186 @@
|
||||
/**
|
||||
* @file board_sweekar_complete_init.cc
|
||||
* @brief 完整的统一硬件初始化实现
|
||||
*
|
||||
* 这个文件提供了完整的统一硬件初始化函数,包含所有必要的硬件初始化步骤。
|
||||
* 专为demo5等复杂应用场景设计。
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief 完整的统一硬件初始化接口(专为demo5优化)
|
||||
*
|
||||
* 按照依赖关系顺序初始化所有硬件资源:
|
||||
* 1. I2C总线(最基础,其他设备依赖)
|
||||
* 2. IO扩展板(控制其他外设)
|
||||
* 3. SD卡(文件系统,供显示和音频使用)
|
||||
* 4. LCD IO引脚(显示相关)
|
||||
* 5. 底座控制串口(通信)
|
||||
* 6. 底座控制模块(业务逻辑)
|
||||
* 7. 其他外设(根据应用需求)
|
||||
*
|
||||
* @return esp_err_t 初始化结果,ESP_OK表示全部成功
|
||||
*/
|
||||
esp_err_t BoardSweekar::InitializeAllHardwareComplete(void)
|
||||
{
|
||||
static const char *HW_INIT_TAG = "HW_INIT_COMPLETE";
|
||||
esp_err_t ret;
|
||||
|
||||
ESP_LOGI(HW_INIT_TAG, "Starting complete hardware initialization...");
|
||||
|
||||
// 1. 初始化I2C总线(最基础,其他设备依赖)
|
||||
ret = I2CMasterInit();
|
||||
if (ret != ESP_OK) {
|
||||
ESP_LOGE(HW_INIT_TAG, "Failed to initialize I2C master: %s", esp_err_to_name(ret));
|
||||
return ret;
|
||||
}
|
||||
ESP_LOGI(HW_INIT_TAG, "✓ I2C master initialized");
|
||||
|
||||
// 2. 创建I2C读任务(IO扩展板需要)
|
||||
io_expansion_.CreateI2cReadTask();
|
||||
ESP_LOGI(HW_INIT_TAG, "✓ I2C read task created");
|
||||
|
||||
// 3. 初始化SD卡(文件系统,供显示和音频使用)
|
||||
ret = InitializeSdcard();
|
||||
if (ret != ESP_OK) {
|
||||
ESP_LOGE(HW_INIT_TAG, "Failed to initialize SD card: %s", esp_err_to_name(ret));
|
||||
// SD卡失败不是致命错误,继续初始化其他硬件
|
||||
ESP_LOGW(HW_INIT_TAG, "⚠ SD card initialization failed, but continuing with other hardware");
|
||||
} else {
|
||||
ESP_LOGI(HW_INIT_TAG, "✓ SD card initialized");
|
||||
}
|
||||
|
||||
// 4. 初始化LCD IO引脚(显示相关)
|
||||
LcdIoInit();
|
||||
ESP_LOGI(HW_INIT_TAG, "✓ LCD IO pins initialized");
|
||||
|
||||
// 5. 初始化底座控制串口(demo5需要)
|
||||
BaseBoardControlUartInit();
|
||||
ESP_LOGI(HW_INIT_TAG, "✓ Base board control UART initialized");
|
||||
|
||||
// 6. 初始化底座控制模块
|
||||
base_board_control_.Init();
|
||||
ESP_LOGI(HW_INIT_TAG, "✓ Base board control initialized");
|
||||
|
||||
// 7. 设置IO扩展板的PA控制模式(demo5需要)
|
||||
io_expansion_.SetPaCtrlMode(true);
|
||||
ESP_LOGI(HW_INIT_TAG, "✓ IO expansion PA control mode set");
|
||||
|
||||
// 8. 可选外设(根据具体应用需求启用)
|
||||
// ESP_LOGI(HW_INIT_TAG, "Initializing optional peripherals...");
|
||||
//
|
||||
// // 毫米波雷达(如需要)
|
||||
// MillimeterWaveRadarUartInit();
|
||||
// MillimeterWaveRadarGpioInit();
|
||||
// ESP_LOGI(HW_INIT_TAG, "✓ Millimeter wave radar initialized");
|
||||
//
|
||||
// // VBAT升压(如需要)
|
||||
// VbatToVbat5vInit();
|
||||
// ESP_LOGI(HW_INIT_TAG, "✓ VBAT to 5V booster initialized");
|
||||
//
|
||||
// // 步进电机(如需要)
|
||||
// StepperMotorInit();
|
||||
// ESP_LOGI(HW_INIT_TAG, "✓ Stepper motor initialized");
|
||||
|
||||
ESP_LOGI(HW_INIT_TAG, "=== Complete hardware initialization finished successfully ===");
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 针对特定应用的硬件初始化配置
|
||||
*
|
||||
* 为不同类型的应用提供专门的初始化配置
|
||||
*/
|
||||
esp_err_t BoardSweekar::InitializeHardwareForApplication(application_type_t app_type) {
|
||||
static const char *APP_INIT_TAG = "APP_HW_INIT";
|
||||
|
||||
ESP_LOGI(APP_INIT_TAG, "Initializing hardware for application type: %d", app_type);
|
||||
|
||||
// 基础硬件初始化(所有应用都需要)
|
||||
esp_err_t ret = InitializeAllHardwareComplete();
|
||||
if (ret != ESP_OK) {
|
||||
ESP_LOGE(APP_INIT_TAG, "Basic hardware initialization failed");
|
||||
return ret;
|
||||
}
|
||||
|
||||
switch (app_type) {
|
||||
case APP_TYPE_DEMO5: // 宠物游戏demo
|
||||
ESP_LOGI(APP_INIT_TAG, "Configuring for Demo5 (Pet Game)...");
|
||||
|
||||
// Demo5需要的额外初始化
|
||||
// 触摸传感器、陀螺仪、RGB LED等会在应用层初始化
|
||||
|
||||
ESP_LOGI(APP_INIT_TAG, "✓ Demo5 hardware configuration complete");
|
||||
break;
|
||||
|
||||
case APP_TYPE_AUDIO_PLAYER: // 音频播放器
|
||||
ESP_LOGI(APP_INIT_TAG, "Configuring for Audio Player...");
|
||||
|
||||
// 音频应用需要确保音频编解码器正确初始化
|
||||
// 这部分通常在AudioPlayer类中处理
|
||||
|
||||
ESP_LOGI(APP_INIT_TAG, "✓ Audio player hardware configuration complete");
|
||||
break;
|
||||
|
||||
case APP_TYPE_DISPLAY_ONLY: // 纯显示应用
|
||||
ESP_LOGI(APP_INIT_TAG, "Configuring for Display Only...");
|
||||
|
||||
// 显示应用需要确保LCD相关硬件正确配置
|
||||
// 这部分通常在Display类中处理
|
||||
|
||||
ESP_LOGI(APP_INIT_TAG, "✓ Display-only hardware configuration complete");
|
||||
break;
|
||||
|
||||
case APP_TYPE_MINIMAL: // 最小化应用
|
||||
ESP_LOGI(APP_INIT_TAG, "Configuring for Minimal Application...");
|
||||
|
||||
// 最小化配置,只保留最基本的功能
|
||||
// 关闭非必要外设以节省功耗
|
||||
|
||||
ESP_LOGI(APP_INIT_TAG, "✓ Minimal hardware configuration complete");
|
||||
break;
|
||||
|
||||
default:
|
||||
ESP_LOGW(APP_INIT_TAG, "Unknown application type, using default configuration");
|
||||
break;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 硬件初始化状态报告
|
||||
*
|
||||
* 提供详细的硬件初始化状态报告,便于调试和问题排查
|
||||
*/
|
||||
void BoardSweekar::ReportHardwareStatus(void) {
|
||||
static const char *STATUS_TAG = "HW_STATUS";
|
||||
|
||||
ESP_LOGI(STATUS_TAG, "=== Hardware Initialization Status Report ===");
|
||||
|
||||
// I2C总线状态
|
||||
ESP_LOGI(STATUS_TAG, "I2C Bus: %s", (bus_handle_ != nullptr) ? "✓ Initialized" : "✗ Not initialized");
|
||||
|
||||
// SD卡状态
|
||||
ESP_LOGI(STATUS_TAG, "SD Card: %s", (is_sdcard_initialized_) ? "✓ Initialized" : "✗ Not initialized");
|
||||
if (is_sdcard_initialized_) {
|
||||
ESP_LOGI(STATUS_TAG, " Peripheral Set: %s", (periph_set_ != nullptr) ? "✓ Available" : "✗ Not available");
|
||||
}
|
||||
|
||||
// IO扩展板状态
|
||||
ESP_LOGI(STATUS_TAG, "IO Expansion Board: %s", (io_expansion_.bus_handle_ != nullptr) ? "✓ Configured" : "✗ Not configured");
|
||||
|
||||
// 底座控制状态
|
||||
ESP_LOGI(STATUS_TAG, "Base Board Control: %s", (base_board_control_.GetUartPort() != 0) ? "✓ Initialized" : "✗ Not initialized");
|
||||
|
||||
// 功耗管理状态
|
||||
ESP_LOGI(STATUS_TAG, "Power Management: %s", (current_power_mode_ == POWER_MODE_NORMAL) ? "✓ Normal mode" : "⚠ Low power mode");
|
||||
ESP_LOGI(STATUS_TAG, " Current Mode: %d", current_power_mode_);
|
||||
ESP_LOGI(STATUS_TAG, " Module Power States: 0x%08X", power_state_flags_);
|
||||
|
||||
// 内存状态
|
||||
ESP_LOGI(STATUS_TAG, "Memory Status:");
|
||||
ESP_LOGI(STATUS_TAG, " Internal RAM Free: %d bytes", heap_caps_get_free_size(MALLOC_CAP_INTERNAL));
|
||||
ESP_LOGI(STATUS_TAG, " PSRAM Free: %d bytes", heap_caps_get_free_size(MALLOC_CAP_SPIRAM));
|
||||
|
||||
ESP_LOGI(STATUS_TAG, "=== End of Hardware Status Report ===");
|
||||
}
|
||||
@@ -0,0 +1,136 @@
|
||||
/* 定义引脚分配 */
|
||||
#ifndef _BOARD_CONFIG_H_
|
||||
#define _BOARD_CONFIG_H_
|
||||
|
||||
/**
|
||||
* @file config.h
|
||||
* @brief 定义了引脚的分配。
|
||||
* @author zouyuhua
|
||||
* @date 2025年8月7日
|
||||
*
|
||||
*/
|
||||
|
||||
#include "driver/gpio.h"
|
||||
#include "driver/i2c_master.h"
|
||||
#include "driver/i2s.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_rom_sys.h" // 用于 esp_rom_delay_us
|
||||
#include "esp_timer.h"
|
||||
#include "esp_mac.h"
|
||||
#include "driver/ledc.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "esp_log.h"
|
||||
#include "driver/gptimer.h"
|
||||
#include "esp_intr_alloc.h"
|
||||
#include "driver/uart.h"
|
||||
#include "esp_err.h"
|
||||
#include "freertos/queue.h"
|
||||
#include "soc/uart_reg.h"
|
||||
#include "linear_motor.h"
|
||||
#include "gyroscope.h"
|
||||
|
||||
#define TAG_BOARD "SWEEKAR_ESP32"
|
||||
/*I2C总线引脚定义*/
|
||||
#define I2C0_MASTER_PORT I2C_NUM_0
|
||||
#define I2C0_MASTER_SDA_IO GPIO_NUM_2
|
||||
#define I2C0_MASTER_SCL_IO GPIO_NUM_3
|
||||
|
||||
/* 步进电机配置 */
|
||||
#define STEPPER_STEP_IO GPIO_NUM_42 // 步进电机脉冲输入引脚
|
||||
#define STEPPER_TIMER_RES_HZ 1000000 // 步进电机定时器分辨率 1 MHz(1 us 步进)
|
||||
|
||||
/* 定义屏幕驱动控制引脚 */
|
||||
#define ST7789_PIN_CLK GPIO_NUM_48 // SPI时钟引脚
|
||||
#define ST7789_PIN_DC GPIO_NUM_38 // 数据/命令选择引脚RSEL
|
||||
#define ST7789_PIN_MOSI GPIO_NUM_47 // SPI数据输出引脚
|
||||
#define ST7789_PIN_CS GPIO_NUM_46 // SPI片选引脚
|
||||
#define ST7789_PIN_BL GPIO_NUM_45 // 背光引脚
|
||||
#define ST7789_PIN_RST GPIO_NUM_NC // 复位引脚
|
||||
#define LCD_BL_ACTIVE_LEVEL 0 // 背光有效电平:1=高电平有效(NMOS),0=低电平有效(PMOS)
|
||||
|
||||
#define LCD_WIDTH 172 // 屏幕宽度(水平方向像素数)
|
||||
#define LCD_HEIGHT 320 // 屏幕高度(垂直方向像素数)
|
||||
|
||||
/* 毫米波雷达配置参数 */
|
||||
/* 定义毫米波雷达的中断引脚 */
|
||||
#define MILLIMETER_WAVE_RADAR_PIN GPIO_NUM_35
|
||||
// UART 配置参数
|
||||
#define RADAR_UART_NUM UART_NUM_1 // 使用 UART1
|
||||
#define UART_TX_PIN GPIO_NUM_40 // GPIO40 作为 TX(根据实际硬件连接调整)
|
||||
#define UART_RX_PIN GPIO_NUM_39 // GPIO39 作为 RX
|
||||
#define RADAR_BAUD_RATE 9600 // 雷达波特率
|
||||
#define RADAR_BUF_SIZE 100 // 雷达接收缓冲区大小
|
||||
|
||||
/* IO扩展硬件配置常量 */
|
||||
#define I2C_MASTER_FREQ_HZ 100000 // I2C通信频率(100kHz)(可更改至400000)
|
||||
#define I2C_IO_EXPAND_SLAVE_ADDR 0x58 // AW9523BTQR器件地址,v1_1_13的addr1和addr0是0
|
||||
#define GPIO_INPUT_PIN_SEL GPIO_NUM_10 // 中断检测引脚
|
||||
#define ESP_INTR_FLAG_DEFAULT 0 // 中断标志默认值
|
||||
#define IO_EXPAND_RSTN GPIO_NUM_14 // IO扩展板复位引脚
|
||||
|
||||
/* 定义线性马达的I2C从机配置常量 */
|
||||
#define LINEAR_MOTOR_I2C_SLAVE_ADDR 0x5A // 线性马达的I2C从机地址
|
||||
|
||||
/* 定义陀螺仪的I2C从机配置常量 */
|
||||
#define GYROSCOPE_I2C_SLAVE_ADDR 0x6A // 陀螺仪的I2C从机地址
|
||||
#define GYROSCOPE_INPUT_PIN_SEL GPIO_NUM_21 // 陀螺仪中断引脚
|
||||
|
||||
/* AW触摸芯片配置 */
|
||||
#define AW_TOUCH_IRQ_PIN GPIO_NUM_11 // AW触摸芯片中断引脚
|
||||
#define NFC_RST_PIN GPIO_NUM_12 // NFC复位引脚
|
||||
#define SHUTDOWN_CTRL_PIN GPIO_NUM_13 // 关机控制引脚
|
||||
|
||||
/* 原生触摸引脚配置 (v1.1.17已改为上述功能,保留定义需谨慎) */
|
||||
// 触摸按键数量配置
|
||||
#define TOUCH_BUTTON_NUM 3
|
||||
// 触摸通道定义 - 注意:v1.1.17如果不使用ESP32原生触摸,这些定义可能不再适用
|
||||
// 但为了兼容编译,可以保留或注释
|
||||
#define TOUCH_PAD_CHANNEL_1 TOUCH_PAD_NUM11 // GPIO11 (Now AW_IRQ)
|
||||
#define TOUCH_PAD_CHANNEL_2 TOUCH_PAD_NUM12 // GPIO12 (Now NFC_RST)
|
||||
#define TOUCH_PAD_CHANNEL_3 TOUCH_PAD_NUM13 // GPIO13 (Now SHUTDOWN)
|
||||
|
||||
/* ES8311音频编解码器配置 (ESP-ADF兼容) */
|
||||
#define AUDIO_INPUT_SAMPLE_RATE 24000
|
||||
#define AUDIO_OUTPUT_SAMPLE_RATE 24000
|
||||
#define AUDIO_INPUT_REFERENCE true
|
||||
|
||||
/* I2S GPIO定义 */
|
||||
#define AUDIO_I2S_GPIO_MCLK GPIO_NUM_15
|
||||
#define AUDIO_I2S_GPIO_WS GPIO_NUM_4
|
||||
#define AUDIO_I2S_GPIO_BCLK GPIO_NUM_5
|
||||
#define AUDIO_I2S_GPIO_DIN GPIO_NUM_6
|
||||
#define AUDIO_I2S_GPIO_DOUT GPIO_NUM_7
|
||||
|
||||
/* PA引脚定义 */
|
||||
#define AUDIO_CODEC_PA_PIN GPIO_NUM_NC
|
||||
|
||||
/* I2C配置 */
|
||||
#define AUDIO_CODEC_I2C_SDA_PIN GPIO_NUM_2
|
||||
#define AUDIO_CODEC_I2C_SCL_PIN GPIO_NUM_3
|
||||
#define AUDIO_CODEC_ES8311_ADDR 0x18
|
||||
#define AUDIO_CODEC_ES7210_ADDR 0x40
|
||||
|
||||
/* WS2812 RGB LED配置 */
|
||||
#define WS2812_PIN GPIO_NUM_41 // WS2812数据引脚
|
||||
#define WS2812_NUM_LEDS 2 // WS2812 LED数量
|
||||
|
||||
/* 创建VBAT to VBAT_5V */
|
||||
#define VBAT_5V_PIN GPIO_NUM_NC // VBAT_5V引脚
|
||||
|
||||
/* 定义按键的中断引脚 */
|
||||
#define BUTTON_PIN GPIO_NUM_0 // 按键中断引脚
|
||||
#define RIGHT_BUTTON_PIN GPIO_NUM_8 // 按键中断引脚
|
||||
|
||||
/* 底座控制命令串口配置 */
|
||||
#define BASE_BOARD_CTL_UART_PORT UART_NUM_0
|
||||
#define BASE_BOARD_CTL_UART_TX_PIN GPIO_NUM_43
|
||||
#define BASE_BOARD_CTL_UART_RX_PIN GPIO_NUM_44
|
||||
#define BASE_BOARD_CTL_UART_BAUDRATE 115200
|
||||
#define BASE_BOARD_CTL_UART_BUF_SIZE 256
|
||||
|
||||
/* 背光控制引脚配置 */
|
||||
#define BL_PIN GPIO_NUM_45
|
||||
|
||||
#endif // _BOARD_CONFIG_H_
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,432 @@
|
||||
#ifndef IO_EXPANSION_BOARD_H
|
||||
#define IO_EXPANSION_BOARD_H
|
||||
|
||||
#include <cstdint>
|
||||
#include <esp_log.h>
|
||||
#include <esp_check.h>
|
||||
#include <esp_timer.h>
|
||||
#include <driver/gpio.h>
|
||||
#include <functional>
|
||||
#include "i2c_bus.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/event_groups.h"
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
#include <freertos/FreeRTOS.h>
|
||||
#include <freertos/task.h>
|
||||
#include <freertos/queue.h>
|
||||
#include <freertos/semphr.h>
|
||||
#include "esp_err.h"
|
||||
#include "config.h"
|
||||
#include "portmacro.h"
|
||||
|
||||
// 前向声明,避免循环引用
|
||||
class MillimeterWaveRadar;
|
||||
class PhotoInterrupter;
|
||||
class AdcBatteryMonitor;
|
||||
|
||||
// 回调函数类型定义
|
||||
typedef std::function<void()> RadarCallback;
|
||||
typedef std::function<void()> PhotoInterrupterStartCallback;
|
||||
typedef std::function<void()> PhotoInterrupterEndCallback;
|
||||
typedef std::function<void()> BatteryChargingCallback;
|
||||
typedef std::function<void()> BatteryFullCallback;
|
||||
typedef std::function<void()> BatteryNotChargingCallback;
|
||||
|
||||
/* 寄存器地址 */
|
||||
#define INPUT_PORT0 0x00 // 输入端口0寄存器
|
||||
#define INPUT_PORT1 0x01 // 输入端口1寄存器 0为低电平(仅支持读取)
|
||||
#define OUTPUT_PORT0 0x02 // 输出端口0寄存器
|
||||
#define OUTPUT_PORT1 0x03 // 输出端口1寄存器 0为低电平
|
||||
#define CONFIG_PORT0 0x04 // 配置端口0寄存器
|
||||
#define CONFIG_PORT1 0x05 // 配置端口1寄存器 0为输出模式
|
||||
#define INT_PORT0 0x06 // 中断端口0寄存器
|
||||
#define INT_PORT1 0x07 // 中断端口1寄存器 0为使能中断(根据手册默认是使能的)
|
||||
#define CTL 0x11 // 全局控制寄存器
|
||||
#define ID 0x23 // 芯片ID寄存器(0x23)
|
||||
|
||||
/***********************************IO扩展板电机引脚配置参数*************************************/
|
||||
/* 设置步进电机方向 */
|
||||
#define STEPPER_MOTOR_LEFT false //步进电机的方向为左转
|
||||
#define STEPPER_MOTOR_RIGHT true //步进电机的方向为右转
|
||||
#define STEPPER_MOTOR_DIR_PORT OUTPUT_PORT0 //步进电机方向引脚挂载在IO扩展板的输出端口OUTPUT_PORT0
|
||||
#define STEPPER_MOTOR_DIR_PIN 4 //步进电机方向引脚对应的IO扩展板引脚P0_4
|
||||
#define STEPPER_MOTOR_DIR_CONFIG CONFIG_PORT0 //步进电机方向引脚配置在P0_4
|
||||
|
||||
/* 设置步进电机细分模式 */
|
||||
#define STEPPER_MOTOR_M0_PIN 5 //步进电机细分模式选择引脚对应IO扩展板引脚P1_5
|
||||
#define STEPPER_MOTOR_M0_MADE_PORT OUTPUT_PORT1 //步进电机模式选择引脚挂载在IO扩展板的输出端口OUTPUT_PORT1
|
||||
#define STEPPER_MOTOR_M0_CONFIG CONFIG_PORT1 //步进电机细分模式选择引脚配置在P1_5
|
||||
|
||||
#define STEPPER_MOTOR_M1_PIN 4 //步进电机细分模式选择引脚对应IO扩展板引脚P1_4
|
||||
#define STEPPER_MOTOR_M1_MADE_PORT OUTPUT_PORT1 //步进电机模式选择引脚挂载在IO扩展板的输出端口OUTPUT_PORT1
|
||||
#define STEPPER_MOTOR_M1_CONFIG CONFIG_PORT1 //步进电机细分模式选择引脚配置在P1_4
|
||||
|
||||
/* 设置步进电机睡眠引脚 */
|
||||
#define STEPPER_MOTOR_SLEEP false //步进电机进入睡眠模式
|
||||
#define STEPPER_MOTOR_WORK true //步进电机进入工作模式
|
||||
#define STEPPER_MOTOR_SLEEP_PIN 6 //步进电机睡眠引脚对应IO扩展板引脚P1_6
|
||||
#define STEPPER_MOTOR_SLEEP_CONFIG CONFIG_PORT1 //步进电机睡眠引脚配置在P1_6
|
||||
#define STEPPER_MOTOR_SLEEP_PORT OUTPUT_PORT1 //步进电机睡眠引脚挂载在IO扩展板的输出端口OUTPUT_PORT1
|
||||
|
||||
/* 设置电机的使能引脚 */
|
||||
#define STEPPER_MOTOR_ENABLE_PIN 7 //电机使能引脚对应IO扩展板引脚P0_7
|
||||
#define STEPPER_MOTOR_ENABLE_PORT OUTPUT_PORT0 //电机使能引脚挂载在IO扩展板的输出端口OUTPUT_PORT0
|
||||
#define STEPPER_MOTOR_ENABLE_CONFIG CONFIG_PORT0 //电机使能引脚配置在P0_7
|
||||
#define STEPPER_MOTOR_ENABLE_ENABLE true //电机使能引脚状态为高电平
|
||||
#define STEPPER_MOTOR_ENABLE_DISABLE false //电机使能引脚状态为低电平
|
||||
|
||||
/* 设置毫米波雷达对应IO扩展板的中断引脚 */
|
||||
#define RADAR_INTERRUPT_PIN 7 //毫米波雷达中断引脚对应IO扩展板引脚P1_7
|
||||
#define RADAR_INTERRUPT_CONFIG CONFIG_PORT1 //毫米波雷达中断引脚挂载在IO扩展板的输入端口
|
||||
#define RADAR_INTERRUPT_INPUT INPUT_PORT1 //毫米波雷达中断引脚输入状态检测在INPUT_PORT1
|
||||
#define RADAR_INTERRUPT_ENABLE true //毫米波雷达中断引脚状态为输入状态
|
||||
#define RADAR_INTERRUPT_DISABLE false //毫米波雷达中断引脚状态为输出状态
|
||||
/* 任务配置常量 */
|
||||
#define WRITE_BUF_SIZE 2 // I2C单次写入字节数
|
||||
#define READ_BUF_SIZE 2 // I2C单次读取字节数
|
||||
#define I2C_TASK_PRIORITY 2 // 任务优先级(中等)
|
||||
#define I2C_TASK_STACK 4096 // 任务栈大小(4KB)
|
||||
|
||||
// 光学传感器引脚定义
|
||||
#define START_PHOTO_INTERRUPTER_PIN 2 // 光学传感器引脚(P0_2)
|
||||
#define START_PHOTO_INTERRUPTER_CONFIG CONFIG_PORT0 // 光学传感器引脚挂载在IO扩展板的输入端口
|
||||
#define START_PHOTO_INTERRUPTER_INPUT INPUT_PORT0 // 光学传感器引脚输入状态检测在INPUT_PORT0
|
||||
#define START_PHOTO_INTERRUPTER_HIGH true // 光学传感器引脚状态为高电平
|
||||
#define START_PHOTO_INTERRUPTER_LOW false // 光学传感器引脚状态为低电平
|
||||
|
||||
#define END_PHOTO_INTERRUPTER_PIN 3 // 光学传感器引脚(P0_3)
|
||||
#define END_PHOTO_INTERRUPTER_PORT_CONFIG CONFIG_PORT0 // 光学传感器引脚挂载在IO扩展板的输入端口
|
||||
#define END_PHOTO_INTERRUPTER_INPUT INPUT_PORT0 // 光学传感器引脚输入状态检测在INPUT_PORT0
|
||||
#define END_PHOTO_INTERRUPTER_HIGH true // 光学传感器引脚状态为高电平
|
||||
#define END_PHOTO_INTERRUPTER_LOW false // 光学传感器引脚状态为低电平
|
||||
|
||||
/***********************************IO扩展板LCD引脚配置参数*************************************/
|
||||
// /* 设置LCD的BL引脚 */
|
||||
// #define LCD_BL_PIN 6 //LCD背光引脚对应IO扩展板引脚P0_6
|
||||
// #define LCD_BL_PORT OUTPUT_PORT0 //LCD背光引脚挂载在IO扩展板的输出端口OUTPUT_PORT0
|
||||
// #define LCD_BL_CONFIG CONFIG_PORT0 //LCD背光引脚配置在P0_6
|
||||
// #define LCD_BL_HIGH true //LCD背光引脚状态为高电平
|
||||
// #define LCD_BL_LOW false //LCD背光引脚状态为低电平
|
||||
|
||||
/* 设置LED_EN (LCD背光/LED控制)引脚, PMOS高侧驱动 */
|
||||
#define LED_EN_PIN 1 //LED_EN对应IO扩展板引脚P0_1
|
||||
#define LED_EN_PORT OUTPUT_PORT0 //挂载在输出端口OUTPUT_PORT0
|
||||
#define LED_EN_CONFIG CONFIG_PORT0 //配置在P0_1
|
||||
#define LED_EN_OFF true //高电平关(PMOS)
|
||||
#define LED_EN_ON false //低电平开(PMOS)
|
||||
|
||||
/* 设置LCD的RST引脚 */
|
||||
#define LCD_RST_PIN 1 //LCD复位引脚对应IO扩展板引脚P1_1
|
||||
#define LCD_RST_CONFIG CONFIG_PORT1 //LCD复位引脚配置在P1_1
|
||||
#define LCD_RST_PORT OUTPUT_PORT1 //LCD复位引脚挂载在IO扩展板的输出端口OUTPUT_PORT1
|
||||
#define LCD_RST_HIGH true //LCD复位引脚状态为高电平
|
||||
#define LCD_RST_LOW false //LCD复位引脚状态为低电平
|
||||
|
||||
/* 设置PA控制引脚 */
|
||||
#define PA_CTRL_PIN 2 //PA控制引脚对应IO扩展板引脚P1_2
|
||||
#define PA_CTRL_CONFIG CONFIG_PORT1 //PA控制引脚配置在P1_2
|
||||
#define PA_CTRL_PORT OUTPUT_PORT1 //PA控制引脚挂载在IO扩展板的输出端口OUTPUT_PORT1
|
||||
#define PA_CTRL_HIGH true //PA控制引脚状态为高电平
|
||||
#define PA_CTRL_LOW false //PA控制引脚状态为低电平
|
||||
|
||||
// 电池充电检测引脚定义
|
||||
#define BATTERY_FULL_INPUT INPUT_PORT1 // 电池充满检测引脚挂载在IO扩展板的输入端口
|
||||
#define BATTERY_FULL_PIN 3 // 电池充满检测引脚对应IO扩展板引脚P1_3
|
||||
#define BATTERY_FULL_CONFIG CONFIG_PORT1 // 电池充满检测引脚配置在P1_3
|
||||
|
||||
#define BATTERY_CHRG_INPUT INPUT_PORT0 // 充电检测引脚挂载在IO扩展板的输入端口
|
||||
#define BATTERY_CHRG_PIN 5 // 充电检测引脚(P0_5)
|
||||
#define BATTERY_CHRG_CONFIG CONFIG_PORT0 // 充电检测引脚挂载在IO扩展板的输入端口
|
||||
|
||||
#define TAG_GPIO_IO_EXPAND_DETECT "GPIO_IO_EXPAND_DETECT" // GPIO中断检测日志标签
|
||||
#define TAG_I2C_IO_EXPAND_TASK "I2C_IO_EXPAND_TASK" // I2CIO扩展板任务日志标签
|
||||
|
||||
// GPIO引脚定义
|
||||
#define GPIO_INPUT_PIN_SEL GPIO_NUM_10 // IO扩展板中断检测引脚
|
||||
// #define IO_EXPAND_RSTN GPIO_NUM_14 // IO扩展板复位引脚
|
||||
|
||||
/**
|
||||
* @class IOExpansionBoard
|
||||
* @brief I/O扩展板驱动类,封装AW9523BTQR芯片操作
|
||||
*/
|
||||
class IOExpansionBoard
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief 构造函数
|
||||
*/
|
||||
IOExpansionBoard();
|
||||
|
||||
/**
|
||||
* @brief 设置毫米波雷达指针
|
||||
* @param radar 毫米波雷达对象指针
|
||||
*/
|
||||
void SetRadar(MillimeterWaveRadar* radar) { radar_ = radar; };
|
||||
|
||||
/**
|
||||
* @brief 设置限位开关指针
|
||||
* @param photo_interrupter 限位开关对象指针
|
||||
*/
|
||||
void setPhotoInterrupter(PhotoInterrupter* photo_interrupter) { photo_interrupter_ = photo_interrupter; };
|
||||
|
||||
/**
|
||||
* @brief 设置电池监控器指针
|
||||
* @param battery_monitor 电池监控器对象指针
|
||||
*/
|
||||
void setBatteryMonitor(AdcBatteryMonitor* battery_monitor) { battery_monitor_ = battery_monitor; };
|
||||
|
||||
/**
|
||||
* @brief 析构函数
|
||||
*/
|
||||
~IOExpansionBoard();
|
||||
|
||||
/**
|
||||
* @brief 初始化GPIO中断检测
|
||||
* @param gpio_num 中断引脚编号
|
||||
* @return esp_err_t 初始化结果
|
||||
*/
|
||||
esp_err_t InterruptGpioInit(gpio_num_t gpio_num);
|
||||
|
||||
/**
|
||||
* @brief 初始化IO扩展板复位引脚
|
||||
* @param gpio_num 复位引脚编号
|
||||
* @return esp_err_t 初始化结果
|
||||
*/
|
||||
esp_err_t ResetGpioInit(gpio_num_t gpio_num);
|
||||
|
||||
/**
|
||||
* @brief 初始化IO扩展板复位引脚
|
||||
* @param gpio_num 复位引脚编号
|
||||
* @return esp_err_t 初始化结果
|
||||
*/
|
||||
esp_err_t ResetIoExpand();
|
||||
|
||||
/**
|
||||
* @brief 初始化I2C主机通信
|
||||
* @return esp_err_t 初始化结果
|
||||
*/
|
||||
// esp_err_t IoExpansionI2cInit();
|
||||
|
||||
/**
|
||||
* @brief 创建I2C数据读取任务
|
||||
*/
|
||||
void CreateI2cReadTask();
|
||||
|
||||
/**
|
||||
* @brief 启动I2C任务(整合初始化和任务创建)
|
||||
* @return esp_err_t 操作结果
|
||||
*/
|
||||
esp_err_t StartTask();
|
||||
|
||||
/**
|
||||
* @brief 写寄存器数据
|
||||
* @param reg_addr 寄存器地址
|
||||
* @param data 要写入的数据
|
||||
* @return esp_err_t 操作结果
|
||||
*/
|
||||
esp_err_t IoexpandWriteReg(uint8_t reg_addr, uint8_t data);
|
||||
|
||||
/**
|
||||
* @brief 读寄存器数据
|
||||
* @param reg_addr 寄存器地址
|
||||
* @param data 要读出的数据
|
||||
* @return esp_err_t 操作结果
|
||||
*/
|
||||
esp_err_t IoexpandReadReg(uint8_t reg_addr, uint8_t *data);
|
||||
|
||||
/**
|
||||
* @brief 读取输入端口0寄存器数据
|
||||
* @param data 输出参数,用于存储读取到的数据
|
||||
* @return esp_err_t 操作结果
|
||||
*/
|
||||
esp_err_t ReadInputPort0(uint8_t *data);
|
||||
|
||||
/**
|
||||
* @brief 读取输入端口1寄存器数据
|
||||
* @param data 输出参数,用于存储读取到的数据
|
||||
* @return esp_err_t 操作结果
|
||||
*/
|
||||
esp_err_t ReadInputPort1(uint8_t *data);
|
||||
|
||||
// /**
|
||||
// * @brief 设置IO扩展板GPIO中断状态 通过读取Input_Port0 和 Input_Port1 寄存器可以清除中断
|
||||
// * @param reg_addr 寄存器地址
|
||||
// * @return esp_err_t 操作结果
|
||||
// */
|
||||
// esp_err_t SetInterruptStatus(bool status);
|
||||
|
||||
/**
|
||||
* @brief 配置IO扩展版上的IO口为输出还是输入,并且设置初始为高电平
|
||||
* @return esp_err_t 操作结果
|
||||
*/
|
||||
esp_err_t IoexpandSetMode();
|
||||
|
||||
/**
|
||||
* @brief 设置步进电机的细分模式
|
||||
* @param mode 模式:1/2/4/8/16/32/64
|
||||
* @return esp_err_t 操作结果
|
||||
*/
|
||||
void SetStepperMicrostepMode(uint8_t mode, uint8_t OUTPUT_PORT_m0, uint8_t m0_pin, uint8_t OUTPUT_PORT_m1, uint8_t m1_pin);
|
||||
|
||||
/**
|
||||
* @brief 设置步进电机的方向
|
||||
* @param dir 方向
|
||||
* @param OUTPUT_PORT 输出端口
|
||||
* @param pin 引脚号
|
||||
* @return esp_err_t 操作结果
|
||||
*/
|
||||
esp_err_t StepperMotorSetDir(bool dir, uint8_t OUTPUT_PORT, uint8_t pin);
|
||||
|
||||
/**
|
||||
* @brief 设置步进电机的睡眠模式
|
||||
* @param 是否进入睡眠模式
|
||||
* @param 输出端口
|
||||
* @param 引脚号
|
||||
* @return esp_err_t 操作结果
|
||||
*/
|
||||
esp_err_t SetMotorSleepMode(bool mode, uint8_t OUTPUT_PORT, uint8_t nsleep_pin);
|
||||
|
||||
/**
|
||||
* @brief 设置步进电机的使能引脚状态
|
||||
* @param 使能状态
|
||||
* @return esp_err_t 操作结果
|
||||
*/
|
||||
esp_err_t SetMotorEnableMode(bool enable, uint8_t OUTPUT_PORT, uint8_t enable_pin);
|
||||
|
||||
/**
|
||||
* @brief 设置LCD的BL引脚状态
|
||||
* @param BL状态
|
||||
* @return esp_err_t 操作结果
|
||||
*/
|
||||
esp_err_t SetLcdBlMode(bool mode, uint8_t OUTPUT_PORT, uint8_t bl_pin);
|
||||
|
||||
/**
|
||||
* @brief 设置 LED_EN 引脚电平(用于控制LCD背光/LED灯电源)
|
||||
* @param mode true:开启(低电平), false:关闭(高电平)
|
||||
*/
|
||||
esp_err_t SetLedEnMode(bool mode);
|
||||
|
||||
/**
|
||||
* @brief 设置LCD的RST引脚状态
|
||||
* @param RST状态
|
||||
* @return esp_err_t 操作结果
|
||||
*/
|
||||
esp_err_t SetLcdResetMode(bool mode, uint8_t OUTPUT_PORT, uint8_t rst_pin);
|
||||
|
||||
/**
|
||||
* @brief 设置PA控制引脚状态
|
||||
* @param mode PA_CTRL状态(true为高电平,false为低电平)
|
||||
* @return esp_err_t 操作结果
|
||||
*/
|
||||
esp_err_t SetPaCtrlMode(bool mode);
|
||||
|
||||
/**
|
||||
* @brief 设置雷达中断引脚
|
||||
* @param 毫米波雷达的中断引脚模式
|
||||
* @param 输入端口
|
||||
* @param 引脚号
|
||||
* @return esp_err_t 操作结果
|
||||
*/
|
||||
esp_err_t SetRadarInterruptPin(bool mode, uint8_t INPUT_PORT, uint8_t interrupt_pin);
|
||||
|
||||
/**
|
||||
* @brief 计算Port0的字节值
|
||||
* @return uint8_t 操作结果
|
||||
*/
|
||||
uint8_t ByteCalculatePort0();
|
||||
|
||||
/**
|
||||
* @brief 计算Port1的字节值
|
||||
* @return uint8_t 操作结果
|
||||
*/
|
||||
uint8_t ByteCalculatePort1();
|
||||
|
||||
/**
|
||||
* @brief 设置雷达中断回调函数
|
||||
* @param callback 雷达中断回调函数
|
||||
*/
|
||||
void SetRadarCallback(RadarCallback callback) { radar_callback_ = callback; }
|
||||
|
||||
/**
|
||||
* @brief 设置光学传感器开始中断回调函数
|
||||
* @param callback 光学传感器开始中断回调函数
|
||||
*/
|
||||
void SetPhotoInterrupterStartCallback(PhotoInterrupterStartCallback callback) { photo_start_callback_ = callback; }
|
||||
|
||||
/**
|
||||
* @brief 设置光学传感器结束中断回调函数
|
||||
* @param callback 光学传感器结束中断回调函数
|
||||
*/
|
||||
void SetPhotoInterrupterEndCallback(PhotoInterrupterEndCallback callback) { photo_end_callback_ = callback; }
|
||||
|
||||
/**
|
||||
* @brief 设置电池充电中断回调函数
|
||||
* @param callback 电池充电中断回调函数
|
||||
*/
|
||||
void SetBatteryChargingCallback(BatteryChargingCallback callback) { battery_charging_callback_ = callback; }
|
||||
|
||||
/**
|
||||
* @brief 设置电池充满中断回调函数
|
||||
* @param callback 电池充满中断回调函数
|
||||
*/
|
||||
void SetBatteryFullCallback(BatteryFullCallback callback) { battery_full_callback_ = callback; }
|
||||
|
||||
/**
|
||||
* @brief 设置电池非充电中断回调函数
|
||||
* @param callback 电池非充电中断回调函数
|
||||
*/
|
||||
void SetBatteryNotChargingCallback(BatteryNotChargingCallback callback) { battery_not_charging_callback_ = callback; }
|
||||
|
||||
// 公共成员变量
|
||||
i2c_bus_handle_t bus_handle_ = nullptr; // I2C总线句柄
|
||||
uint8_t device_addr_; // I2C设备地址
|
||||
|
||||
private:
|
||||
// 静态成员函数
|
||||
MillimeterWaveRadar* radar_ = nullptr; // 毫米波雷达指针,用于触发回调
|
||||
PhotoInterrupter* photo_interrupter_ = nullptr; // 限位开关指针,用于触发回调
|
||||
AdcBatteryMonitor* battery_monitor_ = nullptr; // 电池监控器指针,用于触发回调
|
||||
static void IRAM_ATTR GpioIsrHandler(void* arg); // 中断处理函数
|
||||
static void I2cReadTask(void* pvParameters); // I2C数据读取任务函数
|
||||
|
||||
// 成员变量用于状态跟踪
|
||||
uint8_t last_port0_state_ = 0; // 上次检测到的Port0状态
|
||||
uint8_t last_port1_state_ = 0; // 上次检测到的Port1状态
|
||||
bool radar_last_state_ = false; // 雷达引脚上一次的状态
|
||||
bool battery_charging_last_state_ = false; // 电池充电状态上一次的状态
|
||||
bool battery_full_last_state_ = false; // 电池充满状态上一次的状态
|
||||
|
||||
// 回调函数成员变量
|
||||
RadarCallback radar_callback_ = nullptr;
|
||||
PhotoInterrupterStartCallback photo_start_callback_ = nullptr;
|
||||
PhotoInterrupterEndCallback photo_end_callback_ = nullptr;
|
||||
BatteryChargingCallback battery_charging_callback_ = nullptr;
|
||||
BatteryFullCallback battery_full_callback_ = nullptr;
|
||||
BatteryNotChargingCallback battery_not_charging_callback_ = nullptr;
|
||||
|
||||
// PhotoInterrupter* photo_interrupter_ = nullptr; // 光学传感器指针,用于触发回调
|
||||
// /**
|
||||
// * @brief 分配静态任务所需的内存
|
||||
// * @return bool 分配是否成功
|
||||
// */
|
||||
// bool AllocateStaticTaskMemory();
|
||||
|
||||
// /**
|
||||
// * @brief 释放静态任务分配的内存
|
||||
// */
|
||||
// void FreeStaticTaskMemory();
|
||||
|
||||
// 实例成员变量
|
||||
EventGroupHandle_t i2c_task_event_group_ = nullptr; // 事件组
|
||||
TaskHandle_t xI2CReadTaskHandle_ = nullptr; // 任务句柄
|
||||
bool is_initialized_ = false; // 初始化状态标记(新增)
|
||||
gpio_num_t interrupt_gpio_ = GPIO_NUM_NC; // 中断引脚
|
||||
gpio_num_t reset_gpio_ = GPIO_NUM_NC; // 复位引脚
|
||||
|
||||
// StackType_t* pI2CReadTaskStackBuffer = nullptr; // 任务栈指针(PSRAM)
|
||||
// StaticTask_t* pxI2CReadTaskBuffer = nullptr; // 任务控制块指针(内部RAM)
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,178 @@
|
||||
/**
|
||||
* @file power_management_config.h
|
||||
* @brief 功耗管理配置和策略定义
|
||||
* @author Embedded Software Expert
|
||||
* @date 2025年1月
|
||||
*
|
||||
* 这个文件定义了功耗管理的配置参数、策略和优化建议,
|
||||
* 为系统提供灵活的功耗管理方案。
|
||||
*/
|
||||
|
||||
#ifndef POWER_MANAGEMENT_CONFIG_H
|
||||
#define POWER_MANAGEMENT_CONFIG_H
|
||||
|
||||
#include "esp_sleep.h"
|
||||
#include "driver/rtc_io.h"
|
||||
#include "esp32/rom/rtc.h"
|
||||
|
||||
/**
|
||||
* @brief 功耗管理配置结构体
|
||||
*/
|
||||
typedef struct {
|
||||
// 睡眠模式配置
|
||||
uint64_t light_sleep_duration_us; // 轻度睡眠持续时间(微秒)
|
||||
uint64_t deep_sleep_duration_us; // 深度睡眠持续时间(微秒)
|
||||
|
||||
// 唤醒源配置
|
||||
bool enable_timer_wakeup; // 启用定时器唤醒
|
||||
bool enable_gpio_wakeup; // 启用GPIO唤醒
|
||||
bool enable_touch_wakeup; // 启用触摸唤醒
|
||||
gpio_num_t wakeup_gpio_num; // 唤醒GPIO编号
|
||||
int wakeup_level; // 唤醒电平(0或1)
|
||||
|
||||
// 功耗优化配置
|
||||
bool disable_bt_in_sleep; // 睡眠时关闭蓝牙
|
||||
bool disable_wifi_in_sleep; // 睡眠时关闭WiFi
|
||||
bool reduce_cpu_frequency; // 降低CPU频率
|
||||
uint32_t cpu_frequency_hz; // CPU频率(Hz)
|
||||
|
||||
// 外设功耗配置
|
||||
bool power_down_sdcard; // 睡眠时关闭SD卡电源
|
||||
bool power_down_display; // 睡眠时关闭显示电源
|
||||
bool power_down_audio; // 睡眠时关闭音频电源
|
||||
bool power_down_motor; // 睡眠时关闭电机电源
|
||||
|
||||
// RTC内存配置
|
||||
bool preserve_rtc_memory; // 保留RTC内存
|
||||
size_t rtc_memory_size; // RTC内存大小
|
||||
} power_management_config_t;
|
||||
|
||||
/**
|
||||
* @brief 默认功耗管理配置
|
||||
*/
|
||||
#define DEFAULT_POWER_CONFIG { \
|
||||
.light_sleep_duration_us = 1000000, /* 1秒 */ \
|
||||
.deep_sleep_duration_us = 30000000, /* 30秒 */ \
|
||||
.enable_timer_wakeup = true, /* 启用定时器唤醒 */ \
|
||||
.enable_gpio_wakeup = false, /* 不启用GPIO唤醒 */ \
|
||||
.enable_touch_wakeup = false, /* 不启用触摸唤醒 */ \
|
||||
.wakeup_gpio_num = GPIO_NUM_NC, /* 无GPIO唤醒 */ \
|
||||
.wakeup_level = 0, /* 低电平唤醒 */ \
|
||||
.disable_bt_in_sleep = true, /* 睡眠时关闭蓝牙 */ \
|
||||
.disable_wifi_in_sleep = true, /* 睡眠时关闭WiFi */ \
|
||||
.reduce_cpu_frequency = true, /* 降低CPU频率 */ \
|
||||
.cpu_frequency_hz = 80000000, /* 80MHz */ \
|
||||
.power_down_sdcard = true, /* 睡眠时关闭SD卡 */ \
|
||||
.power_down_display = true, /* 睡眠时关闭显示 */ \
|
||||
.power_down_audio = true, /* 睡眠时关闭音频 */ \
|
||||
.power_down_motor = true, /* 睡眠时关闭电机 */ \
|
||||
.preserve_rtc_memory = true, /* 保留RTC内存 */ \
|
||||
.rtc_memory_size = 4096, /* 4KB RTC内存 */ \
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 各功耗模式的详细配置
|
||||
*/
|
||||
static const power_management_config_t idle_mode_config = {
|
||||
.light_sleep_duration_us = 500000, // 500ms轻度睡眠
|
||||
.deep_sleep_duration_us = 0, // 不使用深度睡眠
|
||||
.enable_timer_wakeup = true,
|
||||
.enable_gpio_wakeup = true,
|
||||
.wakeup_gpio_num = GPIO_NUM_0, // 按键唤醒
|
||||
.wakeup_level = 0,
|
||||
.disable_bt_in_sleep = false, // 保持蓝牙连接
|
||||
.disable_wifi_in_sleep = false, // 保持WiFi连接
|
||||
.reduce_cpu_frequency = true,
|
||||
.cpu_frequency_hz = 40000000, // 40MHz
|
||||
.power_down_sdcard = false, // 保持SD卡(可能有后台任务)
|
||||
.power_down_display = true, // 关闭显示背光
|
||||
.power_down_audio = true, // 关闭音频
|
||||
.power_down_motor = true, // 关闭电机
|
||||
.preserve_rtc_memory = true,
|
||||
.rtc_memory_size = 2048,
|
||||
};
|
||||
|
||||
static const power_management_config_t light_sleep_config = {
|
||||
.light_sleep_duration_us = 0, // 直接进入轻度睡眠
|
||||
.deep_sleep_duration_us = 0,
|
||||
.enable_timer_wakeup = true,
|
||||
.enable_gpio_wakeup = true,
|
||||
.wakeup_gpio_num = GPIO_NUM_0,
|
||||
.wakeup_level = 0,
|
||||
.disable_bt_in_sleep = true, // 关闭蓝牙
|
||||
.disable_wifi_in_sleep = true, // 关闭WiFi
|
||||
.reduce_cpu_frequency = true,
|
||||
.cpu_frequency_hz = 40000000,
|
||||
.power_down_sdcard = true, // 关闭SD卡
|
||||
.power_down_display = true, // 关闭显示
|
||||
.power_down_audio = true, // 关闭音频
|
||||
.power_down_motor = true, // 关闭电机
|
||||
.preserve_rtc_memory = true,
|
||||
.rtc_memory_size = 4096,
|
||||
};
|
||||
|
||||
static const power_management_config_t deep_sleep_config = {
|
||||
.light_sleep_duration_us = 0,
|
||||
.deep_sleep_duration_us = 60000000, // 60秒深度睡眠
|
||||
.enable_timer_wakeup = true,
|
||||
.enable_gpio_wakeup = true,
|
||||
.wakeup_gpio_num = GPIO_NUM_0,
|
||||
.wakeup_level = 0,
|
||||
.disable_bt_in_sleep = true, // 关闭蓝牙
|
||||
.disable_wifi_in_sleep = true, // 关闭WiFi
|
||||
.reduce_cpu_frequency = true,
|
||||
.cpu_frequency_hz = 10000000, // 10MHz
|
||||
.power_down_sdcard = true, // 关闭SD卡
|
||||
.power_down_display = true, // 关闭显示
|
||||
.power_down_audio = true, // 关闭音频
|
||||
.power_down_motor = true, // 关闭电机
|
||||
.preserve_rtc_memory = true,
|
||||
.rtc_memory_size = 8192,
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 功耗统计和监控结构体
|
||||
*/
|
||||
typedef struct {
|
||||
uint64_t total_sleep_time_us; // 总睡眠时间
|
||||
uint64_t total_wake_time_us; // 总唤醒时间
|
||||
uint32_t sleep_count; // 睡眠次数
|
||||
uint32_t wake_count; // 唤醒次数
|
||||
uint32_t average_sleep_duration_us; // 平均睡眠时长
|
||||
uint32_t average_wake_duration_us; // 平均唤醒时长
|
||||
float estimated_power_saving_percent; // 估计的功耗节省百分比
|
||||
} power_statistics_t;
|
||||
|
||||
/**
|
||||
* @brief 功耗优化建议
|
||||
*
|
||||
* 基于硬件特性和使用模式,提供功耗优化建议
|
||||
*/
|
||||
typedef enum {
|
||||
OPTIMIZATION_NONE = 0,
|
||||
OPTIMIZATION_REDUCE_CPU_FREQ, // 降低CPU频率
|
||||
OPTIMIZATION_DISABLE_UNUSED_PERIPHERALS, // 关闭未使用的外设
|
||||
OPTIMIZATION_USE_LIGHT_SLEEP, // 使用轻度睡眠
|
||||
OPTIMIZATION_USE_DEEP_SLEEP, // 使用深度睡眠
|
||||
OPTIMIZATION_OPTIMIZE_GPIO_STATES, // 优化GPIO状态
|
||||
OPTIMIZATION_USE_RTC_MEMORY, // 使用RTC内存
|
||||
OPTIMIZATION_BATCH_OPERATIONS, // 批量操作
|
||||
} power_optimization_t;
|
||||
|
||||
/**
|
||||
* @brief 功耗管理事件回调
|
||||
*/
|
||||
typedef void (*power_event_callback_t)(power_mode_t old_mode, power_mode_t new_mode, void* user_data);
|
||||
|
||||
/**
|
||||
* @brief 功耗管理事件
|
||||
*/
|
||||
typedef enum {
|
||||
POWER_EVENT_MODE_CHANGE, // 功耗模式改变
|
||||
POWER_EVENT_SLEEP_START, // 睡眠开始
|
||||
POWER_EVENT_SLEEP_END, // 睡眠结束
|
||||
POWER_EVENT_WAKEUP, // 系统唤醒
|
||||
POWER_EVENT_OPTIMIZATION_TRIGGER, // 功耗优化触发
|
||||
} power_event_t;
|
||||
|
||||
#endif // POWER_MANAGEMENT_CONFIG_H
|
||||
@@ -0,0 +1,778 @@
|
||||
/**
|
||||
* @file board.cc
|
||||
* @brief 板级外设初始化类,包含步进电机、毫米波雷达、I2C总线等外设的初始化函数。
|
||||
* @author zouyuhua
|
||||
* @date 2025年8月7日
|
||||
*
|
||||
*/
|
||||
|
||||
extern "C" {
|
||||
#include "esp_log.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "driver/uart.h"
|
||||
#include "driver/ledc.h"
|
||||
#include "driver/gptimer.h"
|
||||
#include "esp_err.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "hal/gpio_types.h"
|
||||
#include "hal/uart_types.h"
|
||||
#include "esp_check.h"
|
||||
#include "sdkconfig.h"
|
||||
#include "i2c_bus.h"
|
||||
#include "esp_peripherals.h"
|
||||
#include "periph_sdcard.h"
|
||||
#include "esp_sleep.h"
|
||||
#include "driver/rtc_io.h"
|
||||
}
|
||||
|
||||
#include "board_sweekar.h"
|
||||
#include "config.h"
|
||||
#include "board.h" // 添加board.h以获取audio_board_sdcard_init函数声明
|
||||
#include "drv8428.h"
|
||||
#include "aw8646.h"
|
||||
#include "esp_vfs_fat.h"
|
||||
#include "audio_mem.h"
|
||||
#include "esp_timer.h"
|
||||
#include "base_board_hal_i2c.h"
|
||||
|
||||
#define TAG "board_sweekar"
|
||||
|
||||
static BoardSweekar* s_board_instance = nullptr;
|
||||
|
||||
BoardSweekar* BoardSweekar::GetInstance()
|
||||
{
|
||||
if (s_board_instance == nullptr) {
|
||||
static BoardSweekar global_board;
|
||||
s_board_instance = &global_board;
|
||||
}
|
||||
return s_board_instance;
|
||||
}
|
||||
|
||||
BoardSweekar::BoardSweekar()
|
||||
{
|
||||
#ifdef CONFIG_STEPPER_DRIVER_AW8646
|
||||
stepper_driver_ = new Aw8646Driver(io_expansion_);
|
||||
#else
|
||||
stepper_driver_ = new Drv8428Driver(io_expansion_);
|
||||
#endif
|
||||
}
|
||||
|
||||
BoardSweekar::~BoardSweekar()
|
||||
{
|
||||
if (stepper_driver_) {
|
||||
delete stepper_driver_;
|
||||
stepper_driver_ = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void BoardSweekar::SetAudioAmplifier(bool enable) {
|
||||
// AUD_CTRL 是 codec 侧控制脚,不参与 PA 开关;PA 仍由 IO 扩展板控制。
|
||||
io_expansion_.SetPaCtrlMode(enable);
|
||||
ESP_LOGI(TAG, "Audio Amplifier (via IO Expansion) %s", enable ? "ENABLED" : "DISABLED");
|
||||
}
|
||||
|
||||
/*========================== 步进电机相关驱动 ==========================*/
|
||||
|
||||
/**
|
||||
* @brief 步进电机初始化函数
|
||||
* 配置步进电机所需的GPIO引脚模式,通过IO扩展板设置步进驱动芯片的工作模式
|
||||
* 在 stepper_motor.cc 中完成 GPTimer + GPIO 翻转 STEP 脉冲的初始化
|
||||
*/
|
||||
void BoardSweekar::StepperMotorInit(void)
|
||||
{
|
||||
esp_err_t err = ESP_OK;
|
||||
|
||||
// 1) STEP 引脚改为普通 GPIO(不再用 LEDC)
|
||||
gpio_config_t io_cfg;
|
||||
io_cfg.pin_bit_mask = 1ULL << STEPPER_STEP_IO;
|
||||
io_cfg.mode = GPIO_MODE_OUTPUT;
|
||||
io_cfg.pull_up_en = GPIO_PULLUP_DISABLE;
|
||||
io_cfg.pull_down_en = GPIO_PULLDOWN_DISABLE;
|
||||
io_cfg.intr_type = GPIO_INTR_DISABLE;
|
||||
err = gpio_config(&io_cfg);
|
||||
if (err != ESP_OK)
|
||||
{
|
||||
ESP_LOGE(TAG_BOARD, "步进电机 STEP GPIO 配置失败, 错误码: 0x%x", err);
|
||||
}
|
||||
|
||||
// 初始电平拉低,保证上电不乱跳
|
||||
gpio_set_level(STEPPER_STEP_IO, 0);
|
||||
|
||||
// 2) 检查 I2C 总线是否已初始化
|
||||
if (bus_handle_ == nullptr)
|
||||
{
|
||||
ESP_LOGE(TAG_BOARD, "I2C总线未初始化,请先调用I2CMasterInit()");
|
||||
return;
|
||||
}
|
||||
|
||||
// 3) 初始化驱动对象并初始化
|
||||
if (stepper_driver_) {
|
||||
err = stepper_driver_->Init();
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG_BOARD, "步进电机驱动初始化失败, 错误码: 0x%x", err);
|
||||
}
|
||||
} else {
|
||||
ESP_LOGE(TAG_BOARD, "步进电机驱动创建失败");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief LCD IO引脚初始化函数(消除与步进电机的耦合)
|
||||
*
|
||||
* 配置LCD所需的IO扩展板寄存器,确保LCD复位引脚正常工作
|
||||
* 此函数独立于步进电机初始化,专门处理LCD相关的IO配置
|
||||
*/
|
||||
void BoardSweekar::LcdIoInit(void)
|
||||
{
|
||||
esp_err_t err = ESP_OK;
|
||||
|
||||
// 1) 检查I2C总线是否已初始化
|
||||
if (bus_handle_ == nullptr)
|
||||
{
|
||||
ESP_LOGE(TAG_BOARD, "I2C总线未初始化,请先调用I2CMasterInit()");
|
||||
return;
|
||||
}
|
||||
|
||||
// 2) 执行硬件复位,确保IO扩展板处于已知状态
|
||||
err = io_expansion_.ResetIoExpand();
|
||||
if (err != ESP_OK)
|
||||
{
|
||||
ESP_LOGE(TAG_BOARD, "IO扩展板硬件复位失败, 错误码: 0x%x", err);
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
ESP_LOGI(TAG_BOARD, "IO扩展板硬件复位成功");
|
||||
}
|
||||
|
||||
// 3) 配置IO扩展板模式(端口方向等)
|
||||
err = io_expansion_.IoexpandSetMode();
|
||||
if (err != ESP_OK)
|
||||
{
|
||||
ESP_LOGE(TAG_BOARD, "IO扩展板模式配置失败, 错误码: 0x%x", err);
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
ESP_LOGI(TAG_BOARD, "IO扩展板模式配置成功");
|
||||
}
|
||||
|
||||
// 4) 初始化LCD复位引脚:设置为高电平
|
||||
err = io_expansion_.SetLcdResetMode(LCD_RST_HIGH, LCD_RST_PORT, LCD_RST_PIN);
|
||||
if (err != ESP_OK)
|
||||
{
|
||||
ESP_LOGE(TAG_BOARD, "LCD复位引脚高电平设置失败, 错误码: 0x%x", err);
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
ESP_LOGI(TAG_BOARD, "LCD复位引脚高电平设置成功");
|
||||
}
|
||||
|
||||
// 5) 初始化LED_EN电源为关闭状态 (PMOS高电平关)
|
||||
// 只有在需要亮灯时,由ActuatorActor主动开启,避免平静状态下常亮
|
||||
err = io_expansion_.SetLedEnMode(false);
|
||||
if (err != ESP_OK)
|
||||
{
|
||||
ESP_LOGE(TAG_BOARD, "初始化LED_EN电源(关闭)失败, 错误码: 0x%x", err);
|
||||
}
|
||||
else
|
||||
{
|
||||
ESP_LOGI(TAG_BOARD, "初始化LED_EN电源(关闭)成功");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 执行系统关机
|
||||
* 内部拉高 SHUTDOWN_CTRL_PIN 引脚切断电源
|
||||
*/
|
||||
void BoardSweekar::SystemShutdown(void)
|
||||
{
|
||||
#ifdef SHUTDOWN_CTRL_PIN
|
||||
ESP_LOGI(TAG, "Executing System Shutdown... Pulling SHUTDOWN_CTRL_PIN (%d) HIGH", SHUTDOWN_CTRL_PIN);
|
||||
// 用户指定:拉高可以完成关机动作
|
||||
gpio_set_level(SHUTDOWN_CTRL_PIN, 1);
|
||||
|
||||
// 给一点时间让电源完全断开
|
||||
vTaskDelay(pdMS_TO_TICKS(1000));
|
||||
#else
|
||||
ESP_LOGW(TAG, "SHUTDOWN_CTRL_PIN is not defined. Cannot execute hardware shutdown.");
|
||||
#endif
|
||||
}
|
||||
|
||||
/*========================== 毫米波雷达相关驱动 ==========================*/
|
||||
|
||||
/**
|
||||
* @brief 毫米波雷达串口初始化函数
|
||||
*
|
||||
* 配置毫米波雷达所使用的串口参数(波特率、数据位、校验位、停止位等),设置串口引脚,
|
||||
* 并安装串口驱动。采用较大的RX/TX FIFO深度以处理突发数据,禁用驱动自带事件队列以避免
|
||||
* 与自定义中断冲突。
|
||||
*/
|
||||
void BoardSweekar::MillimeterWaveRadarUartInit(void)
|
||||
{
|
||||
uart_config_t uart_config = {
|
||||
.baud_rate = RADAR_BAUD_RATE,
|
||||
.data_bits = UART_DATA_8_BITS,
|
||||
.parity = UART_PARITY_DISABLE,
|
||||
.stop_bits = UART_STOP_BITS_1,
|
||||
.flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
|
||||
.source_clk = UART_SCLK_DEFAULT,
|
||||
.flags = {
|
||||
.allow_pd = 0,
|
||||
.backup_before_sleep = 0,
|
||||
},
|
||||
};
|
||||
|
||||
// 1. 设置串口参数
|
||||
ESP_ERROR_CHECK(uart_param_config(RADAR_UART_NUM, &uart_config));
|
||||
|
||||
// 2. 设置 UART 引脚
|
||||
ESP_ERROR_CHECK(uart_set_pin(RADAR_UART_NUM, UART_TX_PIN, UART_RX_PIN,
|
||||
UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE));
|
||||
|
||||
// 3. 安装 UART 驱动(禁用驱动自带事件队列,避免与自定义中断冲突)
|
||||
// 增加 RX/TX FIFO 深度以处理突发数据
|
||||
ESP_ERROR_CHECK(uart_driver_install(RADAR_UART_NUM, RADAR_BUF_SIZE * 4, RADAR_BUF_SIZE * 4,
|
||||
0, NULL, 0));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 毫米波雷达中断引脚初始化函数
|
||||
*
|
||||
* 配置毫米波雷达中断引脚为输入模式,禁用上拉电阻,使能下拉电阻,初始禁用中断功能
|
||||
* (如需使用中断需单独进行配置)。
|
||||
*/
|
||||
void BoardSweekar::MillimeterWaveRadarGpioInit(void)
|
||||
{
|
||||
// GPIO配置结构体
|
||||
gpio_config_t io_conf = {
|
||||
.pin_bit_mask = (1ULL << MILLIMETER_WAVE_RADAR_PIN), // 选择GPIO引脚
|
||||
.mode = GPIO_MODE_INPUT, // 设置为输入模式
|
||||
.pull_up_en = GPIO_PULLUP_DISABLE,
|
||||
.pull_down_en = GPIO_PULLDOWN_ENABLE, // 使能下拉
|
||||
.intr_type = GPIO_INTR_DISABLE // 禁用中断(如需中断需单独配置)
|
||||
};
|
||||
|
||||
// 配置GPIO
|
||||
gpio_config(&io_conf);
|
||||
}
|
||||
|
||||
/*========================== I2C总线及挂载的从设备相关驱动 ==========================*/
|
||||
|
||||
/**
|
||||
* @brief I2C总线及从机设备初始化函数
|
||||
*
|
||||
* 首先配置并创建I2C主机总线,然后依次添加IO扩展板和线性马达作为I2C从机设备到总线上。
|
||||
* 若总线创建或设备添加失败,会输出错误信息并进行相应的资源清理(删除已创建的总线)。
|
||||
* 初始化成功后,会通过ESP_LOGI输出IO扩展板和线性马达的从机地址信息。
|
||||
*
|
||||
* @return esp_err_t 初始化结果,ESP_OK表示成功,其他错误码表示相应的失败原因
|
||||
*/
|
||||
esp_err_t BoardSweekar::I2CMasterInit(void)
|
||||
{
|
||||
static const char *I2C_INIT = "I2C_INIT";
|
||||
|
||||
// 初始化IO扩展板复位引脚
|
||||
gpio_config_t reset_io_conf = {
|
||||
.pin_bit_mask = (1ULL << IO_EXPAND_RSTN),
|
||||
.mode = GPIO_MODE_OUTPUT,
|
||||
.pull_up_en = GPIO_PULLUP_ENABLE, // 使能上拉
|
||||
.pull_down_en = GPIO_PULLDOWN_DISABLE,
|
||||
.intr_type = GPIO_INTR_DISABLE
|
||||
};
|
||||
gpio_config(&reset_io_conf);
|
||||
|
||||
// 执行复位时序:先拉低100ms,再拉高并等待100ms
|
||||
gpio_set_level(IO_EXPAND_RSTN, 0); // 拉低复位
|
||||
vTaskDelay(pdMS_TO_TICKS(100)); // 等待100ms
|
||||
gpio_set_level(IO_EXPAND_RSTN, 1); // 释放复位
|
||||
vTaskDelay(pdMS_TO_TICKS(100)); // 等待设备启动
|
||||
|
||||
ESP_LOGI(I2C_INIT, "IO扩展板复位完成");
|
||||
|
||||
// 创建统一的I2C总线(使用ESP-ADF的i2c_bus)
|
||||
i2c_config_t i2c_cfg = {
|
||||
.mode = I2C_MODE_MASTER,
|
||||
.sda_io_num = I2C0_MASTER_SDA_IO,
|
||||
.scl_io_num = I2C0_MASTER_SCL_IO,
|
||||
.sda_pullup_en = GPIO_PULLUP_ENABLE,
|
||||
.scl_pullup_en = GPIO_PULLUP_ENABLE,
|
||||
.master = {
|
||||
.clk_speed = 100000,
|
||||
},
|
||||
};
|
||||
|
||||
// 创建I2C总线(ESP-ADF的audio_board_init会复用这个总线)
|
||||
bus_handle_ = i2c_bus_create(I2C0_MASTER_PORT, &i2c_cfg);
|
||||
if (bus_handle_ == NULL) {
|
||||
ESP_LOGE(TAG, "Failed to create I2C bus");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
vTaskDelay(pdMS_TO_TICKS(100)); // 等待设备启动
|
||||
// ESP-ADF的i2c_bus不需要单独添加设备,直接通过总线句柄和设备地址进行通信
|
||||
|
||||
// 验证线性马达设备是否存在
|
||||
esp_err_t err = i2c_bus_probe_addr(bus_handle_, LINEAR_MOTOR_I2C_SLAVE_ADDR << 1);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(I2C_INIT, "线性马达设备未找到(地址:0x%02X),错误码: 0x%x", LINEAR_MOTOR_I2C_SLAVE_ADDR, err);
|
||||
// 不返回错误,继续初始化
|
||||
} else {
|
||||
ESP_LOGI(I2C_INIT, "线性马达设备检测成功(地址:0x%02X)", LINEAR_MOTOR_I2C_SLAVE_ADDR);
|
||||
}
|
||||
// 验证IO扩展板设备是否存在
|
||||
err = i2c_bus_probe_addr(bus_handle_, I2C_IO_EXPAND_SLAVE_ADDR << 1);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(I2C_INIT, "IO扩展板设备未找到(地址:0x%02X),错误码: 0x%x", I2C_IO_EXPAND_SLAVE_ADDR, err);
|
||||
// 不返回错误,继续初始化其他设备
|
||||
} else {
|
||||
ESP_LOGI(I2C_INIT, "IO扩展板设备检测成功(地址:0x%02X)", I2C_IO_EXPAND_SLAVE_ADDR);
|
||||
}
|
||||
// 验证陀螺仪设备是否存在
|
||||
err = i2c_bus_probe_addr(bus_handle_, GYROSCOPE_I2C_SLAVE_ADDR << 1);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(I2C_INIT, "陀螺仪设备未找到(地址:0x%02X),错误码: 0x%x", GYROSCOPE_I2C_SLAVE_ADDR, err);
|
||||
// 不返回错误,继续初始化
|
||||
} else {
|
||||
ESP_LOGI(I2C_INIT, "陀螺仪设备检测成功(地址:0x%02X)", GYROSCOPE_I2C_SLAVE_ADDR);
|
||||
}
|
||||
|
||||
// 为IO扩展板设置总线句柄和设备地址(使用7位地址)
|
||||
io_expansion_.bus_handle_ = bus_handle_;
|
||||
io_expansion_.device_addr_ = I2C_IO_EXPAND_SLAVE_ADDR << 1;
|
||||
|
||||
// 线性马达的初始化已移至 InitializeAllHardware 中统一调用 Init 方法
|
||||
// linear_motor_ 的参数传递将在那里完成,不再此处直接赋值,提高内聚性
|
||||
|
||||
ESP_LOGI(I2C_INIT, "I2C总线初始化完成");
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
/*========================== VBAT to VBAT_5V相关驱动 ==========================*/
|
||||
|
||||
/**
|
||||
* @brief 开启VBAT to VBAT_5V
|
||||
*
|
||||
* 创建开启升压的电源管理单元
|
||||
*
|
||||
*/
|
||||
void BoardSweekar::VbatToVbat5vInit(void)
|
||||
{
|
||||
// 配置VBAT_5V引脚为输出模式
|
||||
gpio_config_t io_conf = {
|
||||
.pin_bit_mask = (1ULL << VBAT_5V_PIN),
|
||||
.mode = GPIO_MODE_OUTPUT,
|
||||
.pull_up_en = GPIO_PULLUP_DISABLE,
|
||||
.pull_down_en = GPIO_PULLDOWN_DISABLE,
|
||||
.intr_type = GPIO_INTR_DISABLE
|
||||
};
|
||||
gpio_config(&io_conf);
|
||||
// 使能VBAT_5V
|
||||
gpio_set_level(VBAT_5V_PIN, 1);
|
||||
}
|
||||
|
||||
/*========================== 底座控制串口相关驱动 ==========================*/
|
||||
|
||||
/**
|
||||
* @brief 底座控制命令串口初始化函数
|
||||
*/
|
||||
// 根据配置选择通信方式的HAL头文件
|
||||
#ifdef CONFIG_BASE_BOARD_COMM_I2C
|
||||
#include "base_board_hal_i2c.h"
|
||||
#else
|
||||
#include "base_board_hal_uart.h"
|
||||
#endif
|
||||
|
||||
void BoardSweekar::BaseBoardControlInit(void)
|
||||
{
|
||||
#ifdef CONFIG_BASE_BOARD_COMM_I2C
|
||||
// I2C Mode
|
||||
if (bus_handle_ == nullptr) {
|
||||
ESP_LOGE(TAG, "I2C bus not initialized before BaseBoardControlInit");
|
||||
return;
|
||||
}
|
||||
|
||||
// 创建 I2C HAL 实例
|
||||
BaseBoardHalI2c *hal = new BaseBoardHalI2c(bus_handle_);
|
||||
base_board_control_.Init(hal);
|
||||
ESP_LOGI(TAG, "BaseBoardControl I2C initialized");
|
||||
#else
|
||||
// UART Mode
|
||||
uart_config_t uart_config = {
|
||||
.baud_rate = BASE_BOARD_CTL_UART_BAUDRATE,
|
||||
.data_bits = UART_DATA_8_BITS,
|
||||
.parity = UART_PARITY_DISABLE,
|
||||
.stop_bits = UART_STOP_BITS_1,
|
||||
.flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
|
||||
.source_clk = UART_SCLK_DEFAULT,
|
||||
.flags = {
|
||||
.allow_pd = 0,
|
||||
.backup_before_sleep = 0,
|
||||
},
|
||||
};
|
||||
|
||||
// 1. 设置串口参数
|
||||
ESP_ERROR_CHECK(uart_param_config(BASE_BOARD_CTL_UART_PORT, &uart_config));
|
||||
|
||||
// 2. 设置 UART 引脚
|
||||
ESP_ERROR_CHECK(uart_set_pin(BASE_BOARD_CTL_UART_PORT, BASE_BOARD_CTL_UART_TX_PIN, BASE_BOARD_CTL_UART_RX_PIN,
|
||||
UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE));
|
||||
|
||||
// 3. 安装 UART 驱动
|
||||
ESP_ERROR_CHECK(uart_driver_install(BASE_BOARD_CTL_UART_PORT,
|
||||
BASE_BOARD_CTL_UART_BUF_SIZE,
|
||||
BASE_BOARD_CTL_UART_BUF_SIZE,
|
||||
0, NULL, 0));
|
||||
|
||||
BaseBoardHalUart *hal = new BaseBoardHalUart(BASE_BOARD_CTL_UART_PORT);
|
||||
base_board_control_.Init(hal);
|
||||
ESP_LOGI(TAG, "BaseBoardControl UART initialized");
|
||||
#endif
|
||||
}
|
||||
|
||||
/*========================== SD卡相关驱动 ==========================*/
|
||||
|
||||
/**
|
||||
* @brief SD卡初始化函数
|
||||
*
|
||||
* 初始化SD卡外设,使用1线模式进行通信。该函数负责初始化外设管理器
|
||||
* 并配置SD卡,为后续的文件系统操作做准备。
|
||||
*
|
||||
* @return esp_err_t 初始化结果,ESP_OK表示成功,其他错误码表示失败原因
|
||||
*/
|
||||
esp_err_t BoardSweekar::InitializeSdcard(void)
|
||||
{
|
||||
static const char *SDCARD_TAG = "SDCARD_INIT";
|
||||
esp_err_t ret;
|
||||
|
||||
ESP_LOGI(SDCARD_TAG, "Initializing SD card");
|
||||
|
||||
if (is_sdcard_initialized_) {
|
||||
ESP_LOGW(SDCARD_TAG, "SD card already initialized");
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
// 初始化外设管理
|
||||
esp_periph_config_t periph_cfg = DEFAULT_ESP_PERIPH_SET_CONFIG();
|
||||
periph_cfg.extern_stack = true; // 将任务栈分配到 PSRAM 以节省 Internal SRAM
|
||||
periph_set_ = esp_periph_set_init(&periph_cfg);
|
||||
if (!periph_set_) {
|
||||
ESP_LOGE(SDCARD_TAG, "Failed to initialize peripheral set");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
// 初始化SD卡外设
|
||||
ret = audio_board_sdcard_init(periph_set_, SD_MODE_1_LINE);
|
||||
if (ret != ESP_OK) {
|
||||
ESP_LOGE(SDCARD_TAG, "Failed to initialize SD card: %s", esp_err_to_name(ret));
|
||||
return ret;
|
||||
}
|
||||
|
||||
is_sdcard_initialized_ = true;
|
||||
ESP_LOGI(SDCARD_TAG, "SD card initialized successfully");
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 统一的硬件初始化接口实现
|
||||
*
|
||||
* 按照依赖关系顺序初始化所有硬件资源:
|
||||
* 1. I2C总线(最基础,其他设备可能依赖)
|
||||
* 2. IO扩展板(可能影响其他设备)
|
||||
* 3. SD卡(文件系统,供显示和音频使用)
|
||||
* 4. 其他外设
|
||||
*
|
||||
* @return esp_err_t 初始化结果,ESP_OK表示全部成功
|
||||
*/
|
||||
esp_err_t BoardSweekar::InitializeAllHardware(void)
|
||||
{
|
||||
static const char *HW_INIT_TAG = "HW_INIT";
|
||||
esp_err_t ret;
|
||||
|
||||
ESP_LOGI(HW_INIT_TAG, "Starting unified hardware initialization...");
|
||||
|
||||
// 1. 初始化I2C总线(最基础)
|
||||
ret = I2CMasterInit();
|
||||
if (ret != ESP_OK) {
|
||||
ESP_LOGE(HW_INIT_TAG, "Failed to initialize I2C master: %s", esp_err_to_name(ret));
|
||||
return ret;
|
||||
}
|
||||
ESP_LOGI(HW_INIT_TAG, "I2C master initialized");
|
||||
|
||||
// 2. 创建I2C读任务(IO扩展板需要)
|
||||
io_expansion_.CreateI2cReadTask();
|
||||
ESP_LOGI(HW_INIT_TAG, "I2C read task created");
|
||||
|
||||
// 3. 初始化SD卡(文件系统,供显示和音频使用)
|
||||
ret = InitializeSdcard();
|
||||
if (ret != ESP_OK) {
|
||||
ESP_LOGE(HW_INIT_TAG, "Failed to initialize SD card: %s", esp_err_to_name(ret));
|
||||
// SD卡失败不是致命错误,继续初始化其他硬件
|
||||
ESP_LOGW(HW_INIT_TAG, "SD card initialization failed, but continuing with other hardware");
|
||||
} else {
|
||||
ESP_LOGI(HW_INIT_TAG, "SD card initialized");
|
||||
}
|
||||
|
||||
// 4. 初始化LCD IO引脚
|
||||
LcdIoInit();
|
||||
ESP_LOGI(HW_INIT_TAG, "LCD IO pins initialized");
|
||||
|
||||
// 5. 初始化底座控制
|
||||
if (bus_handle_ != nullptr) {
|
||||
BaseBoardHalI2c *hal_i2c = new BaseBoardHalI2c(bus_handle_);
|
||||
base_board_control_.Init(hal_i2c);
|
||||
ESP_LOGI(HW_INIT_TAG, "Base board control initialized with I2C handle");
|
||||
} else {
|
||||
ESP_LOGE(HW_INIT_TAG, "Failed to initialize base board control: I2C bus is null");
|
||||
}
|
||||
|
||||
// 6. AUD_CTRL 为 codec 控制脚,板级初始化后保持拉高,不参与 PA 开关。
|
||||
#ifdef AUD_CTRL_PIN
|
||||
gpio_config_t io_conf = {};
|
||||
io_conf.intr_type = GPIO_INTR_DISABLE;
|
||||
io_conf.mode = GPIO_MODE_OUTPUT;
|
||||
io_conf.pin_bit_mask = (1ULL << AUD_CTRL_PIN);
|
||||
io_conf.pull_down_en = GPIO_PULLDOWN_DISABLE;
|
||||
io_conf.pull_up_en = GPIO_PULLUP_ENABLE;
|
||||
gpio_config(&io_conf);
|
||||
gpio_set_level(AUD_CTRL_PIN, 1);
|
||||
ESP_LOGI(HW_INIT_TAG, "AUD_CTRL pin initialized to HIGH");
|
||||
#endif
|
||||
|
||||
// 7. 可选外设(根据具体应用需求)
|
||||
// BaseBoardControlUartInit(); // 底座控制串口(demo5需要)
|
||||
// ESP_LOGI(HW_INIT_TAG, "Base board control UART initialized");
|
||||
|
||||
// MillimeterWaveRadarUartInit();
|
||||
// MillimeterWaveRadarGpioInit();
|
||||
StepperMotorInit();
|
||||
|
||||
|
||||
|
||||
ESP_LOGI(HW_INIT_TAG, "Unified hardware initialization completed successfully");
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 进入低功耗模式
|
||||
*
|
||||
* 根据指定的功耗模式,执行相应的功耗优化策略:
|
||||
* - IDLE模式:关闭非必要外设,保持快速响应
|
||||
* - LIGHT_SLEEP模式:进入轻度睡眠,CPU暂停,外设断电
|
||||
* - DEEP_SLEEP模式:深度睡眠,仅RTC运行,功耗最低
|
||||
*/
|
||||
esp_err_t BoardSweekar::EnterLowPowerMode(power_mode_t mode) {
|
||||
static const char *POWER_TAG = "POWER_MGMT";
|
||||
esp_err_t ret = ESP_OK;
|
||||
|
||||
ESP_LOGI(POWER_TAG, "Entering power mode: %d", mode);
|
||||
|
||||
if (mode == current_power_mode_) {
|
||||
ESP_LOGW(POWER_TAG, "Already in power mode %d", mode);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
// 保存当前模式,以便恢复
|
||||
power_mode_t previous_mode = current_power_mode_;
|
||||
|
||||
switch (mode) {
|
||||
case POWER_MODE_NORMAL:
|
||||
// 正常模式,不需要特殊处理
|
||||
break;
|
||||
|
||||
case POWER_MODE_IDLE:
|
||||
// 空闲模式:关闭非必要外设
|
||||
ESP_LOGI(POWER_TAG, "Idle mode: disabling non-essential peripherals");
|
||||
|
||||
// 关闭SD卡(如果正在使用,需要先卸载)
|
||||
if (is_sdcard_initialized_) {
|
||||
// 注意:这里只是示例,实际应用中需要确保没有文件操作
|
||||
ESP_LOGW(POWER_TAG, "SD card still active in idle mode");
|
||||
}
|
||||
|
||||
// 关闭显示背光
|
||||
// 关闭非必要GPIO的上拉/下拉
|
||||
// 降低I2C时钟频率
|
||||
break;
|
||||
|
||||
case POWER_MODE_LIGHT_SLEEP:
|
||||
// 轻度睡眠
|
||||
ESP_LOGI(POWER_TAG, "Light sleep mode: preparing for sleep");
|
||||
|
||||
// 设置唤醒源(需要根据具体需求配置)
|
||||
// esp_sleep_enable_timer_wakeup(1000000); // 1秒后唤醒
|
||||
// esp_sleep_enable_ext0_wakeup(GPIO_NUM_XX, 0); // 外部中断唤醒
|
||||
|
||||
// 进入轻度睡眠
|
||||
// ret = esp_light_sleep_start();
|
||||
if (ret != ESP_OK) {
|
||||
ESP_LOGE(POWER_TAG, "Failed to enter light sleep: %s", esp_err_to_name(ret));
|
||||
current_power_mode_ = previous_mode;
|
||||
return ret;
|
||||
}
|
||||
break;
|
||||
|
||||
case POWER_MODE_DEEP_SLEEP:
|
||||
// 深度睡眠
|
||||
ESP_LOGI(POWER_TAG, "Deep sleep mode: system will restart after wake-up");
|
||||
|
||||
// 保存必要的RTC数据
|
||||
// rtc_gpio_isolate(GPIO_NUM_XX); // 隔离GPIO
|
||||
|
||||
// 设置深度睡眠唤醒源
|
||||
// esp_sleep_enable_timer_wakeup(60000000); // 60秒后唤醒
|
||||
|
||||
// 进入深度睡眠
|
||||
// esp_deep_sleep_start();
|
||||
// 注意:深度睡眠后系统会重启,不会返回
|
||||
break;
|
||||
|
||||
default:
|
||||
ESP_LOGE(POWER_TAG, "Invalid power mode: %d", mode);
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
current_power_mode_ = mode;
|
||||
ESP_LOGI(POWER_TAG, "Successfully entered power mode: %d", mode);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 退出低功耗模式
|
||||
*
|
||||
* 从低功耗模式恢复到正常运行模式,重新初始化必要的硬件资源。
|
||||
*/
|
||||
esp_err_t BoardSweekar::ExitLowPowerMode(void) {
|
||||
static const char *POWER_TAG = "POWER_MGMT";
|
||||
|
||||
ESP_LOGI(POWER_TAG, "Exiting low power mode");
|
||||
|
||||
if (current_power_mode_ == POWER_MODE_NORMAL) {
|
||||
ESP_LOGW(POWER_TAG, "Already in normal mode");
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
// 根据之前的功耗模式执行相应的恢复操作
|
||||
switch (current_power_mode_) {
|
||||
case POWER_MODE_IDLE:
|
||||
// 恢复空闲模式
|
||||
ESP_LOGI(POWER_TAG, "Restoring from idle mode");
|
||||
|
||||
// 重新初始化必要的外设
|
||||
// 恢复I2C时钟频率
|
||||
// 重新开启显示背光
|
||||
break;
|
||||
|
||||
case POWER_MODE_LIGHT_SLEEP:
|
||||
// 轻度睡眠唤醒后会自动继续执行
|
||||
ESP_LOGI(POWER_TAG, "Woken up from light sleep");
|
||||
|
||||
// 重新配置时钟(如果需要)
|
||||
// 重新初始化外设
|
||||
break;
|
||||
|
||||
case POWER_MODE_DEEP_SLEEP:
|
||||
// 深度睡眠后系统会重启,不会执行到这里
|
||||
ESP_LOGW(POWER_TAG, "Deep sleep recovery should not reach here");
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// 恢复到正常模式
|
||||
current_power_mode_ = POWER_MODE_NORMAL;
|
||||
ESP_LOGI(POWER_TAG, "Successfully exited low power mode");
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 设置硬件模块电源状态
|
||||
*
|
||||
* 提供精细化的电源管理,可以单独控制各个硬件模块的电源状态。
|
||||
*/
|
||||
esp_err_t BoardSweekar::SetModulePower(hardware_module_t module, bool enable) {
|
||||
static const char *POWER_TAG = "POWER_MODULE";
|
||||
esp_err_t ret = ESP_OK;
|
||||
|
||||
ESP_LOGI(POWER_TAG, "%s module %d", enable ? "Enabling" : "Disabling", module);
|
||||
|
||||
// 更新电源状态位图
|
||||
if (enable) {
|
||||
power_state_flags_ |= (1 << module);
|
||||
} else {
|
||||
power_state_flags_ &= ~(1 << module);
|
||||
}
|
||||
|
||||
switch (module) {
|
||||
case HW_MODULE_I2C:
|
||||
if (!enable && bus_handle_) {
|
||||
// 注意:I2C总线通常不建议完全关闭,可能影响多个设备
|
||||
ESP_LOGW(POWER_TAG, "I2C bus power control not recommended");
|
||||
}
|
||||
break;
|
||||
|
||||
case HW_MODULE_SDCARD:
|
||||
if (enable && !is_sdcard_initialized_) {
|
||||
ret = InitializeSdcard();
|
||||
} else if (!enable && is_sdcard_initialized_) {
|
||||
// 卸载SD卡文件系统
|
||||
// 注意:需要确保没有打开的文件
|
||||
ESP_LOGW(POWER_TAG, "SD card power down requires file system cleanup");
|
||||
}
|
||||
break;
|
||||
|
||||
case HW_MODULE_LCD:
|
||||
// LCD背光控制
|
||||
// LCD电源引脚控制(如果有)
|
||||
break;
|
||||
|
||||
case HW_MODULE_AUDIO:
|
||||
// 音频编解码器电源控制
|
||||
// 需要与AudioPlayer协调
|
||||
break;
|
||||
|
||||
case HW_MODULE_MOTOR:
|
||||
// 步进电机驱动器电源控制
|
||||
// 电机睡眠模式
|
||||
break;
|
||||
|
||||
case HW_MODULE_GYROSCOPE:
|
||||
// 陀螺仪电源控制
|
||||
// 设置陀螺仪为低功耗模式
|
||||
break;
|
||||
|
||||
case HW_MODULE_TOUCH:
|
||||
// 触摸传感器电源控制
|
||||
// 设置触摸传感器为睡眠模式
|
||||
break;
|
||||
|
||||
case HW_MODULE_RADAR:
|
||||
// 毫米波雷达电源控制
|
||||
// 设置雷达为低功耗模式
|
||||
break;
|
||||
|
||||
case HW_MODULE_IO_EXPAND:
|
||||
// IO扩展板电源控制
|
||||
// 设置扩展板为低功耗模式
|
||||
break;
|
||||
|
||||
default:
|
||||
ESP_LOGE(POWER_TAG, "Unknown hardware module: %d", module);
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
if (ret == ESP_OK) {
|
||||
ESP_LOGI(POWER_TAG, "Module %d power %s successfully", module, enable ? "enabled" : "disabled");
|
||||
} else {
|
||||
ESP_LOGE(POWER_TAG, "Failed to %s module %d: %s", enable ? "enable" : "disable", module, esp_err_to_name(ret));
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,181 @@
|
||||
#ifndef __BOARD_H__
|
||||
#define __BOARD_H__
|
||||
#include "config.h"
|
||||
#include "io_expansion_board.h"
|
||||
#include "stepper_motor.h"
|
||||
#include "stepper_driver.h"
|
||||
#include "i2c_bus.h"
|
||||
#include "gyroscope.h"
|
||||
#include "touch_sensor.h"
|
||||
#include "base_board_control.h"
|
||||
#include "esp_peripherals.h"
|
||||
#include "periph_sdcard.h"
|
||||
#include "esp_sleep.h"
|
||||
#include "driver/rtc_io.h"
|
||||
|
||||
/**
|
||||
* @brief 功耗模式枚举
|
||||
*/
|
||||
typedef enum {
|
||||
POWER_MODE_NORMAL, // 正常运行模式,所有硬件可用
|
||||
POWER_MODE_IDLE, // 空闲模式,关闭非必要外设
|
||||
POWER_MODE_LIGHT_SLEEP, // 轻度睡眠,快速唤醒
|
||||
POWER_MODE_DEEP_SLEEP, // 深度睡眠,仅RTC运行
|
||||
} power_mode_t;
|
||||
|
||||
/**
|
||||
* @brief 硬件模块枚举,用于精细化电源管理
|
||||
*/
|
||||
typedef enum {
|
||||
HW_MODULE_I2C, // I2C总线
|
||||
HW_MODULE_SDCARD, // SD卡
|
||||
HW_MODULE_LCD, // LCD显示
|
||||
HW_MODULE_AUDIO, // 音频编解码器
|
||||
HW_MODULE_MOTOR, // 步进电机
|
||||
HW_MODULE_GYROSCOPE, // 陀螺仪
|
||||
HW_MODULE_TOUCH, // 触摸传感器
|
||||
HW_MODULE_RADAR, // 毫米波雷达
|
||||
HW_MODULE_IO_EXPAND, // IO扩展板
|
||||
} hardware_module_t;
|
||||
|
||||
/**
|
||||
* @brief 硬件板级管理器
|
||||
*
|
||||
* 采用高内聚低耦合设计原则,统一管理所有硬件资源。
|
||||
* 提供统一的硬件初始化接口和资源访问,避免各模块重复初始化。
|
||||
*/
|
||||
class BoardSweekar
|
||||
{
|
||||
private:
|
||||
i2c_bus_handle_t bus_handle_ = nullptr; // 使用ESP-ADF的I2C总线句柄
|
||||
esp_periph_set_handle_t periph_set_ = nullptr; // 外设管理句柄
|
||||
bool is_sdcard_initialized_ = false; // SD卡初始化状态
|
||||
power_mode_t current_power_mode_ = POWER_MODE_NORMAL; // 当前功耗模式
|
||||
uint32_t power_state_flags_ = 0xFFFFFFFF; // 各模块电源状态位图(1为开启)
|
||||
|
||||
public:
|
||||
BoardSweekar();
|
||||
~BoardSweekar();
|
||||
|
||||
static BoardSweekar* GetInstance();
|
||||
|
||||
// --- 语义化的高层 API:音频与功放控制 ---
|
||||
// 开启或关闭外放功放 (PA),供上层 AudioActor/AudioPlayer 调用,屏蔽底层引脚实现
|
||||
void SetAudioAmplifier(bool enable);
|
||||
|
||||
IOExpansionBoard io_expansion_; // IO扩展板对象
|
||||
Gyroscope gyroscope_; // 陀螺仪对象
|
||||
TouchSensor touch_sensor_; // 触摸传感器对象
|
||||
BaseBoardControl base_board_control_; // 底座控制对象
|
||||
StepperDriver* stepper_driver_ = nullptr; // 步进电机驱动对象
|
||||
|
||||
StepperDriver* GetStepperDriver() const { return stepper_driver_; }
|
||||
|
||||
// 初始化步进电机
|
||||
void StepperMotorInit(void);
|
||||
|
||||
// 初始化LCD IO引脚(消除与步进电机的耦合)
|
||||
void LcdIoInit(void);
|
||||
|
||||
// 初始化串口
|
||||
void MillimeterWaveRadarUartInit(void);
|
||||
|
||||
//初始化毫米波雷达的中断引脚
|
||||
void MillimeterWaveRadarGpioInit(void);
|
||||
|
||||
/**
|
||||
* @brief 执行系统关机
|
||||
* 内部拉高/拉低 SHUTDOWN_CTRL_PIN 引脚切断电源
|
||||
*/
|
||||
void SystemShutdown(void);
|
||||
|
||||
// 初始化I2C总线
|
||||
esp_err_t I2CMasterInit(void);
|
||||
|
||||
// 初始化VBAT toVBAT_5V引脚
|
||||
void VbatToVbat5vInit(void);
|
||||
|
||||
// 初始化底座控制串口
|
||||
void BaseBoardControlInit(void);
|
||||
|
||||
// 初始化SD卡(推荐使用统一的硬件初始化)
|
||||
esp_err_t InitializeSdcard(void);
|
||||
|
||||
// 获取SD卡初始化状态
|
||||
bool IsSdcardInitialized() const { return is_sdcard_initialized_; }
|
||||
|
||||
// 获取外设管理句柄(供需要访问SD卡的模块使用)
|
||||
esp_periph_set_handle_t GetPeriphSet() const { return periph_set_; }
|
||||
|
||||
// 获取I2C总线句柄
|
||||
i2c_bus_handle_t GetBusHandle() const { return bus_handle_; }
|
||||
|
||||
/**
|
||||
* @brief 统一的硬件初始化接口
|
||||
*
|
||||
* 按照依赖关系顺序初始化所有硬件资源,确保各模块可以安全使用。
|
||||
* 推荐在主程序启动时调用此函数,而不是分别调用各个初始化函数。
|
||||
*
|
||||
* @return esp_err_t 初始化结果,ESP_OK表示全部成功
|
||||
*/
|
||||
esp_err_t InitializeAllHardware(void);
|
||||
|
||||
/**
|
||||
* @brief 完整的统一硬件初始化接口(专为复杂应用优化)
|
||||
*
|
||||
* 包含所有必要外设的完整初始化,适用于demo5等复杂应用场景。
|
||||
* 这个函数会初始化:I2C总线、IO扩展板、SD卡、LCD IO、底座控制等。
|
||||
*
|
||||
* @return esp_err_t 初始化结果,ESP_OK表示全部成功
|
||||
*/
|
||||
esp_err_t InitializeAllHardwareComplete(void);
|
||||
|
||||
/**
|
||||
* @brief 针对特定应用的硬件初始化配置
|
||||
*
|
||||
* 为不同类型的应用提供专门的初始化配置,优化启动流程。
|
||||
*
|
||||
* @param app_type 应用类型(demo5、音频播放器、显示应用等)
|
||||
* @return esp_err_t 初始化结果,ESP_OK表示全部成功
|
||||
*/
|
||||
esp_err_t InitializeHardwareForApplication(int app_type);
|
||||
|
||||
/**
|
||||
* @brief 功耗管理接口 - 进入低功耗模式
|
||||
*
|
||||
* 根据指定的功耗模式,关闭非必要硬件、设置GPIO为低功耗状态、
|
||||
* 调整时钟频率等。支持多种功耗模式以适应不同应用场景。
|
||||
*
|
||||
* @param mode 功耗模式
|
||||
* @return esp_err_t 操作结果
|
||||
*/
|
||||
esp_err_t EnterLowPowerMode(power_mode_t mode);
|
||||
|
||||
/**
|
||||
* @brief 功耗管理接口 - 退出低功耗模式
|
||||
*
|
||||
* 从低功耗模式恢复,重新初始化必要的硬件资源。
|
||||
*
|
||||
* @return esp_err_t 操作结果
|
||||
*/
|
||||
esp_err_t ExitLowPowerMode(void);
|
||||
|
||||
/**
|
||||
* @brief 获取当前功耗模式
|
||||
*
|
||||
* @return power_mode_t 当前功耗模式
|
||||
*/
|
||||
power_mode_t GetPowerMode(void) const { return current_power_mode_; }
|
||||
|
||||
/**
|
||||
* @brief 设置硬件模块电源状态
|
||||
*
|
||||
* 单独控制某个硬件模块的电源状态,用于精细化的功耗管理。
|
||||
*
|
||||
* @param module 硬件模块
|
||||
* @param enable true为开启,false为关闭
|
||||
* @return esp_err_t 操作结果
|
||||
*/
|
||||
esp_err_t SetModulePower(hardware_module_t module, bool enable);
|
||||
};
|
||||
#endif
|
||||
@@ -0,0 +1,200 @@
|
||||
/**
|
||||
* @file board_sweekar_complete_init.cc
|
||||
* @brief 完整的统一硬件初始化实现
|
||||
*
|
||||
* 这个文件提供了完整的统一硬件初始化函数,包含所有必要的硬件初始化步骤。
|
||||
* 专为demo5等复杂应用场景设计。
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief 完整的统一硬件初始化接口(专为demo5优化)
|
||||
*
|
||||
* 按照依赖关系顺序初始化所有硬件资源:
|
||||
* 1. I2C总线(最基础,其他设备依赖)
|
||||
* 2. IO扩展板(控制其他外设)
|
||||
* 3. SD卡(文件系统,供显示和音频使用)
|
||||
* 4. LCD IO引脚(显示相关)
|
||||
* 5. 底座控制串口(通信)
|
||||
* 6. 底座控制模块(业务逻辑)
|
||||
* 7. 其他外设(根据应用需求)
|
||||
*
|
||||
* @return esp_err_t 初始化结果,ESP_OK表示全部成功
|
||||
*/
|
||||
esp_err_t BoardSweekar::InitializeAllHardwareComplete(void)
|
||||
{
|
||||
static const char *HW_INIT_TAG = "HW_INIT_COMPLETE";
|
||||
esp_err_t ret;
|
||||
|
||||
ESP_LOGI(HW_INIT_TAG, "Starting complete hardware initialization...");
|
||||
|
||||
// 1. 初始化I2C总线(最基础,其他设备依赖)
|
||||
ret = I2CMasterInit();
|
||||
if (ret != ESP_OK) {
|
||||
ESP_LOGE(HW_INIT_TAG, "Failed to initialize I2C master: %s", esp_err_to_name(ret));
|
||||
return ret;
|
||||
}
|
||||
ESP_LOGI(HW_INIT_TAG, "✓ I2C master initialized");
|
||||
|
||||
// 2. 创建I2C读任务(IO扩展板需要)
|
||||
io_expansion_.CreateI2cReadTask();
|
||||
ESP_LOGI(HW_INIT_TAG, "✓ I2C read task created");
|
||||
|
||||
// 3. 初始化SD卡(文件系统,供显示和音频使用)
|
||||
ret = InitializeSdcard();
|
||||
if (ret != ESP_OK) {
|
||||
ESP_LOGE(HW_INIT_TAG, "Failed to initialize SD card: %s", esp_err_to_name(ret));
|
||||
// SD卡失败不是致命错误,继续初始化其他硬件
|
||||
ESP_LOGW(HW_INIT_TAG, "⚠ SD card initialization failed, but continuing with other hardware");
|
||||
} else {
|
||||
ESP_LOGI(HW_INIT_TAG, "✓ SD card initialized");
|
||||
}
|
||||
|
||||
// 4. 初始化LCD IO引脚(显示相关)
|
||||
LcdIoInit();
|
||||
ESP_LOGI(HW_INIT_TAG, "✓ LCD IO pins initialized");
|
||||
|
||||
// 5. 初始化底座控制串口(demo5需要)
|
||||
BaseBoardControlUartInit();
|
||||
ESP_LOGI(HW_INIT_TAG, "✓ Base board control UART initialized");
|
||||
|
||||
// 6. 初始化底座控制模块
|
||||
base_board_control_.Init();
|
||||
ESP_LOGI(HW_INIT_TAG, "✓ Base board control initialized");
|
||||
|
||||
// 7. 设置IO扩展板的PA控制模式(demo5需要)
|
||||
io_expansion_.SetPaCtrlMode(true);
|
||||
ESP_LOGI(HW_INIT_TAG, "✓ IO expansion PA control mode set");
|
||||
|
||||
// 8. 初始化 AUD_CTRL 引脚(如果定义了的话)
|
||||
#ifdef AUD_CTRL_PIN
|
||||
gpio_config_t io_conf = {};
|
||||
io_conf.intr_type = GPIO_INTR_DISABLE;
|
||||
io_conf.mode = GPIO_MODE_OUTPUT;
|
||||
io_conf.pin_bit_mask = (1ULL << AUD_CTRL_PIN);
|
||||
io_conf.pull_down_en = GPIO_PULLDOWN_DISABLE;
|
||||
io_conf.pull_up_en = GPIO_PULLUP_ENABLE;
|
||||
gpio_config(&io_conf);
|
||||
// 拉高开机
|
||||
gpio_set_level(AUD_CTRL_PIN, 1);
|
||||
ESP_LOGI(HW_INIT_TAG, "✓ AUD_CTRL pin initialized to HIGH");
|
||||
#endif
|
||||
|
||||
// 9. 可选外设(根据具体应用需求启用)
|
||||
// ESP_LOGI(HW_INIT_TAG, "Initializing optional peripherals...");
|
||||
//
|
||||
// // 毫米波雷达(如需要)
|
||||
// MillimeterWaveRadarUartInit();
|
||||
// MillimeterWaveRadarGpioInit();
|
||||
// ESP_LOGI(HW_INIT_TAG, "✓ Millimeter wave radar initialized");
|
||||
//
|
||||
// // VBAT升压(如需要)
|
||||
// VbatToVbat5vInit();
|
||||
// ESP_LOGI(HW_INIT_TAG, "✓ VBAT to 5V booster initialized");
|
||||
//
|
||||
// // 步进电机(如需要)
|
||||
// StepperMotorInit();
|
||||
// ESP_LOGI(HW_INIT_TAG, "✓ Stepper motor initialized");
|
||||
|
||||
ESP_LOGI(HW_INIT_TAG, "=== Complete hardware initialization finished successfully ===");
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 针对特定应用的硬件初始化配置
|
||||
*
|
||||
* 为不同类型的应用提供专门的初始化配置
|
||||
*/
|
||||
esp_err_t BoardSweekar::InitializeHardwareForApplication(application_type_t app_type) {
|
||||
static const char *APP_INIT_TAG = "APP_HW_INIT";
|
||||
|
||||
ESP_LOGI(APP_INIT_TAG, "Initializing hardware for application type: %d", app_type);
|
||||
|
||||
// 基础硬件初始化(所有应用都需要)
|
||||
esp_err_t ret = InitializeAllHardwareComplete();
|
||||
if (ret != ESP_OK) {
|
||||
ESP_LOGE(APP_INIT_TAG, "Basic hardware initialization failed");
|
||||
return ret;
|
||||
}
|
||||
|
||||
switch (app_type) {
|
||||
case APP_TYPE_DEMO5: // 宠物游戏demo
|
||||
ESP_LOGI(APP_INIT_TAG, "Configuring for Demo5 (Pet Game)...");
|
||||
|
||||
// Demo5需要的额外初始化
|
||||
// 触摸传感器、陀螺仪、RGB LED等会在应用层初始化
|
||||
|
||||
ESP_LOGI(APP_INIT_TAG, "✓ Demo5 hardware configuration complete");
|
||||
break;
|
||||
|
||||
case APP_TYPE_AUDIO_PLAYER: // 音频播放器
|
||||
ESP_LOGI(APP_INIT_TAG, "Configuring for Audio Player...");
|
||||
|
||||
// 音频应用需要确保音频编解码器正确初始化
|
||||
// 这部分通常在AudioPlayer类中处理
|
||||
|
||||
ESP_LOGI(APP_INIT_TAG, "✓ Audio player hardware configuration complete");
|
||||
break;
|
||||
|
||||
case APP_TYPE_DISPLAY_ONLY: // 纯显示应用
|
||||
ESP_LOGI(APP_INIT_TAG, "Configuring for Display Only...");
|
||||
|
||||
// 显示应用需要确保LCD相关硬件正确配置
|
||||
// 这部分通常在Display类中处理
|
||||
|
||||
ESP_LOGI(APP_INIT_TAG, "✓ Display-only hardware configuration complete");
|
||||
break;
|
||||
|
||||
case APP_TYPE_MINIMAL: // 最小化应用
|
||||
ESP_LOGI(APP_INIT_TAG, "Configuring for Minimal Application...");
|
||||
|
||||
// 最小化配置,只保留最基本的功能
|
||||
// 关闭非必要外设以节省功耗
|
||||
|
||||
ESP_LOGI(APP_INIT_TAG, "✓ Minimal hardware configuration complete");
|
||||
break;
|
||||
|
||||
default:
|
||||
ESP_LOGW(APP_INIT_TAG, "Unknown application type, using default configuration");
|
||||
break;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 硬件初始化状态报告
|
||||
*
|
||||
* 提供详细的硬件初始化状态报告,便于调试和问题排查
|
||||
*/
|
||||
void BoardSweekar::ReportHardwareStatus(void) {
|
||||
static const char *STATUS_TAG = "HW_STATUS";
|
||||
|
||||
ESP_LOGI(STATUS_TAG, "=== Hardware Initialization Status Report ===");
|
||||
|
||||
// I2C总线状态
|
||||
ESP_LOGI(STATUS_TAG, "I2C Bus: %s", (bus_handle_ != nullptr) ? "✓ Initialized" : "✗ Not initialized");
|
||||
|
||||
// SD卡状态
|
||||
ESP_LOGI(STATUS_TAG, "SD Card: %s", (is_sdcard_initialized_) ? "✓ Initialized" : "✗ Not initialized");
|
||||
if (is_sdcard_initialized_) {
|
||||
ESP_LOGI(STATUS_TAG, " Peripheral Set: %s", (periph_set_ != nullptr) ? "✓ Available" : "✗ Not available");
|
||||
}
|
||||
|
||||
// IO扩展板状态
|
||||
ESP_LOGI(STATUS_TAG, "IO Expansion Board: %s", (io_expansion_.bus_handle_ != nullptr) ? "✓ Configured" : "✗ Not configured");
|
||||
|
||||
// 底座控制状态
|
||||
ESP_LOGI(STATUS_TAG, "Base Board Control: %s", (base_board_control_.GetUartPort() != 0) ? "✓ Initialized" : "✗ Not initialized");
|
||||
|
||||
// 功耗管理状态
|
||||
ESP_LOGI(STATUS_TAG, "Power Management: %s", (current_power_mode_ == POWER_MODE_NORMAL) ? "✓ Normal mode" : "⚠ Low power mode");
|
||||
ESP_LOGI(STATUS_TAG, " Current Mode: %d", current_power_mode_);
|
||||
ESP_LOGI(STATUS_TAG, " Module Power States: 0x%08X", power_state_flags_);
|
||||
|
||||
// 内存状态
|
||||
ESP_LOGI(STATUS_TAG, "Memory Status:");
|
||||
ESP_LOGI(STATUS_TAG, " Internal RAM Free: %d bytes", heap_caps_get_free_size(MALLOC_CAP_INTERNAL));
|
||||
ESP_LOGI(STATUS_TAG, " PSRAM Free: %d bytes", heap_caps_get_free_size(MALLOC_CAP_SPIRAM));
|
||||
|
||||
ESP_LOGI(STATUS_TAG, "=== End of Hardware Status Report ===");
|
||||
}
|
||||
@@ -0,0 +1,136 @@
|
||||
/* 定义引脚分配 */
|
||||
#ifndef _BOARD_CONFIG_H_
|
||||
#define _BOARD_CONFIG_H_
|
||||
|
||||
/**
|
||||
* @file config.h
|
||||
* @brief 定义了引脚的分配。
|
||||
* @author zouyuhua
|
||||
* @date 2025年8月7日
|
||||
*
|
||||
*/
|
||||
|
||||
#include "driver/gpio.h"
|
||||
#include "driver/i2c_master.h"
|
||||
#include "driver/i2s.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_rom_sys.h" // 用于 esp_rom_delay_us
|
||||
#include "esp_timer.h"
|
||||
#include "esp_mac.h"
|
||||
#include "driver/ledc.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "esp_log.h"
|
||||
#include "driver/gptimer.h"
|
||||
#include "esp_intr_alloc.h"
|
||||
#include "driver/uart.h"
|
||||
#include "esp_err.h"
|
||||
#include "freertos/queue.h"
|
||||
#include "soc/uart_reg.h"
|
||||
#include "linear_motor.h"
|
||||
#include "gyroscope.h"
|
||||
|
||||
#define TAG_BOARD "SWEEKAR_ESP32"
|
||||
/*I2C总线引脚定义*/
|
||||
#define I2C0_MASTER_PORT I2C_NUM_0
|
||||
#define I2C0_MASTER_SDA_IO GPIO_NUM_2
|
||||
#define I2C0_MASTER_SCL_IO GPIO_NUM_3
|
||||
|
||||
/* 步进电机配置 */
|
||||
#define STEPPER_STEP_IO GPIO_NUM_42 // 步进电机脉冲输入引脚
|
||||
#define STEPPER_TIMER_RES_HZ 1000000 // 步进电机定时器分辨率 1 MHz(1 us 步进)
|
||||
|
||||
/* 定义屏幕驱动控制引脚 */
|
||||
#define ST7789_PIN_CLK GPIO_NUM_48 // SPI时钟引脚
|
||||
#define ST7789_PIN_DC GPIO_NUM_38 // 数据/命令选择引脚RSEL
|
||||
#define ST7789_PIN_MOSI GPIO_NUM_47 // SPI数据输出引脚
|
||||
#define ST7789_PIN_CS GPIO_NUM_46 // SPI片选引脚
|
||||
#define ST7789_PIN_BL GPIO_NUM_45 // 背光引脚
|
||||
#define ST7789_PIN_RST GPIO_NUM_NC // 复位引脚
|
||||
#define LCD_BL_ACTIVE_LEVEL 0 // 背光有效电平:1=高电平有效(NMOS),0=低电平有效(PMOS)
|
||||
|
||||
#define LCD_WIDTH 172 // 屏幕宽度(水平方向像素数)
|
||||
#define LCD_HEIGHT 320 // 屏幕高度(垂直方向像素数)
|
||||
|
||||
/* 毫米波雷达配置参数 */
|
||||
/* 定义毫米波雷达的中断引脚 */
|
||||
#define MILLIMETER_WAVE_RADAR_PIN GPIO_NUM_35
|
||||
// UART 配置参数
|
||||
#define RADAR_UART_NUM UART_NUM_1 // 使用 UART1
|
||||
#define UART_TX_PIN GPIO_NUM_40 // GPIO40 作为 TX(根据实际硬件连接调整)
|
||||
#define UART_RX_PIN GPIO_NUM_39 // GPIO39 作为 RX
|
||||
#define RADAR_BAUD_RATE 9600 // 雷达波特率
|
||||
#define RADAR_BUF_SIZE 100 // 雷达接收缓冲区大小
|
||||
|
||||
/* IO扩展硬件配置常量 */
|
||||
#define I2C_MASTER_FREQ_HZ 100000 // I2C通信频率(100kHz)(可更改至400000)
|
||||
#define I2C_IO_EXPAND_SLAVE_ADDR 0x58 // AW9523BTQR器件地址,v1_1_13的addr1和addr0是0
|
||||
#define GPIO_INPUT_PIN_SEL GPIO_NUM_10 // 中断检测引脚
|
||||
#define ESP_INTR_FLAG_DEFAULT 0 // 中断标志默认值
|
||||
#define IO_EXPAND_RSTN GPIO_NUM_14 // IO扩展板复位引脚
|
||||
|
||||
/* 定义线性马达的I2C从机配置常量 */
|
||||
#define LINEAR_MOTOR_I2C_SLAVE_ADDR 0x5A // 线性马达的I2C从机地址
|
||||
|
||||
/* 定义陀螺仪的I2C从机配置常量 */
|
||||
#define GYROSCOPE_I2C_SLAVE_ADDR 0x6A // 陀螺仪的I2C从机地址
|
||||
#define GYROSCOPE_INPUT_PIN_SEL GPIO_NUM_21 // 陀螺仪中断引脚
|
||||
|
||||
/* AW触摸芯片配置 */
|
||||
#define AW_TOUCH_IRQ_PIN GPIO_NUM_11 // AW触摸芯片中断引脚
|
||||
#define NFC_RST_PIN GPIO_NUM_12 // NFC复位引脚
|
||||
#define AUD_CTRL_PIN GPIO_NUM_13 // AUD_CTRL引脚
|
||||
|
||||
/* 原生触摸引脚配置 (v1.1.18已改为上述功能,保留定义需谨慎) */
|
||||
// 触摸按键数量配置
|
||||
#define TOUCH_BUTTON_NUM 3
|
||||
// 触摸通道定义 - 注意:v1.1.18如果不使用ESP32原生触摸,这些定义可能不再适用
|
||||
// 但为了兼容编译,可以保留或注释
|
||||
#define TOUCH_PAD_CHANNEL_1 TOUCH_PAD_NUM11 // GPIO11 (Now AW_IRQ)
|
||||
#define TOUCH_PAD_CHANNEL_2 TOUCH_PAD_NUM12 // GPIO12 (Now NFC_RST)
|
||||
#define TOUCH_PAD_CHANNEL_3 TOUCH_PAD_NUM13 // GPIO13 (Now AUD_CTRL)
|
||||
|
||||
/* ES8311音频编解码器配置 (ESP-ADF兼容) */
|
||||
#define AUDIO_INPUT_SAMPLE_RATE 24000
|
||||
#define AUDIO_OUTPUT_SAMPLE_RATE 24000
|
||||
#define AUDIO_INPUT_REFERENCE true
|
||||
|
||||
/* I2S GPIO定义 */
|
||||
#define AUDIO_I2S_GPIO_MCLK GPIO_NUM_15
|
||||
#define AUDIO_I2S_GPIO_WS GPIO_NUM_4
|
||||
#define AUDIO_I2S_GPIO_BCLK GPIO_NUM_5
|
||||
#define AUDIO_I2S_GPIO_DIN GPIO_NUM_6
|
||||
#define AUDIO_I2S_GPIO_DOUT GPIO_NUM_7
|
||||
|
||||
/* PA引脚定义 */
|
||||
#define AUDIO_CODEC_PA_PIN GPIO_NUM_NC
|
||||
|
||||
/* I2C配置 */
|
||||
#define AUDIO_CODEC_I2C_SDA_PIN GPIO_NUM_2
|
||||
#define AUDIO_CODEC_I2C_SCL_PIN GPIO_NUM_3
|
||||
#define AUDIO_CODEC_ES8311_ADDR 0x18
|
||||
#define AUDIO_CODEC_ES7210_ADDR 0x40
|
||||
|
||||
/* WS2812 RGB LED配置 */
|
||||
#define WS2812_PIN GPIO_NUM_41 // WS2812数据引脚
|
||||
#define WS2812_NUM_LEDS 2 // WS2812 LED数量
|
||||
|
||||
/* 创建VBAT to VBAT_5V */
|
||||
#define VBAT_5V_PIN GPIO_NUM_NC // VBAT_5V引脚
|
||||
|
||||
/* 定义按键的中断引脚 */
|
||||
#define BUTTON_PIN GPIO_NUM_0 // 按键中断引脚
|
||||
#define RIGHT_BUTTON_PIN GPIO_NUM_8 // 按键中断引脚
|
||||
|
||||
/* 底座控制命令串口配置 */
|
||||
#define BASE_BOARD_CTL_UART_PORT UART_NUM_0
|
||||
#define BASE_BOARD_CTL_UART_TX_PIN GPIO_NUM_43
|
||||
#define BASE_BOARD_CTL_UART_RX_PIN GPIO_NUM_44
|
||||
#define BASE_BOARD_CTL_UART_BAUDRATE 115200
|
||||
#define BASE_BOARD_CTL_UART_BUF_SIZE 256
|
||||
|
||||
/* 背光控制引脚配置 */
|
||||
#define BL_PIN GPIO_NUM_45
|
||||
|
||||
#endif // _BOARD_CONFIG_H_
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,432 @@
|
||||
#ifndef IO_EXPANSION_BOARD_H
|
||||
#define IO_EXPANSION_BOARD_H
|
||||
|
||||
#include <cstdint>
|
||||
#include <esp_log.h>
|
||||
#include <esp_check.h>
|
||||
#include <esp_timer.h>
|
||||
#include <driver/gpio.h>
|
||||
#include <functional>
|
||||
#include "i2c_bus.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/event_groups.h"
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
#include <freertos/FreeRTOS.h>
|
||||
#include <freertos/task.h>
|
||||
#include <freertos/queue.h>
|
||||
#include <freertos/semphr.h>
|
||||
#include "esp_err.h"
|
||||
#include "config.h"
|
||||
#include "portmacro.h"
|
||||
|
||||
// 前向声明,避免循环引用
|
||||
class MillimeterWaveRadar;
|
||||
class PhotoInterrupter;
|
||||
class AdcBatteryMonitor;
|
||||
|
||||
// 回调函数类型定义
|
||||
typedef std::function<void()> RadarCallback;
|
||||
typedef std::function<void()> PhotoInterrupterStartCallback;
|
||||
typedef std::function<void()> PhotoInterrupterEndCallback;
|
||||
typedef std::function<void()> BatteryChargingCallback;
|
||||
typedef std::function<void()> BatteryFullCallback;
|
||||
typedef std::function<void()> BatteryNotChargingCallback;
|
||||
|
||||
/* 寄存器地址 */
|
||||
#define INPUT_PORT0 0x00 // 输入端口0寄存器
|
||||
#define INPUT_PORT1 0x01 // 输入端口1寄存器 0为低电平(仅支持读取)
|
||||
#define OUTPUT_PORT0 0x02 // 输出端口0寄存器
|
||||
#define OUTPUT_PORT1 0x03 // 输出端口1寄存器 0为低电平
|
||||
#define CONFIG_PORT0 0x04 // 配置端口0寄存器
|
||||
#define CONFIG_PORT1 0x05 // 配置端口1寄存器 0为输出模式
|
||||
#define INT_PORT0 0x06 // 中断端口0寄存器
|
||||
#define INT_PORT1 0x07 // 中断端口1寄存器 0为使能中断(根据手册默认是使能的)
|
||||
#define CTL 0x11 // 全局控制寄存器
|
||||
#define ID 0x23 // 芯片ID寄存器(0x23)
|
||||
|
||||
/***********************************IO扩展板电机引脚配置参数*************************************/
|
||||
/* 设置步进电机方向 */
|
||||
#define STEPPER_MOTOR_LEFT false //步进电机的方向为左转
|
||||
#define STEPPER_MOTOR_RIGHT true //步进电机的方向为右转
|
||||
#define STEPPER_MOTOR_DIR_PORT OUTPUT_PORT0 //步进电机方向引脚挂载在IO扩展板的输出端口OUTPUT_PORT0
|
||||
#define STEPPER_MOTOR_DIR_PIN 4 //步进电机方向引脚对应的IO扩展板引脚P0_4
|
||||
#define STEPPER_MOTOR_DIR_CONFIG CONFIG_PORT0 //步进电机方向引脚配置在P0_4
|
||||
|
||||
/* 设置步进电机细分模式 */
|
||||
#define STEPPER_MOTOR_M0_PIN 5 //步进电机细分模式选择引脚对应IO扩展板引脚P1_5
|
||||
#define STEPPER_MOTOR_M0_MADE_PORT OUTPUT_PORT1 //步进电机模式选择引脚挂载在IO扩展板的输出端口OUTPUT_PORT1
|
||||
#define STEPPER_MOTOR_M0_CONFIG CONFIG_PORT1 //步进电机细分模式选择引脚配置在P1_5
|
||||
|
||||
#define STEPPER_MOTOR_M1_PIN 4 //步进电机细分模式选择引脚对应IO扩展板引脚P1_4
|
||||
#define STEPPER_MOTOR_M1_MADE_PORT OUTPUT_PORT1 //步进电机模式选择引脚挂载在IO扩展板的输出端口OUTPUT_PORT1
|
||||
#define STEPPER_MOTOR_M1_CONFIG CONFIG_PORT1 //步进电机细分模式选择引脚配置在P1_4
|
||||
|
||||
/* 设置步进电机睡眠引脚 */
|
||||
#define STEPPER_MOTOR_SLEEP false //步进电机进入睡眠模式
|
||||
#define STEPPER_MOTOR_WORK true //步进电机进入工作模式
|
||||
#define STEPPER_MOTOR_SLEEP_PIN 6 //步进电机睡眠引脚对应IO扩展板引脚P1_6
|
||||
#define STEPPER_MOTOR_SLEEP_CONFIG CONFIG_PORT1 //步进电机睡眠引脚配置在P1_6
|
||||
#define STEPPER_MOTOR_SLEEP_PORT OUTPUT_PORT1 //步进电机睡眠引脚挂载在IO扩展板的输出端口OUTPUT_PORT1
|
||||
|
||||
/* 设置电机的使能引脚 */
|
||||
#define STEPPER_MOTOR_ENABLE_PIN 7 //电机使能引脚对应IO扩展板引脚P0_7
|
||||
#define STEPPER_MOTOR_ENABLE_PORT OUTPUT_PORT0 //电机使能引脚挂载在IO扩展板的输出端口OUTPUT_PORT0
|
||||
#define STEPPER_MOTOR_ENABLE_CONFIG CONFIG_PORT0 //电机使能引脚配置在P0_7
|
||||
#define STEPPER_MOTOR_ENABLE_ENABLE true //电机使能引脚状态为高电平
|
||||
#define STEPPER_MOTOR_ENABLE_DISABLE false //电机使能引脚状态为低电平
|
||||
|
||||
/* 设置毫米波雷达对应IO扩展板的中断引脚 */
|
||||
#define RADAR_INTERRUPT_PIN 7 //毫米波雷达中断引脚对应IO扩展板引脚P1_7
|
||||
#define RADAR_INTERRUPT_CONFIG CONFIG_PORT1 //毫米波雷达中断引脚挂载在IO扩展板的输入端口
|
||||
#define RADAR_INTERRUPT_INPUT INPUT_PORT1 //毫米波雷达中断引脚输入状态检测在INPUT_PORT1
|
||||
#define RADAR_INTERRUPT_ENABLE true //毫米波雷达中断引脚状态为输入状态
|
||||
#define RADAR_INTERRUPT_DISABLE false //毫米波雷达中断引脚状态为输出状态
|
||||
/* 任务配置常量 */
|
||||
#define WRITE_BUF_SIZE 2 // I2C单次写入字节数
|
||||
#define READ_BUF_SIZE 2 // I2C单次读取字节数
|
||||
#define I2C_TASK_PRIORITY 2 // 任务优先级(中等)
|
||||
#define I2C_TASK_STACK 4096 // 任务栈大小(4KB)
|
||||
|
||||
// 光学传感器引脚定义
|
||||
#define START_PHOTO_INTERRUPTER_PIN 2 // 光学传感器引脚(P0_2)
|
||||
#define START_PHOTO_INTERRUPTER_CONFIG CONFIG_PORT0 // 光学传感器引脚挂载在IO扩展板的输入端口
|
||||
#define START_PHOTO_INTERRUPTER_INPUT INPUT_PORT0 // 光学传感器引脚输入状态检测在INPUT_PORT0
|
||||
#define START_PHOTO_INTERRUPTER_HIGH true // 光学传感器引脚状态为高电平
|
||||
#define START_PHOTO_INTERRUPTER_LOW false // 光学传感器引脚状态为低电平
|
||||
|
||||
#define END_PHOTO_INTERRUPTER_PIN 3 // 光学传感器引脚(P0_3)
|
||||
#define END_PHOTO_INTERRUPTER_PORT_CONFIG CONFIG_PORT0 // 光学传感器引脚挂载在IO扩展板的输入端口
|
||||
#define END_PHOTO_INTERRUPTER_INPUT INPUT_PORT0 // 光学传感器引脚输入状态检测在INPUT_PORT0
|
||||
#define END_PHOTO_INTERRUPTER_HIGH true // 光学传感器引脚状态为高电平
|
||||
#define END_PHOTO_INTERRUPTER_LOW false // 光学传感器引脚状态为低电平
|
||||
|
||||
/***********************************IO扩展板LCD引脚配置参数*************************************/
|
||||
// /* 设置LCD的BL引脚 */
|
||||
// #define LCD_BL_PIN 6 //LCD背光引脚对应IO扩展板引脚P0_6
|
||||
// #define LCD_BL_PORT OUTPUT_PORT0 //LCD背光引脚挂载在IO扩展板的输出端口OUTPUT_PORT0
|
||||
// #define LCD_BL_CONFIG CONFIG_PORT0 //LCD背光引脚配置在P0_6
|
||||
// #define LCD_BL_HIGH true //LCD背光引脚状态为高电平
|
||||
// #define LCD_BL_LOW false //LCD背光引脚状态为低电平
|
||||
|
||||
/* 设置LED_EN (LCD背光/LED控制)引脚, PMOS高侧驱动 */
|
||||
#define LED_EN_PIN 1 //LED_EN对应IO扩展板引脚P0_1
|
||||
#define LED_EN_PORT OUTPUT_PORT0 //挂载在输出端口OUTPUT_PORT0
|
||||
#define LED_EN_CONFIG CONFIG_PORT0 //配置在P0_1
|
||||
#define LED_EN_OFF true //高电平关(PMOS)
|
||||
#define LED_EN_ON false //低电平开(PMOS)
|
||||
|
||||
/* 设置LCD的RST引脚 */
|
||||
#define LCD_RST_PIN 1 //LCD复位引脚对应IO扩展板引脚P1_1
|
||||
#define LCD_RST_CONFIG CONFIG_PORT1 //LCD复位引脚配置在P1_1
|
||||
#define LCD_RST_PORT OUTPUT_PORT1 //LCD复位引脚挂载在IO扩展板的输出端口OUTPUT_PORT1
|
||||
#define LCD_RST_HIGH true //LCD复位引脚状态为高电平
|
||||
#define LCD_RST_LOW false //LCD复位引脚状态为低电平
|
||||
|
||||
/* 设置PA控制引脚 */
|
||||
#define PA_CTRL_PIN 2 //PA控制引脚对应IO扩展板引脚P1_2
|
||||
#define PA_CTRL_CONFIG CONFIG_PORT1 //PA控制引脚配置在P1_2
|
||||
#define PA_CTRL_PORT OUTPUT_PORT1 //PA控制引脚挂载在IO扩展板的输出端口OUTPUT_PORT1
|
||||
#define PA_CTRL_HIGH true //PA控制引脚状态为高电平
|
||||
#define PA_CTRL_LOW false //PA控制引脚状态为低电平
|
||||
|
||||
// 电池充电检测引脚定义
|
||||
#define BATTERY_FULL_INPUT INPUT_PORT1 // 电池充满检测引脚挂载在IO扩展板的输入端口
|
||||
#define BATTERY_FULL_PIN 3 // 电池充满检测引脚对应IO扩展板引脚P1_3
|
||||
#define BATTERY_FULL_CONFIG CONFIG_PORT1 // 电池充满检测引脚配置在P1_3
|
||||
|
||||
#define BATTERY_CHRG_INPUT INPUT_PORT0 // 充电检测引脚挂载在IO扩展板的输入端口
|
||||
#define BATTERY_CHRG_PIN 5 // 充电检测引脚(P0_5)
|
||||
#define BATTERY_CHRG_CONFIG CONFIG_PORT0 // 充电检测引脚挂载在IO扩展板的输入端口
|
||||
|
||||
#define TAG_GPIO_IO_EXPAND_DETECT "GPIO_IO_EXPAND_DETECT" // GPIO中断检测日志标签
|
||||
#define TAG_I2C_IO_EXPAND_TASK "I2C_IO_EXPAND_TASK" // I2CIO扩展板任务日志标签
|
||||
|
||||
// GPIO引脚定义
|
||||
#define GPIO_INPUT_PIN_SEL GPIO_NUM_10 // IO扩展板中断检测引脚
|
||||
// #define IO_EXPAND_RSTN GPIO_NUM_14 // IO扩展板复位引脚
|
||||
|
||||
/**
|
||||
* @class IOExpansionBoard
|
||||
* @brief I/O扩展板驱动类,封装AW9523BTQR芯片操作
|
||||
*/
|
||||
class IOExpansionBoard
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief 构造函数
|
||||
*/
|
||||
IOExpansionBoard();
|
||||
|
||||
/**
|
||||
* @brief 设置毫米波雷达指针
|
||||
* @param radar 毫米波雷达对象指针
|
||||
*/
|
||||
void SetRadar(MillimeterWaveRadar* radar) { radar_ = radar; };
|
||||
|
||||
/**
|
||||
* @brief 设置限位开关指针
|
||||
* @param photo_interrupter 限位开关对象指针
|
||||
*/
|
||||
void setPhotoInterrupter(PhotoInterrupter* photo_interrupter) { photo_interrupter_ = photo_interrupter; };
|
||||
|
||||
/**
|
||||
* @brief 设置电池监控器指针
|
||||
* @param battery_monitor 电池监控器对象指针
|
||||
*/
|
||||
void setBatteryMonitor(AdcBatteryMonitor* battery_monitor) { battery_monitor_ = battery_monitor; };
|
||||
|
||||
/**
|
||||
* @brief 析构函数
|
||||
*/
|
||||
~IOExpansionBoard();
|
||||
|
||||
/**
|
||||
* @brief 初始化GPIO中断检测
|
||||
* @param gpio_num 中断引脚编号
|
||||
* @return esp_err_t 初始化结果
|
||||
*/
|
||||
esp_err_t InterruptGpioInit(gpio_num_t gpio_num);
|
||||
|
||||
/**
|
||||
* @brief 初始化IO扩展板复位引脚
|
||||
* @param gpio_num 复位引脚编号
|
||||
* @return esp_err_t 初始化结果
|
||||
*/
|
||||
esp_err_t ResetGpioInit(gpio_num_t gpio_num);
|
||||
|
||||
/**
|
||||
* @brief 初始化IO扩展板复位引脚
|
||||
* @param gpio_num 复位引脚编号
|
||||
* @return esp_err_t 初始化结果
|
||||
*/
|
||||
esp_err_t ResetIoExpand();
|
||||
|
||||
/**
|
||||
* @brief 初始化I2C主机通信
|
||||
* @return esp_err_t 初始化结果
|
||||
*/
|
||||
// esp_err_t IoExpansionI2cInit();
|
||||
|
||||
/**
|
||||
* @brief 创建I2C数据读取任务
|
||||
*/
|
||||
void CreateI2cReadTask();
|
||||
|
||||
/**
|
||||
* @brief 启动I2C任务(整合初始化和任务创建)
|
||||
* @return esp_err_t 操作结果
|
||||
*/
|
||||
esp_err_t StartTask();
|
||||
|
||||
/**
|
||||
* @brief 写寄存器数据
|
||||
* @param reg_addr 寄存器地址
|
||||
* @param data 要写入的数据
|
||||
* @return esp_err_t 操作结果
|
||||
*/
|
||||
esp_err_t IoexpandWriteReg(uint8_t reg_addr, uint8_t data);
|
||||
|
||||
/**
|
||||
* @brief 读寄存器数据
|
||||
* @param reg_addr 寄存器地址
|
||||
* @param data 要读出的数据
|
||||
* @return esp_err_t 操作结果
|
||||
*/
|
||||
esp_err_t IoexpandReadReg(uint8_t reg_addr, uint8_t *data);
|
||||
|
||||
/**
|
||||
* @brief 读取输入端口0寄存器数据
|
||||
* @param data 输出参数,用于存储读取到的数据
|
||||
* @return esp_err_t 操作结果
|
||||
*/
|
||||
esp_err_t ReadInputPort0(uint8_t *data);
|
||||
|
||||
/**
|
||||
* @brief 读取输入端口1寄存器数据
|
||||
* @param data 输出参数,用于存储读取到的数据
|
||||
* @return esp_err_t 操作结果
|
||||
*/
|
||||
esp_err_t ReadInputPort1(uint8_t *data);
|
||||
|
||||
// /**
|
||||
// * @brief 设置IO扩展板GPIO中断状态 通过读取Input_Port0 和 Input_Port1 寄存器可以清除中断
|
||||
// * @param reg_addr 寄存器地址
|
||||
// * @return esp_err_t 操作结果
|
||||
// */
|
||||
// esp_err_t SetInterruptStatus(bool status);
|
||||
|
||||
/**
|
||||
* @brief 配置IO扩展版上的IO口为输出还是输入,并且设置初始为高电平
|
||||
* @return esp_err_t 操作结果
|
||||
*/
|
||||
esp_err_t IoexpandSetMode();
|
||||
|
||||
/**
|
||||
* @brief 设置步进电机的细分模式
|
||||
* @param mode 模式:1/2/4/8/16/32/64
|
||||
* @return esp_err_t 操作结果
|
||||
*/
|
||||
void SetStepperMicrostepMode(uint8_t mode, uint8_t OUTPUT_PORT_m0, uint8_t m0_pin, uint8_t OUTPUT_PORT_m1, uint8_t m1_pin);
|
||||
|
||||
/**
|
||||
* @brief 设置步进电机的方向
|
||||
* @param dir 方向
|
||||
* @param OUTPUT_PORT 输出端口
|
||||
* @param pin 引脚号
|
||||
* @return esp_err_t 操作结果
|
||||
*/
|
||||
esp_err_t StepperMotorSetDir(bool dir, uint8_t OUTPUT_PORT, uint8_t pin);
|
||||
|
||||
/**
|
||||
* @brief 设置步进电机的睡眠模式
|
||||
* @param 是否进入睡眠模式
|
||||
* @param 输出端口
|
||||
* @param 引脚号
|
||||
* @return esp_err_t 操作结果
|
||||
*/
|
||||
esp_err_t SetMotorSleepMode(bool mode, uint8_t OUTPUT_PORT, uint8_t nsleep_pin);
|
||||
|
||||
/**
|
||||
* @brief 设置步进电机的使能引脚状态
|
||||
* @param 使能状态
|
||||
* @return esp_err_t 操作结果
|
||||
*/
|
||||
esp_err_t SetMotorEnableMode(bool enable, uint8_t OUTPUT_PORT, uint8_t enable_pin);
|
||||
|
||||
/**
|
||||
* @brief 设置LCD的BL引脚状态
|
||||
* @param BL状态
|
||||
* @return esp_err_t 操作结果
|
||||
*/
|
||||
esp_err_t SetLcdBlMode(bool mode, uint8_t OUTPUT_PORT, uint8_t bl_pin);
|
||||
|
||||
/**
|
||||
* @brief 设置 LED_EN 引脚电平(用于控制LCD背光/LED灯电源)
|
||||
* @param mode true:开启(低电平), false:关闭(高电平)
|
||||
*/
|
||||
esp_err_t SetLedEnMode(bool mode);
|
||||
|
||||
/**
|
||||
* @brief 设置LCD的RST引脚状态
|
||||
* @param RST状态
|
||||
* @return esp_err_t 操作结果
|
||||
*/
|
||||
esp_err_t SetLcdResetMode(bool mode, uint8_t OUTPUT_PORT, uint8_t rst_pin);
|
||||
|
||||
/**
|
||||
* @brief 设置PA控制引脚状态
|
||||
* @param mode PA_CTRL状态(true为高电平,false为低电平)
|
||||
* @return esp_err_t 操作结果
|
||||
*/
|
||||
esp_err_t SetPaCtrlMode(bool mode);
|
||||
|
||||
/**
|
||||
* @brief 设置雷达中断引脚
|
||||
* @param 毫米波雷达的中断引脚模式
|
||||
* @param 输入端口
|
||||
* @param 引脚号
|
||||
* @return esp_err_t 操作结果
|
||||
*/
|
||||
esp_err_t SetRadarInterruptPin(bool mode, uint8_t INPUT_PORT, uint8_t interrupt_pin);
|
||||
|
||||
/**
|
||||
* @brief 计算Port0的字节值
|
||||
* @return uint8_t 操作结果
|
||||
*/
|
||||
uint8_t ByteCalculatePort0();
|
||||
|
||||
/**
|
||||
* @brief 计算Port1的字节值
|
||||
* @return uint8_t 操作结果
|
||||
*/
|
||||
uint8_t ByteCalculatePort1();
|
||||
|
||||
/**
|
||||
* @brief 设置雷达中断回调函数
|
||||
* @param callback 雷达中断回调函数
|
||||
*/
|
||||
void SetRadarCallback(RadarCallback callback) { radar_callback_ = callback; }
|
||||
|
||||
/**
|
||||
* @brief 设置光学传感器开始中断回调函数
|
||||
* @param callback 光学传感器开始中断回调函数
|
||||
*/
|
||||
void SetPhotoInterrupterStartCallback(PhotoInterrupterStartCallback callback) { photo_start_callback_ = callback; }
|
||||
|
||||
/**
|
||||
* @brief 设置光学传感器结束中断回调函数
|
||||
* @param callback 光学传感器结束中断回调函数
|
||||
*/
|
||||
void SetPhotoInterrupterEndCallback(PhotoInterrupterEndCallback callback) { photo_end_callback_ = callback; }
|
||||
|
||||
/**
|
||||
* @brief 设置电池充电中断回调函数
|
||||
* @param callback 电池充电中断回调函数
|
||||
*/
|
||||
void SetBatteryChargingCallback(BatteryChargingCallback callback) { battery_charging_callback_ = callback; }
|
||||
|
||||
/**
|
||||
* @brief 设置电池充满中断回调函数
|
||||
* @param callback 电池充满中断回调函数
|
||||
*/
|
||||
void SetBatteryFullCallback(BatteryFullCallback callback) { battery_full_callback_ = callback; }
|
||||
|
||||
/**
|
||||
* @brief 设置电池非充电中断回调函数
|
||||
* @param callback 电池非充电中断回调函数
|
||||
*/
|
||||
void SetBatteryNotChargingCallback(BatteryNotChargingCallback callback) { battery_not_charging_callback_ = callback; }
|
||||
|
||||
// 公共成员变量
|
||||
i2c_bus_handle_t bus_handle_ = nullptr; // I2C总线句柄
|
||||
uint8_t device_addr_; // I2C设备地址
|
||||
|
||||
private:
|
||||
// 静态成员函数
|
||||
MillimeterWaveRadar* radar_ = nullptr; // 毫米波雷达指针,用于触发回调
|
||||
PhotoInterrupter* photo_interrupter_ = nullptr; // 限位开关指针,用于触发回调
|
||||
AdcBatteryMonitor* battery_monitor_ = nullptr; // 电池监控器指针,用于触发回调
|
||||
static void IRAM_ATTR GpioIsrHandler(void* arg); // 中断处理函数
|
||||
static void I2cReadTask(void* pvParameters); // I2C数据读取任务函数
|
||||
|
||||
// 成员变量用于状态跟踪
|
||||
uint8_t last_port0_state_ = 0; // 上次检测到的Port0状态
|
||||
uint8_t last_port1_state_ = 0; // 上次检测到的Port1状态
|
||||
bool radar_last_state_ = false; // 雷达引脚上一次的状态
|
||||
bool battery_charging_last_state_ = false; // 电池充电状态上一次的状态
|
||||
bool battery_full_last_state_ = false; // 电池充满状态上一次的状态
|
||||
|
||||
// 回调函数成员变量
|
||||
RadarCallback radar_callback_ = nullptr;
|
||||
PhotoInterrupterStartCallback photo_start_callback_ = nullptr;
|
||||
PhotoInterrupterEndCallback photo_end_callback_ = nullptr;
|
||||
BatteryChargingCallback battery_charging_callback_ = nullptr;
|
||||
BatteryFullCallback battery_full_callback_ = nullptr;
|
||||
BatteryNotChargingCallback battery_not_charging_callback_ = nullptr;
|
||||
|
||||
// PhotoInterrupter* photo_interrupter_ = nullptr; // 光学传感器指针,用于触发回调
|
||||
// /**
|
||||
// * @brief 分配静态任务所需的内存
|
||||
// * @return bool 分配是否成功
|
||||
// */
|
||||
// bool AllocateStaticTaskMemory();
|
||||
|
||||
// /**
|
||||
// * @brief 释放静态任务分配的内存
|
||||
// */
|
||||
// void FreeStaticTaskMemory();
|
||||
|
||||
// 实例成员变量
|
||||
EventGroupHandle_t i2c_task_event_group_ = nullptr; // 事件组
|
||||
TaskHandle_t xI2CReadTaskHandle_ = nullptr; // 任务句柄
|
||||
bool is_initialized_ = false; // 初始化状态标记(新增)
|
||||
gpio_num_t interrupt_gpio_ = GPIO_NUM_NC; // 中断引脚
|
||||
gpio_num_t reset_gpio_ = GPIO_NUM_NC; // 复位引脚
|
||||
|
||||
// StackType_t* pI2CReadTaskStackBuffer = nullptr; // 任务栈指针(PSRAM)
|
||||
// StaticTask_t* pxI2CReadTaskBuffer = nullptr; // 任务控制块指针(内部RAM)
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,178 @@
|
||||
/**
|
||||
* @file power_management_config.h
|
||||
* @brief 功耗管理配置和策略定义
|
||||
* @author Embedded Software Expert
|
||||
* @date 2025年1月
|
||||
*
|
||||
* 这个文件定义了功耗管理的配置参数、策略和优化建议,
|
||||
* 为系统提供灵活的功耗管理方案。
|
||||
*/
|
||||
|
||||
#ifndef POWER_MANAGEMENT_CONFIG_H
|
||||
#define POWER_MANAGEMENT_CONFIG_H
|
||||
|
||||
#include "esp_sleep.h"
|
||||
#include "driver/rtc_io.h"
|
||||
#include "esp32/rom/rtc.h"
|
||||
|
||||
/**
|
||||
* @brief 功耗管理配置结构体
|
||||
*/
|
||||
typedef struct {
|
||||
// 睡眠模式配置
|
||||
uint64_t light_sleep_duration_us; // 轻度睡眠持续时间(微秒)
|
||||
uint64_t deep_sleep_duration_us; // 深度睡眠持续时间(微秒)
|
||||
|
||||
// 唤醒源配置
|
||||
bool enable_timer_wakeup; // 启用定时器唤醒
|
||||
bool enable_gpio_wakeup; // 启用GPIO唤醒
|
||||
bool enable_touch_wakeup; // 启用触摸唤醒
|
||||
gpio_num_t wakeup_gpio_num; // 唤醒GPIO编号
|
||||
int wakeup_level; // 唤醒电平(0或1)
|
||||
|
||||
// 功耗优化配置
|
||||
bool disable_bt_in_sleep; // 睡眠时关闭蓝牙
|
||||
bool disable_wifi_in_sleep; // 睡眠时关闭WiFi
|
||||
bool reduce_cpu_frequency; // 降低CPU频率
|
||||
uint32_t cpu_frequency_hz; // CPU频率(Hz)
|
||||
|
||||
// 外设功耗配置
|
||||
bool power_down_sdcard; // 睡眠时关闭SD卡电源
|
||||
bool power_down_display; // 睡眠时关闭显示电源
|
||||
bool power_down_audio; // 睡眠时关闭音频电源
|
||||
bool power_down_motor; // 睡眠时关闭电机电源
|
||||
|
||||
// RTC内存配置
|
||||
bool preserve_rtc_memory; // 保留RTC内存
|
||||
size_t rtc_memory_size; // RTC内存大小
|
||||
} power_management_config_t;
|
||||
|
||||
/**
|
||||
* @brief 默认功耗管理配置
|
||||
*/
|
||||
#define DEFAULT_POWER_CONFIG { \
|
||||
.light_sleep_duration_us = 1000000, /* 1秒 */ \
|
||||
.deep_sleep_duration_us = 30000000, /* 30秒 */ \
|
||||
.enable_timer_wakeup = true, /* 启用定时器唤醒 */ \
|
||||
.enable_gpio_wakeup = false, /* 不启用GPIO唤醒 */ \
|
||||
.enable_touch_wakeup = false, /* 不启用触摸唤醒 */ \
|
||||
.wakeup_gpio_num = GPIO_NUM_NC, /* 无GPIO唤醒 */ \
|
||||
.wakeup_level = 0, /* 低电平唤醒 */ \
|
||||
.disable_bt_in_sleep = true, /* 睡眠时关闭蓝牙 */ \
|
||||
.disable_wifi_in_sleep = true, /* 睡眠时关闭WiFi */ \
|
||||
.reduce_cpu_frequency = true, /* 降低CPU频率 */ \
|
||||
.cpu_frequency_hz = 80000000, /* 80MHz */ \
|
||||
.power_down_sdcard = true, /* 睡眠时关闭SD卡 */ \
|
||||
.power_down_display = true, /* 睡眠时关闭显示 */ \
|
||||
.power_down_audio = true, /* 睡眠时关闭音频 */ \
|
||||
.power_down_motor = true, /* 睡眠时关闭电机 */ \
|
||||
.preserve_rtc_memory = true, /* 保留RTC内存 */ \
|
||||
.rtc_memory_size = 4096, /* 4KB RTC内存 */ \
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 各功耗模式的详细配置
|
||||
*/
|
||||
static const power_management_config_t idle_mode_config = {
|
||||
.light_sleep_duration_us = 500000, // 500ms轻度睡眠
|
||||
.deep_sleep_duration_us = 0, // 不使用深度睡眠
|
||||
.enable_timer_wakeup = true,
|
||||
.enable_gpio_wakeup = true,
|
||||
.wakeup_gpio_num = GPIO_NUM_0, // 按键唤醒
|
||||
.wakeup_level = 0,
|
||||
.disable_bt_in_sleep = false, // 保持蓝牙连接
|
||||
.disable_wifi_in_sleep = false, // 保持WiFi连接
|
||||
.reduce_cpu_frequency = true,
|
||||
.cpu_frequency_hz = 40000000, // 40MHz
|
||||
.power_down_sdcard = false, // 保持SD卡(可能有后台任务)
|
||||
.power_down_display = true, // 关闭显示背光
|
||||
.power_down_audio = true, // 关闭音频
|
||||
.power_down_motor = true, // 关闭电机
|
||||
.preserve_rtc_memory = true,
|
||||
.rtc_memory_size = 2048,
|
||||
};
|
||||
|
||||
static const power_management_config_t light_sleep_config = {
|
||||
.light_sleep_duration_us = 0, // 直接进入轻度睡眠
|
||||
.deep_sleep_duration_us = 0,
|
||||
.enable_timer_wakeup = true,
|
||||
.enable_gpio_wakeup = true,
|
||||
.wakeup_gpio_num = GPIO_NUM_0,
|
||||
.wakeup_level = 0,
|
||||
.disable_bt_in_sleep = true, // 关闭蓝牙
|
||||
.disable_wifi_in_sleep = true, // 关闭WiFi
|
||||
.reduce_cpu_frequency = true,
|
||||
.cpu_frequency_hz = 40000000,
|
||||
.power_down_sdcard = true, // 关闭SD卡
|
||||
.power_down_display = true, // 关闭显示
|
||||
.power_down_audio = true, // 关闭音频
|
||||
.power_down_motor = true, // 关闭电机
|
||||
.preserve_rtc_memory = true,
|
||||
.rtc_memory_size = 4096,
|
||||
};
|
||||
|
||||
static const power_management_config_t deep_sleep_config = {
|
||||
.light_sleep_duration_us = 0,
|
||||
.deep_sleep_duration_us = 60000000, // 60秒深度睡眠
|
||||
.enable_timer_wakeup = true,
|
||||
.enable_gpio_wakeup = true,
|
||||
.wakeup_gpio_num = GPIO_NUM_0,
|
||||
.wakeup_level = 0,
|
||||
.disable_bt_in_sleep = true, // 关闭蓝牙
|
||||
.disable_wifi_in_sleep = true, // 关闭WiFi
|
||||
.reduce_cpu_frequency = true,
|
||||
.cpu_frequency_hz = 10000000, // 10MHz
|
||||
.power_down_sdcard = true, // 关闭SD卡
|
||||
.power_down_display = true, // 关闭显示
|
||||
.power_down_audio = true, // 关闭音频
|
||||
.power_down_motor = true, // 关闭电机
|
||||
.preserve_rtc_memory = true,
|
||||
.rtc_memory_size = 8192,
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 功耗统计和监控结构体
|
||||
*/
|
||||
typedef struct {
|
||||
uint64_t total_sleep_time_us; // 总睡眠时间
|
||||
uint64_t total_wake_time_us; // 总唤醒时间
|
||||
uint32_t sleep_count; // 睡眠次数
|
||||
uint32_t wake_count; // 唤醒次数
|
||||
uint32_t average_sleep_duration_us; // 平均睡眠时长
|
||||
uint32_t average_wake_duration_us; // 平均唤醒时长
|
||||
float estimated_power_saving_percent; // 估计的功耗节省百分比
|
||||
} power_statistics_t;
|
||||
|
||||
/**
|
||||
* @brief 功耗优化建议
|
||||
*
|
||||
* 基于硬件特性和使用模式,提供功耗优化建议
|
||||
*/
|
||||
typedef enum {
|
||||
OPTIMIZATION_NONE = 0,
|
||||
OPTIMIZATION_REDUCE_CPU_FREQ, // 降低CPU频率
|
||||
OPTIMIZATION_DISABLE_UNUSED_PERIPHERALS, // 关闭未使用的外设
|
||||
OPTIMIZATION_USE_LIGHT_SLEEP, // 使用轻度睡眠
|
||||
OPTIMIZATION_USE_DEEP_SLEEP, // 使用深度睡眠
|
||||
OPTIMIZATION_OPTIMIZE_GPIO_STATES, // 优化GPIO状态
|
||||
OPTIMIZATION_USE_RTC_MEMORY, // 使用RTC内存
|
||||
OPTIMIZATION_BATCH_OPERATIONS, // 批量操作
|
||||
} power_optimization_t;
|
||||
|
||||
/**
|
||||
* @brief 功耗管理事件回调
|
||||
*/
|
||||
typedef void (*power_event_callback_t)(power_mode_t old_mode, power_mode_t new_mode, void* user_data);
|
||||
|
||||
/**
|
||||
* @brief 功耗管理事件
|
||||
*/
|
||||
typedef enum {
|
||||
POWER_EVENT_MODE_CHANGE, // 功耗模式改变
|
||||
POWER_EVENT_SLEEP_START, // 睡眠开始
|
||||
POWER_EVENT_SLEEP_END, // 睡眠结束
|
||||
POWER_EVENT_WAKEUP, // 系统唤醒
|
||||
POWER_EVENT_OPTIMIZATION_TRIGGER, // 功耗优化触发
|
||||
} power_event_t;
|
||||
|
||||
#endif // POWER_MANAGEMENT_CONFIG_H
|
||||
@@ -0,0 +1,26 @@
|
||||
#ifndef BOARD_CONFIG_H
|
||||
#define BOARD_CONFIG_H
|
||||
|
||||
#include "sdkconfig.h"
|
||||
|
||||
// 根据menuconfig的配置选择不同版本的config.h文件
|
||||
#ifdef CONFIG_BOARD_VERSION_V1_1_11
|
||||
#include "boards/board_v1_1_11/config.h"
|
||||
#elif defined(CONFIG_BOARD_VERSION_V1_1_12)
|
||||
#include "boards/board_v1_1_12/config.h"
|
||||
#elif defined(CONFIG_BOARD_VERSION_V1_1_13)
|
||||
#include "boards/board_v1_1_13/config.h"
|
||||
#elif defined(CONFIG_BOARD_VERSION_V1_1_14)
|
||||
#include "boards/board_v1_1_14/config.h"
|
||||
#elif defined(CONFIG_BOARD_VERSION_V1_1_16)
|
||||
#include "boards/board_v1_1_16/config.h"
|
||||
#elif defined(CONFIG_BOARD_VERSION_V1_1_17)
|
||||
#include "boards/board_v1_1_17/config.h"
|
||||
#elif defined(CONFIG_BOARD_VERSION_V1_1_18)
|
||||
#include "boards/board_v1_1_18/config.h"
|
||||
#else
|
||||
// 默认使用v1.1.11版本,避免编译错误
|
||||
#include "boards/board_v1_1_13/config.h"
|
||||
#endif
|
||||
|
||||
#endif // BOARD_CONFIG_H
|
||||
@@ -0,0 +1,35 @@
|
||||
# 根据 menuconfig 中选择的板卡配置,自动匹配 boards/board_v* 目录
|
||||
# 这样新增板卡时,只要:
|
||||
# 1. 增加对应的 Kconfig 项,例如 CONFIG_BOARD_VERSION_V1_1_18
|
||||
# 2. 新增目录 02_physical/boards/board_v1_1_18/
|
||||
# 就不需要再修改 main/CMakeLists.txt
|
||||
|
||||
set(BOARD_ROOT_DIR "${CMAKE_CURRENT_LIST_DIR}")
|
||||
set(MAIN_ROOT_DIR "${CMAKE_CURRENT_LIST_DIR}/../..")
|
||||
set(SELECTED_BOARD_DIR "")
|
||||
|
||||
file(GLOB BOARD_CANDIDATE_DIRS RELATIVE "${BOARD_ROOT_DIR}" "${BOARD_ROOT_DIR}/board_v*")
|
||||
|
||||
foreach(board_dir ${BOARD_CANDIDATE_DIRS})
|
||||
if(IS_DIRECTORY "${BOARD_ROOT_DIR}/${board_dir}")
|
||||
string(REGEX REPLACE "^board_" "" board_suffix "${board_dir}")
|
||||
string(TOUPPER "${board_suffix}" board_suffix_upper)
|
||||
set(board_config_var "CONFIG_BOARD_VERSION_${board_suffix_upper}")
|
||||
|
||||
if(DEFINED ${board_config_var} AND ${board_config_var})
|
||||
set(SELECTED_BOARD_DIR "02_physical/boards/${board_dir}")
|
||||
break()
|
||||
endif()
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
if(NOT SELECTED_BOARD_DIR)
|
||||
message(FATAL_ERROR "Please select a board version in menuconfig")
|
||||
endif()
|
||||
|
||||
target_sources(${COMPONENT_LIB} PRIVATE "${SELECTED_BOARD_DIR}/board_sweekar.cc")
|
||||
target_sources(${COMPONENT_LIB} PRIVATE "${SELECTED_BOARD_DIR}/io_expansion_board.cc")
|
||||
target_include_directories(${COMPONENT_LIB} PRIVATE "${SELECTED_BOARD_DIR}")
|
||||
|
||||
# 添加到 main 目录,使类似 "boards/config.h" 的包含路径保持兼容
|
||||
target_include_directories(${COMPONENT_LIB} PRIVATE "${MAIN_ROOT_DIR}")
|
||||
Reference in new issue
Block a user