Initial commit: TXW82x FPV v2.7.0.7-42229 SDK + project sources
This commit is contained in:
933
项目笔记.md
Normal file
933
项目笔记.md
Normal file
@@ -0,0 +1,933 @@
|
||||
# TXW82x FPV SDK 项目笔记
|
||||
|
||||
> 版本:v2.7.0.7-42229
|
||||
> 芯片厂商:HugeIC(宏晶)
|
||||
> 记录日期:2026-06-09
|
||||
|
||||
---
|
||||
|
||||
## 一、项目概述
|
||||
|
||||
这是一个 **TXW82x FPV(第一人称视角)嵌入式 Wi-Fi 视频传输 SDK**,主要用于**无人机/航模/婴儿监视器/对讲机**等实时无线视频传输设备的固件开发。
|
||||
|
||||
- **目标芯片**:TXW82x(C-SKY CK804DF 内核,32位 RISC 处理器,192MHz,带硬件浮点和 DSP)
|
||||
- **双核架构**:CPU0 运行 WiFi MAC 层固件(`txw82xcore.bin`),CPU1 运行应用固件,通过邮箱 RPC 通信
|
||||
- **编程语言**:几乎全是 C 语言(1584 个 .c 文件),少量汇编用于启动代码
|
||||
- **支持的 RTOS**:AliOS (Rhino) 和 OpenHarmony LiteOS-M(二选一)
|
||||
|
||||
---
|
||||
|
||||
## 二、目录结构
|
||||
|
||||
| 目录 | 说明 |
|
||||
|------|------|
|
||||
| `project/` | **主工程目录**,包含应用代码、配置、构建脚本、入口文件 |
|
||||
| `sdk/` | **核心 SDK**,包含应用模块、HAL、驱动、库 |
|
||||
| `csky/` | **C-SKY CPU 支持**,包含 RTOS 内核(AliOS Rhino)、DSP/NN 库、minilibc |
|
||||
| `ohos/` | **OpenHarmony LiteOS-M 内核**(可选的第二个 RTOS) |
|
||||
| `libs/` | **预编译静态库**(19 个 .a 文件,WiFi、ISP、Video、Audio 等闭源模块) |
|
||||
| `tools/` | 工具目录(此版本为空) |
|
||||
| `doc/` | 文档目录(此版本为空) |
|
||||
| `no_WPA3/` | 不含 WPA3 的核心固件备选 |
|
||||
|
||||
---
|
||||
|
||||
## 三、系统架构(从上到下)
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────┐
|
||||
│ 用户应用层 (project/app/) │
|
||||
│ FPV │ Demo │ 婴儿监视器 │ 对讲机 等 │
|
||||
├─────────────────────────────────────────┤
|
||||
│ SDK 应用模块 (sdk/app/) │
|
||||
│ RTSP │ Video │ Audio │ UI/LVGL │ MQTT │
|
||||
├─────────────────────────────────────────┤
|
||||
│ SDK 库 (sdk/lib/) │
|
||||
│ 视频│音频│网络│蓝牙│加密│文件系统│多媒体 │
|
||||
├─────────────────────────────────────────┤
|
||||
│ HAL 硬件抽象层 (sdk/hal/) │
|
||||
│ 40 个外设 HAL 模块 │
|
||||
├─────────────────────────────────────────┤
|
||||
│ 驱动层 (sdk/driver/) │
|
||||
│ 16 类外设驱动 │
|
||||
├─────────────────────────────────────────┤
|
||||
│ OSAL 操作系统抽象层 (sdk/osal/) │
|
||||
│ AliOS (Rhino) │ OpenHarmony (LiteOS) │
|
||||
├─────────────────────────────────────────┤
|
||||
│ 芯片启动 (sdk/chip/txw82x/) │
|
||||
│ 向量表 │ 中断 │ 系统初始化 │
|
||||
├─────────────────────────────────────────┤
|
||||
│ 预编译核心库 (libs/*.a) │
|
||||
│ WiFi MAC │ ISP │ Video │ Audio │ Flash │
|
||||
├─────────────────────────────────────────┤
|
||||
│ TXW82x 硬件 (CK804DF 双核) │
|
||||
│ WiFi│H264│JPEG│ISP│LCD│USB│SD│PSRAM │
|
||||
└─────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 四、关键源文件
|
||||
|
||||
### 4.1 入口和配置(最先看)
|
||||
|
||||
| 文件 | 行数 | 说明 |
|
||||
|------|------|------|
|
||||
| `project/project_config.h` | - | 主配置,`CUSTOMER_ID` 选择产品类型 |
|
||||
| `project/sys_config.h` | - | 系统配置(OS选择、内存布局) |
|
||||
| `project/config.cfg` | - | 引脚复用/GPIO 配置 |
|
||||
| `project/main.c` | 286 | **主入口**,初始化看门狗→CPU RPC→堆→配置→事件→WiFi→网络→启动应用 |
|
||||
|
||||
### 4.2 系统初始化
|
||||
|
||||
| 文件 | 行数 | 说明 |
|
||||
|------|------|------|
|
||||
| `project/device.c` | 725 | 所有硬件外设初始化 |
|
||||
| `project/events.c` | 180 | WiFi/网络事件处理 |
|
||||
| `project/wifi.c` | 171 | WiFi 参数设置(ACS、速率控制、发射功率) |
|
||||
| `project/network.c` | - | LwIP 网络栈初始化 |
|
||||
| `project/syscfg.c/h` | - | 系统配置持久化 |
|
||||
|
||||
### 4.3 应用层
|
||||
|
||||
| 文件 | 行数 | 说明 |
|
||||
|------|------|------|
|
||||
| `project/app/app_fpv.c` | 597 | FPV 应用初始化,视频/音频流、RTSP、对讲 |
|
||||
| `project/app/app_demo.c` | - | 通用 Demo |
|
||||
| `project/app/app_tunning.c` | - | ISP 调参 |
|
||||
| `project/app/app_bbm_cam.c` | - | 婴儿监视器-摄像头端 |
|
||||
| `project/app/app_bbm_lcd.c` | - | 婴儿监视器-LCD 端 |
|
||||
| `project/app/app_walkie_talkie.c` | - | 对讲机 |
|
||||
| `project/app/fpv_mem.c` | - | FPV 内存管理 |
|
||||
|
||||
### 4.4 SDK 层
|
||||
|
||||
| 目录 | 说明 |
|
||||
|------|------|
|
||||
| `sdk/app/spook/` | RTSP 服务器(RTP/H264/MJPEG 流媒体) |
|
||||
| `sdk/app/video_app/` | 视频采集、编码 |
|
||||
| `sdk/app/audio_msi/` | 音频 ADC/DAC |
|
||||
| `sdk/app/recorder/` | 视频录制(MP4/AVI) |
|
||||
| `sdk/app/intercom/` | 双向对讲 |
|
||||
| `sdk/app/ui/` | LVGL UI 界面 |
|
||||
| `sdk/app/http/` | HTTP 客户端/服务端 |
|
||||
| `sdk/app/mqtt/` | MQTT 客户端 |
|
||||
| `sdk/app/babyprotocol/` | 婴儿监视器协议 |
|
||||
| `sdk/app/walkie-talkie/` | 对讲机应用 |
|
||||
| `sdk/app/decode/` | JPEG/H264 解码 |
|
||||
| `sdk/app/scale_msi/` | 图像缩放 |
|
||||
| `sdk/app/mp4/` | MP4 容器封装 |
|
||||
|
||||
---
|
||||
|
||||
## 五、支持的产品配置
|
||||
|
||||
通过 `project_config.h` 中的 `CUSTOMER_ID` 切换:
|
||||
|
||||
| ID | 产品 | 说明 |
|
||||
|----|------|------|
|
||||
| 1 | FPV Demo | FPV 实时视频传输 |
|
||||
| 2 | ISP Tunning Demo | ISP 图像调参 |
|
||||
| 3 | 720P Camera | H264 主码流 + H264 子码流 + RTSP + MP4 录制 |
|
||||
| 4 | 1080P Camera | H264 1080P@25fps + MJPG 子码流 + RTSP + MP4 录制 |
|
||||
| 5 | 720P→1080P | 720P 上采样到 1080P |
|
||||
| 6 | UVC Camera | USB 视频类摄像头 |
|
||||
| 7 | Walkie-Talkie | 对讲机 |
|
||||
| 8 | LCD Demo | LCD 显示 |
|
||||
| 9 | Baby Monitor LCD | 婴儿监视器 LCD 端 |
|
||||
| 10 | Baby Monitor Camera | 婴儿监视器摄像头端 |
|
||||
| 11 | LCD MP4 Player | LCD MP4 播放器|
|
||||
|
||||
---
|
||||
|
||||
## 六、构建系统
|
||||
|
||||
### 6.1 开发环境
|
||||
|
||||
- **IDE**:C-SKY Development Kit (CDK) V2.24.19
|
||||
- **工作区文件**:`project/txw82xApp.cdkws`
|
||||
- **工具链**:`csky-elfabiv2-gcc`(C-SKY 架构交叉编译器 V3.10.33)
|
||||
- **编译器标志**:`-mcpu=e804df -mhard-float -melrw -Os -g3 -Wall -ffunction-sections -fdata-sections`
|
||||
|
||||
### 6.2 编译流程
|
||||
|
||||
1. **PreBuild**:`prebuild.sh` 清除旧目标文件 + `precompile.exe` 生成代码
|
||||
2. **Build**:`make -f txw82xApp.mk -j 8`(编译 500+ 源文件 + 链接 19 个预编译库)
|
||||
3. **PostBuild**:`BuildBIN.sh`
|
||||
- 拷贝 `.elf`、`.map`、`.hex` 到工程根目录
|
||||
- `crc.exe` CRC 校验
|
||||
- `BinScript.exe` 合并核心固件 + 应用 hex → `txw82xApp.bin`
|
||||
- `makecode.exe` 生成 SPI Flash 镜像
|
||||
- `merge.bat` 创建带时间戳的最终 `.bin`
|
||||
|
||||
### 6.3 如何构建
|
||||
|
||||
在 CDK IDE 中打开 `project/txw82xApp.cdkws`,点击 Build;或命令行在 `project/` 目录下运行 `make -f cdkws.mk`(需工具链在 PATH 中)。
|
||||
|
||||
---
|
||||
|
||||
## 七、硬件资源
|
||||
|
||||
### 7.1 内存布局
|
||||
|
||||
| 区域 | 起始地址 | 大小 | 用途 |
|
||||
|------|----------|------|------|
|
||||
| ISRAM | 0x04001000 | 168 KB | 核心代码 |
|
||||
| SRAM | 0x20006B44 | 256 KB | 堆/数据 |
|
||||
| SRAM0 | 0x20001100 | ~12 KB | 部分 sleep 用 |
|
||||
| SRAM2 | 0x20068000 | ~14 KB | 最后 256 字节 CoreSetting |
|
||||
| FLASH | 0x10000000 | 2 MB | 固件存储 |
|
||||
| PSRAM | 0x28000000 | 8 MB | 外部 PSRAM |
|
||||
|
||||
### 7.2 片上外设
|
||||
|
||||
- WiFi(802.11 b/g/n,AP + STA 模式,HT MCS0-7)
|
||||
- 蓝牙低功耗(BLE)
|
||||
- MIPI CSI(摄像头接口,支持双摄)
|
||||
- DVP(并口摄像头接口)
|
||||
- H.264 硬件编码器
|
||||
- JPEG 硬件编码/解码器
|
||||
- ISP(图像信号处理器,AE/AWB/gamma/IR-cut)
|
||||
- VPP(视频后处理器)
|
||||
- LCD 控制器(MIPI DSI + MCU 接口)
|
||||
- Audio ADC/DAC、I2S、PDM
|
||||
- USB 2.0 OTG + USB 1.1 Host
|
||||
- SD 卡主机(SDIO)
|
||||
- SPI、I2C、UART、PWM、ADC、DMA、SHA、AES
|
||||
- PSRAM 接口(外部 8MB)
|
||||
|
||||
### 7.3 支持的图像传感器
|
||||
|
||||
GC1084, GC2053, GC2083, GC2145, GC0308, GC0329, OV2640, OV7725, OV9734, SC1346, SC2331, SC2336P, BF3A03, BF30A2, BF2013, BF3703, BF3720, IMX219, H62, H63P, F37P, F38P, TP9950 等
|
||||
|
||||
### 7.4 支持的 LCD 面板
|
||||
|
||||
ST7701S(MIPI), ST7789V, ST7735, ST7796, ILI9881C, JD9852 等
|
||||
|
||||
---
|
||||
|
||||
## 八、网络协议栈
|
||||
|
||||
- **LwIP** TCP/IP 协议栈(DHCP 客户端/服务端、DNS、NAT)
|
||||
- **RTSP/RTP** 服务器(spook),支持 H264/MJPEG 实时流
|
||||
- **HTTP** 客户端/服务端
|
||||
- **MQTT** 客户端
|
||||
- **libcurl**(完整 HTTP 客户端库)
|
||||
- WiFi AP 模式默认 IP:192.168.169.1
|
||||
- 多种 WiFi 速率控制算法(FPV/航拍/IPC/婴儿监视器场景)
|
||||
|
||||
---
|
||||
|
||||
## 九、预编译库说明
|
||||
|
||||
| 库文件 | 说明 |
|
||||
|--------|------|
|
||||
| `libcore.a` | WiFi MAC(LMAC/UMAC)核心 |
|
||||
| `libwifi.a` | WiFi 驱动 |
|
||||
| `libvideo.a` | 视频编码管线 |
|
||||
| `libisp.a` | 图像信号处理 |
|
||||
| `libaudio_app.a` | 音频应用 |
|
||||
| `libaudio_drver.a` | 音频驱动 |
|
||||
| `libflash.a` | Flash 访问 |
|
||||
| `libpsram.a` | PSRAM 驱动 |
|
||||
| `libusb.a` | USB 协议栈 |
|
||||
| `libsd.a` | SD 卡主机 |
|
||||
| `libcommon.a` | 通用工具 |
|
||||
| `libatcmd.a` | AT 命令解析 |
|
||||
|
||||
---
|
||||
|
||||
## 十、学习路径建议
|
||||
|
||||
1. **先读配置**:`project/project_config.h` → `project/sys_config.h` → `project/config.cfg`
|
||||
2. **跟主线**:从 `project/main.c` 的 `main()` 函数开始,按初始化流程往下读
|
||||
3. **读应用**:根据 `CUSTOMER_ID` 找到对应的应用文件(如 FPV 看 `app_fpv.c`)
|
||||
4. **理解 SDK 层**:需要用到具体功能时再看 `sdk/app/` 下的对应模块
|
||||
5. **底层驱动**:需要硬件调试时再看 `sdk/hal/` 和 `sdk/driver/`
|
||||
6. **构建验证**:安装 CDK IDE,打开 `.cdkws` 工作区,尝试编译和烧录
|
||||
|
||||
---
|
||||
|
||||
## 十一、如何添加/修改功能
|
||||
|
||||
### 11.1 项目文件职责速查
|
||||
|
||||
```
|
||||
project/
|
||||
├── project_config.h ← 全局宏配置(功能开关、参数)
|
||||
├── main.c ← 程序入口,系统初始化流程
|
||||
├── events.c ← 系统事件分发(WiFi连接/断开/DHCP等)
|
||||
├── wifi.c ← WiFi初始化和参数配置
|
||||
├── network.c ← 网络初始化
|
||||
├── syscfg.c/h ← 系统参数持久化存储(Flash读写)
|
||||
├── atcmd.c ← AT命令注册表
|
||||
├── device.c ← 所有硬件外设初始化
|
||||
├── app/
|
||||
│ ├── app_fpv.c ← FPV图传应用主逻辑(当前激活:CUSTOMER_ID=11)
|
||||
│ ├── app_demo.c ← 通用Demo
|
||||
│ ├── app_bbm_lcd.c ← 婴儿监视器LCD端
|
||||
│ ├── app_bbm_cam.c ← 婴儿监视器摄像头端
|
||||
│ ├── app_walkie_talkie.c ← 对讲机
|
||||
│ ├── app_tunning.c ← ISP调参
|
||||
│ └── user_app.h ← 应用层对外接口声明
|
||||
├── module_code/ ← 硬件模块用户层代码
|
||||
│ ├── gen422_user.c ← H.264辅码流(gen420)用户层
|
||||
│ ├── h264_user.c ← H.264编码用户层
|
||||
│ ├── jpg_user.c ← JPEG编解码用户层
|
||||
│ └── prc_user.c ← PRC电源/复位用户层
|
||||
├── config.cfg ← 引脚配置脚本
|
||||
└── pin_param.h ← 生成的引脚映射
|
||||
```
|
||||
|
||||
### 11.2 添加新功能模块(6步流程)
|
||||
|
||||
#### 步骤1:在 `project_config.h` 添加宏开关
|
||||
|
||||
在对应 `CUSTOMER_ID` 分支(当前为ID=11)中添加:
|
||||
|
||||
```c
|
||||
#define MY_FEATURE_EN 1 // 我的新功能使能,0=禁用,1=启用
|
||||
```
|
||||
|
||||
#### 步骤2:创建功能代码文件
|
||||
|
||||
在 `project/app/` 下新建 `app_my_feature.c`:
|
||||
|
||||
```c
|
||||
#include "sys_config.h"
|
||||
#include "basic_include.h"
|
||||
|
||||
// 初始化函数,会被 main.c 的 sys_app_init() 调用
|
||||
int sys_app_my_feature_init(void)
|
||||
{
|
||||
// 在此初始化你的功能模块
|
||||
os_printf("my feature init ok\r\n");
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
#### 步骤3:在 `user_app.h` 声明接口
|
||||
|
||||
```c
|
||||
int sys_app_my_feature_init(void);
|
||||
```
|
||||
|
||||
#### 步骤4:在 `main.c` 的 `sys_app_init()` 中注册
|
||||
|
||||
在 `sys_app_init()` 函数内添加:
|
||||
|
||||
```c
|
||||
#ifdef MY_FEATURE_EN
|
||||
sys_app_my_feature_init();
|
||||
#endif
|
||||
```
|
||||
|
||||
#### 步骤5:处理系统事件(如需监听WiFi/网络事件)
|
||||
|
||||
有两种方式,根据复杂度选择:
|
||||
|
||||
**方式A:轻量事件**(直接在 `events.c` 的 `sys_event_hdl()` 中添加):
|
||||
|
||||
```c
|
||||
#if MY_FEATURE_EN
|
||||
my_feature_event_handler(event_id, data, priv);
|
||||
#endif
|
||||
```
|
||||
|
||||
适合:只需响应几个简单事件的场景。
|
||||
|
||||
**方式B:复杂事件**(用 `sys_event_take()` 注册独立处理函数):
|
||||
|
||||
在 `main()` 函数的正常模式分支中添加:
|
||||
|
||||
```c
|
||||
sys_event_take(0xffffffff, my_feature_event_hdl, 0);
|
||||
```
|
||||
|
||||
适合:需要完整事件处理链的复杂模块。注意:每次调用消耗 16 字节 heap。
|
||||
|
||||
**WiFi协议栈回调**(在 `events.c` 的 `sys_wifi_event_cb()` 中添加):
|
||||
|
||||
```c
|
||||
#if MY_FEATURE_EN
|
||||
ret |= my_wifi_event_hdl(ifidx, evt, param1, param2);
|
||||
#endif
|
||||
```
|
||||
|
||||
> **重要**:`sys_wifi_event_cb()` 在WiFi协议栈Task中执行,**禁止耗时操作**(如DHCP、Flash读写、长循环)。
|
||||
> 需要耗时逻辑时,通过 `sys_event_post()` 将事件转发到 `sys_event_hdl()` 处理。
|
||||
|
||||
#### 步骤6:添加AT调试命令(可选)
|
||||
|
||||
在 `atcmd.c` 的 `static_atcmds[]` 表中注册:
|
||||
|
||||
```c
|
||||
#ifdef MY_FEATURE_EN
|
||||
{ "AT+MYCMD", my_atcmd_handler },
|
||||
#endif
|
||||
```
|
||||
|
||||
AT命令处理函数格式:
|
||||
|
||||
```c
|
||||
int32 my_atcmd_handler(const char *cmd, char *argv[], uint32 argc)
|
||||
{
|
||||
// 解析参数、执行操作、返回结果
|
||||
os_printf("my feature cmd received\r\n");
|
||||
return ATCMD_RESULT_DONE;
|
||||
}
|
||||
```
|
||||
|
||||
### 11.3 修改现有功能——按目标定位文件
|
||||
|
||||
| 修改目标 | 修改文件 | 说明 |
|
||||
|---------|---------|------|
|
||||
| 功能开关/使能 | `project_config.h` | 改宏值(0↔1)或添加新宏 |
|
||||
| WiFi功率/速率/信道 | `project_config.h` 的 `WIFI_*` 宏 | 参数配置 |
|
||||
| WiFi初始化逻辑 | `wifi.c` | ACS扫描、速率控制、FEM芯片初始化 |
|
||||
| 网络IP/DHCP配置 | `project_config.h` 的 `NET_*/DHCPD_*` 宏 | IP地址池、子网等 |
|
||||
| 网络初始化流程 | `network.c` + `syscfg.c` | LwIP初始化、DHCP服务端 |
|
||||
| FPV图传逻辑 | `app/app_fpv.c` | 视频/音频流、RTSP、对讲、录像 |
|
||||
| 系统事件处理 | `events.c` | WiFi连接/断开/DHCP/LTE事件分发 |
|
||||
| 程序启动流程 | `main.c` | 初始化顺序、应用入口注册 |
|
||||
| 系统参数持久化 | `syscfg.h`(结构体)+ `syscfg.c`(默认值/保存) | Flash参数读写 |
|
||||
| GPIO引脚配置 | `config.cfg` + `pin_param.h` | 引脚复用映射 |
|
||||
| 调试命令 | `atcmd.c` | AT命令注册表 |
|
||||
| 传感器型号支持 | `project_config.h` 的 `DEV_SENSOR_*` | 传感器选择 |
|
||||
| 内存分配大小 | `CONFIG_PSRAM_AVHEAP_SIZE` / `CONFIG_AVHEAP_SIZE` | PSRAM/SRAM音视频堆大小 |
|
||||
| 编解码参数 | `module_code/` 下的文件 | H264/JPEG用户层配置 |
|
||||
| LCD驱动选择 | `project_config.h` 的 `LCD_*` 宏 | ST7701S/ST7789V等 |
|
||||
|
||||
### 11.4 关键注意事项
|
||||
|
||||
1. **内存规划**:新功能若需大块内存,需调整 `CONFIG_PSRAM_AVHEAP_SIZE`(PSRAM)或 `CONFIG_AVHEAP_SIZE`(SRAM),系统需保留约 20KB 空闲 SRAM 防止 malloc 失败
|
||||
2. **syscfg 兼容性**:修改 `struct sys_config`(`syscfg.h`)时**只能在末尾追加字段**,不能修改已有字段的顺序或类型,否则会导致 Flash 中已存储的参数数据错乱(CRC校验失败后回退到默认值)
|
||||
3. **事件处理线程安全**:
|
||||
- `sys_wifi_event_cb()` → WiFi协议栈Task上下文 → **禁止耗时操作**
|
||||
- `sys_event_hdl()` → 独立系统事件Task上下文 → 可以执行耗时操作(DHCP、Flash读写等)
|
||||
- 耗时逻辑必须用 `sys_event_post()` 从回调转发到事件Task
|
||||
4. **条件编译**:用 `#ifdef MY_FEATURE_EN` 包裹新代码,确保不影响其他 `CUSTOMER_ID` 分支
|
||||
5. **CUSTOMER_ID 切换**:修改 `project_config.h` 顶部的 `CUSTOMER_ID` 值即可切换整个产品配置,每个ID分支独立配置互不影响
|
||||
6. **双核通信**:CPU0 运行WiFi MAC固件(不可修改),CPU1 运行应用固件,通过 `cpu_rpc_init()` 建立邮箱通信,应用层通过 RPC 接口调用CPU0的WiFi功能
|
||||
|
||||
### 11.5 系统事件ID一览
|
||||
|
||||
用于 `sys_event_hdl()` 和 `sys_event_post()` 的事件:
|
||||
|
||||
| 事件宏 | 说明 |
|
||||
|--------|------|
|
||||
| `SYS_EVENT(SYS_EVENT_WIFI, SYSEVT_WIFI_CONNECTTED)` | WiFi连接成功 |
|
||||
| `SYS_EVENT(SYS_EVENT_WIFI, SYSEVT_WIFI_DISCONNECT)` | WiFi断开连接 |
|
||||
| `SYS_EVENT(SYS_EVENT_NETWORK, SYSEVT_LWIP_DHCPC_DONE)` | DHCP客户端获取IP完成 |
|
||||
| `SYS_EVENT(SYS_EVENT_LTE, SYSEVT_LTE_CONNECTED)` | LTE网卡连接 |
|
||||
| `SYS_EVENT(SYS_EVENT_LTE, SYSEVT_LTE_DISCONNECTED)` | LTE网卡断开 |
|
||||
|
||||
WiFi协议栈回调事件(`sys_wifi_event_cb`):
|
||||
|
||||
| 事件宏 | 说明 |
|
||||
|--------|------|
|
||||
| `IEEE80211_EVENT_CONNECTED` | WiFi关联成功 |
|
||||
| `IEEE80211_EVENT_DISCONNECTED` | WiFi断开 |
|
||||
| `IEEE80211_EVENT_CONNECT_FAIL` | WiFi连接失败 |
|
||||
| `IEEE80211_EVENT_RSSI` | RSSI信号强度更新 |
|
||||
| `IEEE80211_EVENT_EVM` | EVM信号质量更新 |
|
||||
| `IEEE80211_EVENT_CHANNEL_CHANGE` | 信道切换 |
|
||||
| `IEEE80211_EVENT_INTERFACE_ENABLE` | WiFi接口使能 |
|
||||
|
||||
### 11.6 常用AT命令速查
|
||||
|
||||
| AT命令 | 说明 |
|
||||
|--------|------|
|
||||
| `AT+RST` | 软件复位 |
|
||||
| `AT+SYSDBG` | 系统调试开关 |
|
||||
| `AT+SYSCFG` | 打印系统配置 |
|
||||
| `AT+HEAP` | 打印堆内存信息 |
|
||||
| `AT+SSID` | 设置WiFi SSID |
|
||||
| `AT+KEY` | 设置WiFi密码 |
|
||||
| `AT+WIFIMODE` | 设置WiFi模式(sta/ap) |
|
||||
| `AT+CHANNEL` | 设置WiFi信道 |
|
||||
| `AT+SCAN` | 扫描WiFi |
|
||||
| `AT+LOADDEF` | 恢复出厂默认配置 |
|
||||
| `AT+FPV_HEAP` | 打印FPV内存状态 |
|
||||
| `AT+PING` | Ping测试 |
|
||||
| `AT+IPERF2` | 网络带宽测试 |
|
||||
|
||||
串口参数:UART0,921600 波特率(见 `atcmd.c` 的 `sys_atcmd_init()`)。
|
||||
|
||||
---
|
||||
|
||||
## 十二、LCD UI 自由修改完全指南
|
||||
|
||||
本项目使用 **LVGL v8** 图形库,所有UI代码都用C语言编写。
|
||||
|
||||
### 12.1 UI代码在哪里
|
||||
|
||||
```
|
||||
sdk/app/ui/
|
||||
├── main_ui.c ← UI入口,选择显示哪种UI风格
|
||||
├── main_ui.h ← 入口函数声明
|
||||
├── lvgl_ui.h ← 所有UI页面函数声明
|
||||
├── preview_ui.c ← 摄像头预览页面(参考这个学习)
|
||||
├── mp4_player_ui.c ← MP4播放页面
|
||||
├── mp4_recorder_ui.c ← MP4录像页面
|
||||
├── photo_ui.c ← 拍照页面
|
||||
└── takephoto_ui.c ← 拍照页面(拇指相机版)
|
||||
|
||||
sdk/app/interface_management/
|
||||
└── interface_mgnt_msi.c ← LVGL初始化入口(第122-153行)
|
||||
|
||||
sdk/app/app_lcd/
|
||||
├── app_lcd.h ← LCD显示接口
|
||||
├── lvgl_osd_msi.c ← LVGL与LCD显示桥接
|
||||
└── lcd_video_msi.c ← 视频流显示到LCD
|
||||
```
|
||||
|
||||
### 12.2 UI启动调用链
|
||||
|
||||
```
|
||||
app_fpv.c: hardware_init()
|
||||
↓
|
||||
interface_mgnt_msi.c: lvgl_init_msi(w, h, rotate)
|
||||
↓ (第122行)
|
||||
lv_init() // LVGL库初始化
|
||||
lv_port_disp_init_msi() // 显示屏初始化
|
||||
lv_style_init(&g_style) // 全局黑色背景样式
|
||||
↓
|
||||
main_ui(NULL) // ← UI从这里开始(第148行)
|
||||
↓
|
||||
创建GUI线程,开始刷新屏幕
|
||||
```
|
||||
|
||||
**`main_ui()` 函数**(`sdk/app/ui/main_ui.c` 第68行)是所有UI的入口:
|
||||
|
||||
```c
|
||||
lv_obj_t *main_ui(lv_obj_t *base_ui)
|
||||
{
|
||||
lv_group_t *group = lv_group_create();
|
||||
lv_indev_set_group(indev_keypad, group);
|
||||
lv_obj_t *ui = lv_list_create(lv_scr_act());
|
||||
lv_obj_set_size(ui, LV_PCT(100), LV_PCT(100));
|
||||
|
||||
switch(DEFINE_UI) { // 根据 DEFINE_UI 宏选择UI
|
||||
case MINI_DV_UI: main_Mini_DV_ui(ui, group); break;
|
||||
case POCKET_CAMERA_UI: main_pocket_camera_ui(ui, group); break;
|
||||
case BBM_UI: lv_obj_add_style(ui, &g_style, 0); break;
|
||||
// 在这里添加自己的UI case
|
||||
}
|
||||
return ui;
|
||||
}
|
||||
```
|
||||
|
||||
### 12.3 添加自定义UI的步骤
|
||||
|
||||
#### 步骤1:在 `main_ui.c` 的枚举中添加UI类型
|
||||
|
||||
```c
|
||||
enum UI_MODE
|
||||
{
|
||||
MINI_DV_UI,
|
||||
IPC_UI,
|
||||
BBM_UI,
|
||||
CHILDREN_UI,
|
||||
POCKET_CAMERA_UI,
|
||||
LLM_VISION_UI,
|
||||
MY_SMART_CAMERA_UI, // ← 新增
|
||||
};
|
||||
```
|
||||
|
||||
#### 步骤2:在 `lvgl_ui.h` 中声明函数
|
||||
|
||||
```c
|
||||
lv_obj_t *my_home_ui(lv_group_t *group, lv_obj_t *base_ui);
|
||||
```
|
||||
|
||||
#### 步骤3:在 `main_ui.c` 的 switch 中添加 case
|
||||
|
||||
```c
|
||||
case MY_SMART_CAMERA_UI:
|
||||
my_home_ui(ui, group);
|
||||
break;
|
||||
```
|
||||
|
||||
#### 步骤4:在 `project_config.h` 对应 CUSTOMER_ID 分支中选择UI
|
||||
|
||||
```c
|
||||
#define DEFINE_UI MY_SMART_CAMERA_UI
|
||||
```
|
||||
|
||||
#### 步骤5:新建 `sdk/app/ui/my_home_ui.c` 编写UI代码
|
||||
|
||||
### 12.4 LVGL v8 核心控件速查
|
||||
|
||||
#### 基本概念
|
||||
|
||||
```c
|
||||
lv_obj_t // 所有UI控件的类型(按钮、标签、容器等)
|
||||
lv_group_t // 按键组,物理按键通过组来切换焦点
|
||||
lv_style_t // 样式(颜色、字体、边距等)
|
||||
lv_scr_act() // 获取当前屏幕对象
|
||||
```
|
||||
|
||||
#### 容器(用于布局)
|
||||
|
||||
```c
|
||||
lv_obj_t *container = lv_obj_create(lv_scr_act());
|
||||
lv_obj_set_size(container, 320, 240); // 像素
|
||||
lv_obj_set_size(container, LV_PCT(100), LV_PCT(50)); // 百分比
|
||||
lv_obj_set_pos(container, 0, 0); // x, y 像素
|
||||
lv_obj_align(container, LV_ALIGN_CENTER, 0, 0); // 居中
|
||||
lv_obj_align(container, LV_ALIGN_TOP_MID, 0, 10); // 顶部居中偏移10px
|
||||
lv_obj_add_flag(container, LV_OBJ_FLAG_HIDDEN); // 隐藏
|
||||
lv_obj_clear_flag(container, LV_OBJ_FLAG_HIDDEN); // 显示
|
||||
```
|
||||
|
||||
#### 文字标签
|
||||
|
||||
```c
|
||||
lv_obj_t *label = lv_label_create(parent_obj);
|
||||
lv_label_set_text(label, "Hello World");
|
||||
lv_label_set_text_fmt(label, "WiFi: %s", ssid);
|
||||
lv_obj_set_style_text_color(label, lv_color_white(), 0);
|
||||
lv_obj_set_style_text_font(label, &lv_font_montserrat_16, 0);
|
||||
```
|
||||
|
||||
#### 按钮
|
||||
|
||||
```c
|
||||
lv_obj_t *btn = lv_btn_create(parent_obj);
|
||||
lv_obj_set_size(btn, 80, 40);
|
||||
lv_obj_t *btn_label = lv_label_create(btn);
|
||||
lv_label_set_text(btn_label, "Click Me");
|
||||
lv_obj_add_event_cb(btn, my_btn_callback, LV_EVENT_PRESSED, my_data);
|
||||
lv_group_add_obj(group, btn); // 加入按键组(物理按键可选它)
|
||||
```
|
||||
|
||||
#### 列表按钮(本项目大量使用)
|
||||
|
||||
```c
|
||||
lv_obj_t *btn = lv_list_add_btn(list_obj, NULL, "预览"); // 一步创建
|
||||
lv_group_add_obj(group, btn);
|
||||
```
|
||||
|
||||
### 12.5 UI页面编写模板(核心套路)
|
||||
|
||||
参考 `preview_ui.c`,每个UI页面都遵循这个模式:
|
||||
|
||||
```c
|
||||
// 1. 定义页面状态结构体(保存控件引用)
|
||||
struct my_page_s {
|
||||
lv_group_t *last_group; // 上一个按键组(用于返回时恢复)
|
||||
lv_obj_t *base_ui; // 主界面容器
|
||||
lv_obj_t *now_ui; // 当前页面容器(退出时删除)
|
||||
lv_group_t *now_group; // 当前页面按键组
|
||||
lv_obj_t *label_status; // 页面内控件
|
||||
};
|
||||
|
||||
// 2. 退出页面的回调
|
||||
static void exit_my_page(lv_event_t *e)
|
||||
{
|
||||
struct my_page_s *s = lv_event_get_user_data(e);
|
||||
lv_indev_set_group(indev_keypad, s->last_group); // 恢复按键组
|
||||
lv_obj_clear_flag(s->base_ui, LV_OBJ_FLAG_HIDDEN); // 显示主界面
|
||||
if (s->now_group) lv_group_del(s->now_group);
|
||||
if (s->now_ui) lv_obj_del(s->now_ui);
|
||||
lv_free(s);
|
||||
}
|
||||
|
||||
// 3. 进入页面的回调
|
||||
static void enter_my_page(lv_event_t *e)
|
||||
{
|
||||
struct my_page_s *s = lv_event_get_user_data(e);
|
||||
lv_obj_add_flag(s->base_ui, LV_OBJ_FLAG_HIDDEN); // 隐藏主界面
|
||||
|
||||
lv_obj_t *page = lv_obj_create(lv_scr_act());
|
||||
s->now_ui = page;
|
||||
lv_obj_add_style(page, &g_style, 0);
|
||||
lv_obj_set_size(page, LV_PCT(100), LV_PCT(100));
|
||||
|
||||
// 在这里添加UI控件...
|
||||
|
||||
lv_group_t *group = lv_group_create();
|
||||
lv_indev_set_group(indev_keypad, group);
|
||||
// lv_group_add_obj(group, btn); // 把按钮加入按键组
|
||||
s->now_group = group;
|
||||
}
|
||||
|
||||
// 4. 对外接口(在主界面列表中创建入口按钮)
|
||||
lv_obj_t *my_page_ui(lv_group_t *group, lv_obj_t *base_ui)
|
||||
{
|
||||
struct my_page_s *s = lv_malloc(sizeof(struct my_page_s));
|
||||
s->last_group = group;
|
||||
s->base_ui = base_ui;
|
||||
|
||||
lv_obj_t *btn = lv_list_add_btn(base_ui, NULL, "我的页面");
|
||||
lv_group_add_obj(group, btn);
|
||||
lv_obj_add_event_cb(btn, enter_my_page, LV_EVENT_PRESSED, s);
|
||||
return btn;
|
||||
}
|
||||
```
|
||||
|
||||
### 12.6 视频流绑定到LCD
|
||||
|
||||
摄像头画面不是LVGL控件画的,而是通过 **MSI流** 直接写到LCD的Video层:
|
||||
|
||||
```c
|
||||
// 开启摄像头 → LCD显示
|
||||
struct msi *s = scale3_normal_msi2(S_PREVIEW_SCALE3, FSTYPE_YUV_P0, w, h);
|
||||
msi_do_cmd(s, MSI_CMD_SCALE3_NORMAL, MSI_SCALE3_START, 1);
|
||||
msi_add_output(s, NULL, R_VIDEO_P0);
|
||||
msi_add_output(s, NULL, R_VIDEO_P1);
|
||||
msi_cmd(R_VIDEO_P0, MSI_CMD_LCD_VIDEO, MSI_VIDEO_ENABLE, 1);
|
||||
msi_cmd(R_VIDEO_P1, MSI_CMD_LCD_VIDEO, MSI_VIDEO_ENABLE, 1);
|
||||
s->enable = 1;
|
||||
|
||||
// 关闭视频显示(退出预览时)
|
||||
msi_cmd(R_VIDEO_P0, MSI_CMD_LCD_VIDEO, MSI_VIDEO_ENABLE, 0);
|
||||
msi_cmd(R_VIDEO_P1, MSI_CMD_LCD_VIDEO, MSI_VIDEO_ENABLE, 0);
|
||||
msi_del_output(s, NULL, R_VIDEO_P0);
|
||||
msi_del_output(s, NULL, R_VIDEO_P1);
|
||||
s->enable = 0;
|
||||
msi_do_cmd(s, MSI_CMD_SCALE3_NORMAL, MSI_SCALE3_START, 0);
|
||||
msi_destroy(s);
|
||||
```
|
||||
|
||||
**LCD显示分两层**:
|
||||
- **OSD层**:LVGL绘制的UI(按钮、文字)—— 在上层
|
||||
- **Video层**:摄像头实时视频 —— 在下层
|
||||
|
||||
两层叠加,所以可以在视频画面上叠加半透明UI按钮。
|
||||
|
||||
### 12.7 布局技巧
|
||||
|
||||
#### Flex弹性布局(推荐)
|
||||
|
||||
```c
|
||||
lv_obj_t *row = lv_obj_create(parent);
|
||||
lv_obj_set_size(row, LV_PCT(100), 60);
|
||||
lv_obj_set_flex_flow(row, LV_FLEX_FLOW_ROW); // 横向排列
|
||||
lv_obj_set_flex_align(row, LV_FLEX_ALIGN_CENTER,
|
||||
LV_FLEX_ALIGN_CENTER,
|
||||
LV_FLEX_ALIGN_CENTER);
|
||||
lv_obj_set_style_pad_column(row, 10, 0); // 子元素间距10px
|
||||
```
|
||||
|
||||
#### 绝对定位
|
||||
|
||||
```c
|
||||
lv_obj_set_size(obj, 320, 30); // 宽320 高30
|
||||
lv_obj_set_pos(obj, 0, 0); // 左上角
|
||||
```
|
||||
|
||||
### 12.8 颜色和样式
|
||||
|
||||
```c
|
||||
lv_obj_set_style_bg_color(obj, lv_color_make(0xFF, 0x00, 0x00), 0); // 红色背景
|
||||
lv_obj_set_style_bg_opa(obj, LV_OPA_50, 0); // 50%透明度(半透明叠加视频)
|
||||
lv_obj_set_style_text_color(label, lv_color_white(), 0); // 白色文字
|
||||
lv_obj_set_style_border_width(obj, 0, 0); // 去掉边框
|
||||
lv_obj_set_style_radius(obj, 0, 0); // 去掉圆角
|
||||
lv_obj_set_style_pad_all(obj, 5, 0); // 四边内边距5px
|
||||
```
|
||||
|
||||
### 12.9 按键事件处理
|
||||
|
||||
本项目用物理按键,LVGL通过 `lv_group_t` 管理焦点:
|
||||
|
||||
```c
|
||||
// 物理按键上下 → group自动切换焦点
|
||||
// 短按 → LV_EVENT_PRESSED(确认)
|
||||
// 长按 → LV_EVENT_LONG_PRESSED(长按)
|
||||
|
||||
lv_obj_add_event_cb(obj, callback, LV_EVENT_PRESSED, user_data);
|
||||
|
||||
static void my_callback(lv_event_t *e) {
|
||||
void *my_data = lv_event_get_user_data(e); // 用户数据
|
||||
lv_obj_t *target = lv_event_get_target(e); // 触发事件的控件
|
||||
}
|
||||
```
|
||||
|
||||
### 12.10 定时刷新UI(实时时间/状态)
|
||||
|
||||
```c
|
||||
// 创建(页面进入时)
|
||||
lv_timer_t *timer = lv_timer_create(timer_cb, 1000, my_data); // 每1000ms
|
||||
|
||||
static void timer_cb(lv_timer_t *t) {
|
||||
struct my_page_s *s = t->user_data;
|
||||
lv_label_set_text_fmt(s->label_time, "Time: %d", os_get_tick_count());
|
||||
}
|
||||
|
||||
// 删除(退出页面时)
|
||||
lv_timer_del(s->timer);
|
||||
```
|
||||
|
||||
### 12.11 完整示例:自定义"预览+按钮列表"UI
|
||||
|
||||
```c
|
||||
// sdk/app/ui/my_home_ui.c
|
||||
#include "lvgl/lvgl.h"
|
||||
#include "lvgl_ui.h"
|
||||
#include "basic_include.h"
|
||||
#include "lib/multimedia/msi.h"
|
||||
#include "scale3_normal_msi.h"
|
||||
|
||||
extern lv_indev_t *indev_keypad;
|
||||
extern lv_style_t g_style;
|
||||
|
||||
struct my_home_s {
|
||||
lv_group_t *last_group;
|
||||
lv_obj_t *base_ui;
|
||||
lv_obj_t *now_ui;
|
||||
lv_group_t *now_group;
|
||||
lv_obj_t *label_status;
|
||||
lv_timer_t *timer;
|
||||
struct msi *video_msi;
|
||||
uint16_t w, h;
|
||||
};
|
||||
|
||||
static void exit_home(lv_event_t *e)
|
||||
{
|
||||
struct my_home_s *s = lv_event_get_user_data(e);
|
||||
if (s->video_msi) {
|
||||
msi_cmd(R_VIDEO_P0, MSI_CMD_LCD_VIDEO, MSI_VIDEO_ENABLE, 0);
|
||||
msi_del_output(s->video_msi, NULL, R_VIDEO_P0);
|
||||
s->video_msi->enable = 0;
|
||||
msi_do_cmd(s->video_msi, MSI_CMD_SCALE3_NORMAL, MSI_SCALE3_START, 0);
|
||||
msi_destroy(s->video_msi);
|
||||
}
|
||||
if (s->timer) lv_timer_del(s->timer);
|
||||
lv_indev_set_group(indev_keypad, s->last_group);
|
||||
lv_obj_clear_flag(s->base_ui, LV_OBJ_FLAG_HIDDEN);
|
||||
if (s->now_group) lv_group_del(s->now_group);
|
||||
if (s->now_ui) lv_obj_del(s->now_ui);
|
||||
lv_free(s);
|
||||
}
|
||||
|
||||
static void home_timer_cb(lv_timer_t *t)
|
||||
{
|
||||
struct my_home_s *s = t->user_data;
|
||||
lv_label_set_text_fmt(s->label_status, "WiFi:%s | RTSP://554",
|
||||
sys_status.wifi_connected ? "OK" : "--");
|
||||
}
|
||||
|
||||
static void enter_home(lv_event_t *e)
|
||||
{
|
||||
struct my_home_s *s = lv_event_get_user_data(e);
|
||||
lv_obj_add_flag(s->base_ui, LV_OBJ_FLAG_HIDDEN);
|
||||
|
||||
lv_obj_t *page = lv_obj_create(lv_scr_act());
|
||||
s->now_ui = page;
|
||||
lv_obj_add_style(page, &g_style, 0);
|
||||
lv_obj_set_size(page, LV_PCT(100), LV_PCT(100));
|
||||
|
||||
// 顶部状态栏
|
||||
lv_obj_t *top = lv_obj_create(page);
|
||||
lv_obj_set_size(top, LV_PCT(100), 30);
|
||||
lv_obj_set_pos(top, 0, 0);
|
||||
lv_obj_set_style_bg_opa(top, LV_OPA_70, 0);
|
||||
s->label_status = lv_label_create(top);
|
||||
lv_label_set_text(s->label_status, "WiFi:-- | RTSP://554");
|
||||
lv_obj_set_style_text_color(s->label_status, lv_color_white(), 0);
|
||||
|
||||
// 启动视频流到LCD
|
||||
s->video_msi = scale3_normal_msi2(S_PREVIEW_SCALE3, FSTYPE_YUV_P0, s->w, s->h);
|
||||
if (s->video_msi) {
|
||||
msi_do_cmd(s->video_msi, MSI_CMD_SCALE3_NORMAL, MSI_SCALE3_START, 1);
|
||||
msi_add_output(s->video_msi, NULL, R_VIDEO_P0);
|
||||
msi_cmd(R_VIDEO_P0, MSI_CMD_LCD_VIDEO, MSI_VIDEO_ENABLE, 1);
|
||||
s->video_msi->enable = 1;
|
||||
}
|
||||
|
||||
// 底部按钮栏
|
||||
lv_obj_t *bottom = lv_obj_create(page);
|
||||
lv_obj_set_size(bottom, LV_PCT(100), 50);
|
||||
lv_obj_align(bottom, LV_ALIGN_BOTTOM_MID, 0, 0);
|
||||
lv_obj_set_flex_flow(bottom, LV_FLEX_FLOW_ROW);
|
||||
lv_obj_set_flex_align(bottom, LV_FLEX_ALIGN_SPACE_EVENLY,
|
||||
LV_FLEX_ALIGN_CENTER,
|
||||
LV_FLEX_ALIGN_CENTER);
|
||||
|
||||
lv_obj_t *btn_back = lv_btn_create(bottom);
|
||||
lv_label_create(btn_back)->lv_label_set_text("返回");
|
||||
lv_obj_add_event_cb(btn_back, exit_home, LV_EVENT_PRESSED, s);
|
||||
|
||||
lv_obj_t *btn_rec = lv_btn_create(bottom);
|
||||
lv_label_create(btn_rec)->lv_label_set_text("录像");
|
||||
|
||||
lv_obj_t *btn_photo = lv_btn_create(bottom);
|
||||
lv_label_create(btn_photo)->lv_label_set_text("拍照");
|
||||
|
||||
lv_group_t *group = lv_group_create();
|
||||
lv_indev_set_group(indev_keypad, group);
|
||||
lv_group_add_obj(group, btn_back);
|
||||
lv_group_add_obj(group, btn_rec);
|
||||
lv_group_add_obj(group, btn_photo);
|
||||
s->now_group = group;
|
||||
s->timer = lv_timer_create(home_timer_cb, 1000, s);
|
||||
}
|
||||
|
||||
lv_obj_t *my_home_ui(lv_group_t *group, lv_obj_t *base_ui)
|
||||
{
|
||||
struct my_home_s *s = lv_malloc(sizeof(struct my_home_s));
|
||||
s->last_group = group;
|
||||
s->base_ui = base_ui;
|
||||
s->video_msi = NULL;
|
||||
s->timer = NULL;
|
||||
s->w = 320;
|
||||
s->h = 240;
|
||||
|
||||
lv_obj_t *btn = lv_list_add_btn(base_ui, NULL, "Smart Camera");
|
||||
lv_group_add_obj(group, btn);
|
||||
lv_obj_add_event_cb(btn, enter_home, LV_EVENT_PRESSED, s);
|
||||
return btn;
|
||||
}
|
||||
```
|
||||
|
||||
### 12.12 远程WiFi看摄像头(STA模式配网)
|
||||
|
||||
SDK已内置RTSP服务器(`sdk/app/spook/`),`app_fpv.c` 中的 `spook_init()` 自动启动。
|
||||
|
||||
**RTSP流地址**:
|
||||
|
||||
| 地址 | 编码 | 说明 |
|
||||
|------|------|------|
|
||||
| `rtsp://设备IP:554/h264` | H.264 | 视频流(带宽小画质好,推荐) |
|
||||
| `rtsp://设备IP:554/webcam` | MJPEG | 视频流(兼容性好) |
|
||||
| `rtsp://设备IP:554/custom` | MJPEG | 自定义MJPEG流 |
|
||||
|
||||
**AT命令配网步骤**(串口921600波特率):
|
||||
|
||||
```
|
||||
AT+SSID=你家WiFi名称 ← 设置WiFi名称
|
||||
AT+KEY=你家WiFi密码 ← 设置WiFi密码
|
||||
AT+WIFIMODE=sta ← 切换为STA模式(连接路由器)
|
||||
AT+SAVE ← 保存配置到Flash
|
||||
AT+RST ← 重启生效
|
||||
```
|
||||
|
||||
重启后设备自动连接路由器,串口会打印获取到的IP地址。手机装VLC播放器,同一WiFi下打开 `rtsp://设备IP:554/h264` 即可看到画面。
|
||||
|
||||
### 12.13 调试技巧
|
||||
|
||||
| 技巧 | 方法 |
|
||||
|------|------|
|
||||
| 查看UI效果 | 改代码后编译烧录,屏幕直接看 |
|
||||
| 调整预览分辨率 | `scale3_normal_msi2()` 的第3、4个参数 |
|
||||
| LCD屏幕分辨率 | `project/config.cfg` 中配置 |
|
||||
| 按键焦点高亮 | LVGL默认在焦点控件周围显示高亮边框 |
|
||||
| RTSP视频流 | 手机VLC → 打开网络流 → `rtsp://设备IP:554/h264` |
|
||||
| CPU占用 | 串口发 `AT+SYSDBG=top,1` |
|
||||
| 恢复默认 | 串口发 `AT+LOADDEF` |
|
||||
|
||||
### 12.14 UI修改文件速查
|
||||
|
||||
| 要改什么 | 改哪个文件 |
|
||||
|---------|-----------|
|
||||
| 添加新UI页面 | 新建 `sdk/app/ui/xxx_ui.c` |
|
||||
| 声明新UI函数 | `sdk/app/ui/lvgl_ui.h` |
|
||||
| 注册UI入口 | `sdk/app/ui/main_ui.c`(枚举+switch) |
|
||||
| 选择UI风格 | `project/project_config.h`(`DEFINE_UI` 宏) |
|
||||
| 修改全局样式 | `sdk/app/interface_management/interface_mgnt_msi.c` 第134-140行 |
|
||||
| LVGL字体/配置 | `sdk/lib/lvgl/lv_conf.h` |
|
||||
| LCD分辨率/旋转 | `project/config.cfg` + `pin_param.h` |
|
||||
| 视频流分辨率 | UI代码中 `scale3_normal_msi2()` 的参数 |
|
||||
Reference in New Issue
Block a user