ch32v307_camera/doc/设计文档/DVP模块设计.md
zhoujie b69717b964 📝 docs(design): 新增系统设计文档集
 feat(system-overview): 创建系统总览文档
- 描述项目背景与硬件平台配置
- 提供 FreeRTOS 任务拓扑表(任务优先级、栈大小、职责)
- 详细说明系统启动序列和初始化依赖关系
- 绘制 2D/1D 状态机完整流程图
- 解释 TEMP_REQ 辅助通道工作机制
- 说明任务间同步机制(Frame_Ready_Flag、双缓冲 TX)

 feat(dvp-module-design): 创建 DVP 模块设计文档
- 提供 DVP 硬件连接引脚映射表
- 描述 DVP 时序配置(信号极性、工作模式)
- 解释 DMA ping-pong 行缓冲机制和切换逻辑
- 说明 DVP IRQ 帧组装流程(STR_FRM/ROW_DONE)
- 定义 FrameBuffer 数据格式和像素访问方式
- 说明 TMP 模式温度换算公式和字节序要求

 feat(qdx-protocol-design): 创建 QDX 协议设计文档
- 描述完整 TLV 帧结构(FrameHeader + TLV + CRC)
- 列出所有 Class/Type 映射表和用途说明
- 解释零拷贝 TX 缓冲区架构(HeadOffset 机制)
- 说明分片机制和最大载荷限制
- 定义 Flags 字段各位含义和使用场景

 feat(tcp-module-design): 创建 TCP 通信模块设计文档
- 描述双流连接架构(控制流 5511 / 数据流 5512)
- 说明握手流程和连接建立时序
- 解释心跳机制和 TCP Keepalive 配置
- 描述配置下发与缓存机制
- 说明数据发送队列和背压处理策略
- 解释 WCHNET 网络栈驱动任务工作机制

 feat(integration-guide): 创建对接集成指南
- 提供网络接入参数表(IP、端口、协议)
- 详细说明握手流程和配置下发格式
- 提供 2D/1D 温度帧解析方法和示例代码
- 说明检测结果上报和 NG 响应机制
- 解释 TEMP_REQ 按需截图工作方式
- 列出错误码表和对接故障排查步骤
2026-03-15 19:17:41 +08:00

199 lines
5.7 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# DVP 模块设计文档
> 文档版本1.0 · 日期2026-03-15 · 状态:已发布
---
## 1. 模块概述
DVPDigital Video Port模块负责将 Mini212G2 传感器输出的 8-bit CMOS 并行数据转换为内存中可访问的帧缓冲FrameBuffer。整个采集链路通过硬件 DMA ping-pong 和快速中断实现CPU 占用极低。
源文件:`Debug/dvp.c` / `Debug/dvp.h`
---
## 2. DVP 硬件连接与引脚映射
所有 DVP 引脚配置为 **浮空输入GPIO_Mode_IN_FLOATING**
| 引脚 | DVP 信号 | 说明 |
|------|----------|------|
| PA4 | D0 | 数据位 0 |
| PA5 | D1 | 数据位 1 |
| PA6 | D2 | 数据位 2 |
| PA9 | D3 | 数据位 3 |
| PA10 | D4 | 数据位 4 |
| PC8 | D5 | 数据位 5 |
| PC9 | D6 | 数据位 6 |
| PC11 | D7 | 数据位 7 |
| PB3 | VSYNC | 帧同步信号 |
| PB8 | HSYNC | 行同步信号 |
| PB9 | PIXCLK | 像素时钟 |
---
## 3. DVP 时序配置
`DVP_Init()` 中完成以下配置:
### 3.1 工作模式
| 配置项 | 值 | 说明 |
|--------|-----|------|
| 数据宽度 | `RB_DVP_D8_MOD` | 8-bit 并行数据 |
| 采集模式 | `Video_Mode` | 连续帧采集(非快照模式) |
| 捕获控制 | 持续捕获CR1 CM=0 | 不限帧数 |
### 3.2 信号极性
| 信号 | 寄存器位 | 配置值 | 说明 |
|------|----------|--------|------|
| VSYNC | `RB_DVP_V_POLAR` | **1高有效** | DIGITAL_FIELD_VALID 高电平期间为有效帧行 |
| HSYNC | `RB_DVP_H_POLAR` | 0高有效| 标准高有效行同步 |
| PCLK | `RB_DVP_P_POLAR` | 0上升沿采样| 正常时钟极性 |
> **与手册对应**Mini212G2 FIELD_VALID 高电平为有效期,因此 V_POLAR 置 1高有效与硬件手册时序图一致。
### 3.3 图像尺寸配置
| 寄存器 | 值 | 说明 |
|--------|-----|------|
| `DVP->COL_NUM` | 512`BYTES_PER_LINE` | 每行字节数 = 256 像素 × 2 字节 |
| `DVP->ROW_NUM` | 1 | 每行触发一次 ROW_DONE 中断 |
---
## 4. DMA ping-pong 行缓冲机制
### 4.1 缓冲区配置
```c
__attribute__((aligned(4))) uint8_t DMA_LineBuf0[512]; /* DMA_BUF0 */
__attribute__((aligned(4))) uint8_t DMA_LineBuf1[512]; /* DMA_BUF1 */
```
两个缓冲区分别挂载在 `DVP->DMA_BUF0``DVP->DMA_BUF1`DVP 硬件在两者之间自动切换,无需 CPU 干预。
### 4.2 缓冲切换逻辑
ROW_DONE 中断触发时,硬件已切换到 **下一个缓冲**开始写入。因此正确读取方法为:
```c
/* BUF_TOG=1 表示 DMA 正在写 BUF0此时应读 BUF1刚写完的那个 */
uint8_t *src = (DVP->CR1 & RB_DVP_BUF_TOG) ? DMA_LineBuf0 : DMA_LineBuf1;
```
即:`BUF_TOG` 状态位指示**当前正在写入的缓冲**,应读取**另一个**刚刚完成写入的缓冲。
### 4.3 尺寸约束
修改传感器分辨率时,必须同时更新以下三个宏(`dvp.h`
```c
#define SENSOR_WIDTH 256 /* 像素列数 */
#define SENSOR_HEIGHT 192 /* 像素行数 */
#define BYTES_PER_LINE 512 /* SENSOR_WIDTH × 2 字节/像素 */
```
---
## 5. DVP IRQ 帧组装逻辑
中断处理函数声明:
```c
void DVP_IRQHandler(void) __attribute__((interrupt("WCH-Interrupt-fast")));
```
`WCH-Interrupt-fast` 属性使中断跳过通用寄存器入栈显著降低中断延迟确保在下一行像素时钟到来Mini212G2 @ 25 Hz每行约 42.67 µs前完成 512 B 的 `memcpy`
### 5.1 帧同步STR_FRM 中断)
VSYNC 上升沿触发,是帧同步的**唯一锚点**
```c
if (DVP->IFR & RB_DVP_IF_STR_FRM) {
DVP->IFR = RB_DVP_IF_STR_FRM;
current_line_idx = 0; /* 重置行计数器 */
dvp_frame_count++;
}
```
### 5.2 行完成ROW_DONE 中断)
每行像素传输完成后触发:
```c
if (DVP->IFR & RB_DVP_IF_ROW_DONE) {
DVP->IFR = RB_DVP_IF_ROW_DONE;
uint8_t *src = (DVP->CR1 & RB_DVP_BUF_TOG) ? DMA_LineBuf0 : DMA_LineBuf1;
uint32_t idx = current_line_idx;
current_line_idx++;
if (idx < SENSOR_HEIGHT) {
memcpy(FrameBuffer[idx], src, BYTES_PER_LINE);
if (idx == SENSOR_HEIGHT - 1) { /* 第 191 行完成 */
Frame_Ready_Flag = 1; /* 通知业务任务 */
Ready_Frame_Count = dvp_frame_count; /* 记录帧号 */
}
}
}
```
> **注意:先读 `idx` 再递增**,避免 off-by-one。STR_FRM 将 `idx` 置 0首次 ROW_DONE 时 `idx=0`,将数据写入 `FrameBuffer[0]`,符合预期。
---
## 6. FrameBuffer 数据格式
```c
__attribute__((aligned(4))) uint8_t FrameBuffer[SENSOR_HEIGHT][BYTES_PER_LINE];
/* = uint8_t[192][512] */
```
### 6.1 像素访问方式
FrameBuffer 声明为 `uint8_t` 数组,实际存储 `uint16_t` 小端序温度值:
```c
/* 访问第 row 行、第 col 列的温度 */
uint16_t *pixels = (uint16_t *)FrameBuffer;
uint16_t raw_val = pixels[row * SENSOR_WIDTH + col];
```
### 6.2 温度换算TMP 模式)
```
温度°C= raw_val × 0.1
```
例:`raw_val = 370``37.0°C`
### 6.3 字节序说明
CH32V307 为**小端序**Little-Endian
| 偏移 | 内容 |
|------|------|
| `FrameBuffer[row][col*2 + 0]` | 温度低字节 |
| `FrameBuffer[row][col*2 + 1]` | 温度高字节 |
传感器必须配置为 **CMOS8(LSB) 模式**(低字节先发),否则字节顺序反转,温度值错误。
### 6.4 内存布局摘要
| 参数 | 值 |
|------|-----|
| 总大小 | 192 × 512 = 98,304 字节 ≈ 96 KB |
| 每行 | 512 字节 = 256 像素 |
| 像素格式 | uint16_t小端0.1°C/LSBTMP 模式绝对温度 |
| 对齐 | 4 字节对齐(`__attribute__((aligned(4)))` |
---
## 7. 相关文档
| 文档 | 内容 |
|------|------|
| [系统总览.md](系统总览.md) | FreeRTOS 任务拓扑、Frame_Ready_Flag 同步机制 |
| [Mini212G2预配置指南.md](../Mini212G2预配置指南.md) | CMOS8(LSB) + TMP 模式配置命令 |