阶段1: 将 dzbj 项目的 LVGL 8.3.11 LCD 显示集成到 AI小智 主项目, 开机显示 ScreenHome 界面,同时优化配网模式下的内存使用, 确保 WiFi+BLE+LVGL 三者共存运行。 ## 新增功能 ### dzbj 显示模块集成 - 新增 main/dzbj/ 目录,移植 LCD 驱动(ST77916 QSPI)、触摸驱动(CST816S)、 LVGL 初始化和 SquareLine Studio UI 界面 - I2C 总线共享:dzbj 触摸控制器复用主项目的 I2C_NUM_1 总线 - GPIO 冲突解决:LED(GPIO21)、Touch1(GPIO1)、Touch4(GPIO7) 改为 NC, 电池 ADC 从 GPIO6 改为 GPIO3 - 添加 LVGL、esp_lcd_st77916、esp_lcd_touch_cst816s 等组件依赖 - managed_components 纳入版本管理 ### 配网模式轻量化启动 - BoxAudioCodec: 新增 output_only 模式,仅创建 I2S TX 通道(省 ~13KB DMA) 跳过 ES7210 ADC 初始化(省 ~2-4KB) - AudioCodec: 新增 StartOutputOnly() 方法,仅启用扬声器输出 - Application: 配网模式跳过 Opus 编码器、输入重采样器、协议初始化、 天气位置检测等网络业务 - 板级构造函数: 配网模式跳过电池检测、IMU传感器、PowerSaveTimer ### WifiBoard 配网流程修复 - NeedsProvisioning() 静态方法: 读取 NVS force_ap 和 SSID 列表, 用于提前判断配网模式 - force_ap 竞态修复: 构造函数不再清零 force_ap,改在 StartNetwork() 清零, 确保 NeedsProvisioning() 能正确读到 force_ap=1 - Application 缓存 provisioning_mode_ 成员变量,避免重复读 NVS ### BLE 配网重启修复 - 配网成功后用 esp_timer 延迟重启替代 xTaskCreate, 避免内存紧张时任务创建失败导致设备不重启 - 注释掉 WiFi 连接成功后的 MAC 地址发送步骤 ### sdkconfig 内存优化 - BT_ALLOCATION_FROM_SPIRAM_FIRST=y (BLE 动态分配优先 PSRAM) - SPIRAM_MALLOC_RESERVE_INTERNAL=32768 - NVS_ALLOCATE_CACHE_IN_SPIRAM=y - WiFi 静态缓冲区数量优化 (RX=10, TX=8) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
4.3 KiB
Coding style
File format
Use misc/lv_templ.c and misc/lv_templ.h
Naming conventions
- Words are separated by '_'
- In variable and function names use only lower case letters (e.g. height_tmp)
- In enums and defines use only upper case letters (e.g. e.g. MAX_LINE_NUM)
- Global names (API):
- start with lv
- followed by module name: btn, label, style etc.
- followed by the action (for functions): set, get, refr etc.
- closed with the subject: name, size, state etc.
- Typedefs
- prefer
typedef structandtypedef enuminstead ofstruct nameandenum name - always end
typedef structandtypedef enumtype names with_t
- prefer
- Abbreviations:
- Only words longer or equal than 6 characters can be abbreviated.
- Abbreviate only if it makes the word at least half as long
- Use only very straightforward and well-known abbreviations (e.g. pos: position, def: default, btn: button)
Coding guide
- Functions:
- Try to write function shorter than is 50 lines
- Always shorter than 200 lines (except very straightforwards)
- Variables:
- One line, one declaration (BAD: char x, y;)
- Use
<stdint.h>(uint8_t, int32_t etc) - Declare variables where needed (not all at function start)
- Use the smallest required scope
- Variables in a file (outside functions) are always static
- Do not use global variables (use functions to set/get static variables)
Comments
Before every function have a comment like this:
/**
* Return with the screen of an object
* @param obj pointer to an object
* @return pointer to a screen
*/
lv_obj_t * lv_obj_get_scr(lv_obj_t * obj);
Always use /*Something*/ format and NOT //Something
Write readable code to avoid descriptive comments like:
x++; /*Add 1 to x*/.
The code should show clearly what you are doing.
You should write why have you done this:
x++; /*Because of closing '\0' of the string*/
Short "code summaries" of a few lines are accepted. E.g. /*Calculate the new coordinates*/
In comments use ` ` when referring to a variable. E.g. /*Update the value of `x_act`*/
Formatting
Here is example to show bracket placing and using of white spaces:
/**
* Set a new text for a label. Memory will be allocated to store the text by the label.
* @param label pointer to a label object
* @param text '\0' terminated character string. NULL to refresh with the current text.
*/
void lv_label_set_text(lv_obj_t * label, const char * text)
{ /*Main brackets of functions in new line*/
if(label == NULL) return; /*No bracket only if the command is inline with the if statement*/
lv_obj_inv(label);
lv_label_ext_t * ext = lv_obj_get_ext(label);
/*Comment before a section*/
if(text == ext->txt || text == NULL) { /*Bracket of statements start inline*/
lv_label_refr_text(label);
return;
}
...
}
Use 4 spaces indentation instead of tab.
You can use astyle to format the code. Run code-formatter.sh from the scrips folder.
pre-commit
pre-commit is a multi-language package manager for pre-commit hooks. See the instalation guide to get pre-commit python package installed into your development machine.
Once you have pre-commit installed you will need to set up the git hook scripts with:
pre-commit install
now pre-commit will run automatically on git commit!
Hooks
The format-source local hook (see .pre-commit-config.yaml) runs astyle on all the staged source and header
files (that are not excluded, see exclude key of the hook configuration) before entering the commit message,
if any file gets formatted by astyle you will need to add the change to the staging area and run git commit again.
The trailing-whitespace hook fixes trailing whitespaces on all of the files.
Skipping hooks
If you want to skip any particular hook you can do so with:
SKIP=name-of-the-hook git commit
Testing hooks
It's no necessary to do a commit to test the hooks, you can test hooks by adding the files into the staging area and run:
pre-commit run name-of-the-hook