侧边栏壁纸
博主头像
M的小站

记录问题、证据与可复现的解决过程

  • 累计撰写 15 篇文章
  • 累计创建 36 个标签
  • 累计收到 0 条评论

目 录CONTENT

文章目录

ESP32 项目目录如何长大而不失控(补档)

ESP32 项目目录如何长大而不失控

补档说明:本文整理自一次原型重构。重点不是推荐唯一目录,而是说明每个边界解决了什么问题。

很多 ESP32 项目都从 main.c 开始,这没有错。问题出现在第二块传感器、第二种板型和第一位协作者加入之后:头文件互相包含,GPIO 数字散落各处,构建选项只存在某个人的电脑上。那次重构的目标不是追求“企业级架构”,而是让新功能不会修改十个不相干的文件。

目录按变化原因划分

最终目录大致如下:

project/
├─ main/                 # 组装应用与生命周期
├─ components/
│  ├─ board/             # 引脚、电源与板型差异
│  ├─ sensor_service/    # 传感器抽象和采样策略
│  ├─ ble_protocol/      # 数据模型、编解码、传输
│  ├─ display_ui/        # 显示状态,不直接读硬件
│  └─ storage/           # 配置与日志持久化
├─ configs/              # 各环境的 sdkconfig.defaults
├─ tools/                # 量产、抓日志与数据转换脚本
└─ tests/                # 主机侧纯逻辑测试

board 组件只回答“这块板如何操作”,不会决定采样间隔;sensor_service 决定何时采样,但不知道数据会显示还是通过蓝牙发送。BLE 组件接收稳定的数据结构,不直接访问 I2C。这样更换屏幕或传感器时,变化停在对应边界内。

公共接口要小

每个组件的 include 目录只放调用方真正需要的声明。内部结构体留在源文件,避免其他组件依赖字段布局。返回值统一为错误码,日志里同时打印组件名和关键参数。

esp_err_t sensor_service_start(const sensor_cfg_t *cfg);
esp_err_t sensor_service_read(sensor_sample_t *out, TickType_t wait);
void sensor_service_stop(void);

这里刻意不暴露任务句柄、队列句柄和具体驱动。测试替身只需实现同样的三个动作,应用层就能在主机上演练状态机。

配置分三层

不再把所有差异塞进 menuconfig。构建期能力用 Kconfig,例如是否启用屏幕;板级常量在 board;用户可变参数存 NVS,并提供版本号与迁移函数。敏感值不提交仓库,而是在发布流程中注入。

配置读取遵循“默认值—持久化值—运行时覆盖”的顺序,启动日志会输出最终配置摘要,但掩去密钥。这样现场说“采样频率不对”时,可以先比较事实,而不是猜测烧录了哪一版。

依赖方向比文件夹更重要

我画了一条简单规则:main 可以依赖所有业务组件,业务组件可以依赖基础设施,但基础设施不能反向调用界面。跨组件通知通过事件或窄接口完成。构建时开启循环依赖检查,代码评审看到跨层 include 就先问原因。

重构验收清单

  • [x] 全新目录执行一条命令即可构建
  • [x] 两种板型只切换配置,不修改源码
  • [x] 协议编解码可在电脑上跑单元测试
  • [x] 每个组件有负责人、入口文档和错误码说明
  • [x] 固件打印版本、提交号与配置摘要
  • [x] 删除某个可选组件后,其余工程仍可编译

重构之后代码行数略有增加,但“理解一次修改会影响哪里”的时间明显缩短。目录结构不是为了好看,它是团队对变化方式的共同约定。原型阶段可以简单,准备长期维护时则要尽早固定依赖方向、配置来源和可验证入口。

0

评论区