1. 项目概述
这个基于STM32H723和OV2640的摄像头图像采集系统,是我最近完成的一个嵌入式视觉项目。它能够实时采集OV2640摄像头拍摄的图像数据,通过DCMI接口传输到STM32H723微控制器,然后通过FSMC接口输出到LCD显示屏上显示。整套系统实现了从图像采集到显示的完整链路,可以作为一个基础的嵌入式视觉开发平台。
在实际项目中,我发现STM32H723这款Cortex-M7内核的MCU性能足够强大,能够流畅处理OV2640输出的QVGA(320x240)甚至更高分辨率的图像数据。而OV2640作为一款性价比极高的200万像素摄像头模组,通过SCCB(兼容I2C)接口配置后,可以直接输出JPEG或RGB格式的图像数据,非常适合嵌入式应用。
2. 硬件设计与选型
2.1 主控芯片STM32H723
选择STM32H723作为主控主要基于以下几点考虑:
- 550MHz主频的Cortex-M7内核,带有双精度浮点单元,处理图像数据游刃有余
- 丰富的存储资源:1MB Flash、564KB SRAM,可以缓存多帧图像数据
- 内置DCMI(数字摄像头接口),直接支持OV2640等并行输出摄像头
- 带有硬件JPEG编解码器,如果使用JPEG模式可以减轻CPU负担
- 提供FSMC接口,可以方便地驱动LCD屏
2.2 OV2640摄像头模组
OV2640是一款200万像素的CMOS图像传感器,主要特性包括:
- 输出分辨率最高支持1600x1200
- 支持输出RGB565、RGB888、JPEG等多种格式
- 内置图像处理功能(自动曝光、白平衡等)
- 通过SCCB接口(兼容I2C)进行配置
- 并行数据输出接口,最高支持15fps@UXGA
在实际使用中,我选择了QVGA(320x240)分辨率RGB565格式输出,这样既能保证显示流畅度,又不会给STM32带来太大处理压力。
2.3 LCD显示屏选择
系统选用了一款3.2寸的TFT LCD,主要参数如下:
- 分辨率:320x240 (与摄像头输出匹配)
- 接口:16位8080并行接口
- 驱动IC:ILI9341
- 通过FSMC接口与STM32连接
选择这款屏幕主要是因为其分辨率与摄像头输出匹配,且FSMC接口可以高效地进行数据传输。
3. 硬件连接设计
3.1 DCMI接口连接
OV2640与STM32H723通过DCMI接口连接:
- DCMI_D0-D7: 连接OV2640的D0-D7数据线
- DCMI_PIXCLK: 连接OV2640的PCLK
- DCMI_HSYNC: 连接OV2640的HREF
- DCMI_VSYNC: 连接OV2640的VSYNC
3.2 SCCB控制接口
OV2640的配置通过SCCB接口完成,使用STM32的I2C1:
- SCL: PB6
- SDA: PB7
3.3 LCD接口连接
LCD通过FSMC接口连接:
- FSMC_D0-D15: 连接LCD的16位数据线
- FSMC_A16: 连接LCD的RS(寄存器选择)引脚
- FSMC_NE1: 作为LCD的片选信号
- FSMC_NOE: 读使能
- FSMC_NWE: 写使能
4. 软件设计与实现
4.1 系统初始化流程
系统上电后的初始化流程如下:
- 初始化系统时钟,配置STM32H723运行在550MHz
- 初始化DCMI接口
- 初始化I2C接口用于SCCB通信
- 配置OV2640摄像头参数
- 初始化FSMC接口用于LCD驱动
- 初始化LCD显示屏
- 开启DCMI DMA传输
4.2 OV2640配置
OV2640的配置通过SCCB接口完成,主要配置步骤包括:
- 复位OV2640
- 设置输出格式为RGB565
- 设置分辨率为QVGA(320x240)
- 配置图像处理参数(亮度、对比度等)
- 开启自动曝光和自动白平衡
以下是部分关键寄存器配置代码示例:
c复制// 设置输出格式为RGB565
SCCB_WriteReg(0xDA, 0x00); // DSP input format
SCCB_WriteReg(0xD3, 0x7F); // DSP output format
SCCB_WriteReg(0xFF, 0x01); // DSP register bank
SCCB_WriteReg(0x15, 0x00); // DSP output format control
SCCB_WriteReg(0xC0, 0xC8); // RGB565 format
// 设置QVGA分辨率
SCCB_WriteReg(0xFF, 0x00); // Sensor register bank
SCCB_WriteReg(0x12, 0x40); // COM7 - QVGA
SCCB_WriteReg(0x11, 0x80); // CLKRC - 内部时钟分频
SCCB_WriteReg(0x0C, 0x00); // COM3 - 默认
SCCB_WriteReg(0x3E, 0x00); // COM14 - 默认
4.3 DCMI与DMA配置
DCMI接口配置为接收RGB565格式数据,使用DMA将数据直接传输到内存缓冲区:
c复制// DCMI配置
DCMI_HandleTypeDef hdcmi;
hdcmi.Instance = DCMI;
hdcmi.Init.SynchroMode = DCMI_SYNCHRO_HARDWARE;
hdcmi.Init.PCKPolarity = DCMI_PCKPOLARITY_RISING;
hdcmi.Init.VSPolarity = DCMI_VSPOLARITY_HIGH;
hdcmi.Init.HSPolarity = DCMI_HSPOLARITY_HIGH;
hdcmi.Init.CaptureRate = DCMI_CR_ALL_FRAME;
hdcmi.Init.ExtendedDataMode = DCMI_EXTEND_DATA_8B;
HAL_DCMI_Init(&hdcmi);
// DMA配置
DMA_HandleTypeDef hdma_dcmi;
hdma_dcmi.Instance = DMA2_Stream1;
hdma_dcmi.Init.Channel = DMA_CHANNEL_1;
hdma_dcmi.Init.Direction = DMA_PERIPH_TO_MEMORY;
hdma_dcmi.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_dcmi.Init.MemInc = DMA_MINC_ENABLE;
hdma_dcmi.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;
hdma_dcmi.Init.MemDataAlignment = DMA_MDATAALIGN_WORD;
hdma_dcmi.Init.Mode = DMA_CIRCULAR;
hdma_dcmi.Init.Priority = DMA_PRIORITY_HIGH;
hdma_dcmi.Init.FIFOMode = DMA_FIFOMODE_ENABLE;
hdma_dcmi.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL;
hdma_dcmi.Init.MemBurst = DMA_MBURST_SINGLE;
hdma_dcmi.Init.PeriphBurst = DMA_PBURST_SINGLE;
HAL_DMA_Init(&hdma_dcmi);
__HAL_LINKDMA(&hdcmi, DMA_Handle, hdma_dcmi);
4.4 LCD驱动实现
LCD驱动通过FSMC接口实现,主要操作包括:
- 初始化FSMC接口
- 发送初始化命令序列
- 实现画点、画线等基本绘图函数
- 实现图像显示函数
以下是FSMC初始化代码示例:
c复制SRAM_HandleTypeDef hsram1;
FSMC_NORSRAM_TimingTypeDef Timing;
// FSMC时序配置
Timing.AddressSetupTime = 1;
Timing.AddressHoldTime = 0;
Timing.DataSetupTime = 2;
Timing.BusTurnAroundDuration = 0;
Timing.CLKDivision = 0;
Timing.DataLatency = 0;
Timing.AccessMode = FSMC_ACCESS_MODE_A;
hsram1.Instance = FSMC_NORSRAM_DEVICE;
hsram1.Extended = FSMC_NORSRAM_EXTENDED_DEVICE;
hsram1.Init.NSBank = FSMC_NORSRAM_BANK1;
hsram1.Init.DataAddressMux = FSMC_DATA_ADDRESS_MUX_DISABLE;
hsram1.Init.MemoryType = FSMC_MEMORY_TYPE_SRAM;
hsram1.Init.MemoryDataWidth = FSMC_NORSRAM_MEM_BUS_WIDTH_16;
hsram1.Init.BurstAccessMode = FSMC_BURST_ACCESS_MODE_DISABLE;
hsram1.Init.WaitSignalPolarity = FSMC_WAIT_SIGNAL_POLARITY_LOW;
hsram1.Init.WrapMode = FSMC_WRAP_MODE_DISABLE;
hsram1.Init.WaitSignalActive = FSMC_WAIT_TIMING_BEFORE_WS;
hsram1.Init.WriteOperation = FSMC_WRITE_OPERATION_ENABLE;
hsram1.Init.WaitSignal = FSMC_WAIT_SIGNAL_DISABLE;
hsram1.Init.ExtendedMode = FSMC_EXTENDED_MODE_DISABLE;
hsram1.Init.AsynchronousWait = FSMC_ASYNCHRONOUS_WAIT_DISABLE;
hsram1.Init.WriteBurst = FSMC_WRITE_BURST_DISABLE;
HAL_SRAM_Init(&hsram1, &Timing, &Timing);
4.5 图像显示流程
完整的图像采集与显示流程如下:
- 配置DCMI DMA传输目标地址为内存缓冲区
- 启动DCMI捕获
- DMA将图像数据传输到内存缓冲区
- 帧传输完成后触发DCMI中断
- 在中断处理函数中将缓冲区数据通过FSMC传输到LCD
- 循环执行上述过程实现实时显示
5. 关键问题与解决方案
5.1 图像数据对齐问题
在实际调试中发现,直接从DCMI接收的数据直接显示在LCD上会出现颜色错乱的问题。这是因为OV2640输出的RGB565数据在内存中的排列方式与LCD期望的格式不完全一致。
解决方案:
- 在DMA传输完成后,对图像数据进行重新排列
- 或者配置DCMI的ExtendedDataMode为16位模式,直接接收正确的数据格式
5.2 帧率优化
初始实现帧率较低,只有约10fps。通过以下优化措施提升到20fps以上:
- 使用双缓冲机制:当DMA向一个缓冲区传输数据时,CPU处理另一个缓冲区的数据
- 优化LCD写入时序:调整FSMC的时序参数,提高写入速度
- 关闭不必要的图像处理功能:如降噪、锐化等
5.3 内存管理
高分辨率图像会占用大量内存,例如QVGA RGB565格式一帧图像需要150KB内存。解决方案:
- 使用STM32H723的DTCM内存作为图像缓冲区,提供最高速的访问
- 对于更高分辨率,可以使用外部SDRAM扩展存储空间
- 合理分配内存,避免频繁动态分配
6. 性能测试与优化
6.1 帧率测试
在不同分辨率下的实测帧率:
- QVGA(320x240): 22fps
- VGA(640x480): 12fps
- 720P(1280x720): 3fps (需要外部SDRAM支持)
6.2 CPU负载分析
使用STM32的DWT计数器测量CPU使用率:
- QVGA分辨率下,CPU负载约40%
- 主要消耗在图像数据传输和LCD刷新上
- 通过进一步优化DMA传输可以降低CPU负载
6.3 功耗测试
系统在不同工作模式下的电流消耗:
- 全速运行:120mA
- 仅摄像头工作:80mA
- 休眠模式:5mA
可以通过动态调整时钟频率和关闭不必要的外设来优化功耗。
7. 应用扩展
基于这个基础系统,可以进一步扩展以下功能:
7.1 图像处理功能
利用STM32H723的强大计算能力,可以实时实现:
- 边缘检测
- 颜色识别
- 简单的人脸检测
- 二维码识别
7.2 无线传输
添加Wi-Fi或蓝牙模块,可以将图像数据传输到:
- 手机APP显示
- 云端服务器存储和分析
- 其他设备进行协同处理
7.3 本地存储
添加SD卡接口,可以实现:
- 图像和视频录制
- 事件触发存储
- 延时摄影功能
8. 开发心得与建议
在实际开发过程中,我总结了以下几点经验:
-
硬件布局很重要:DCMI接口对信号完整性要求较高,PCB布局时应尽量缩短摄像头与MCU之间的走线长度,保持信号线等长。
-
时钟配置要精确:OV2640的XCLK输入时钟需要精确配置,偏差过大会导致图像数据错乱。建议使用STM32的专用时钟输出引脚(MCO)提供稳定的时钟源。
-
DMA缓冲区对齐:DMA缓冲区地址最好按32字节对齐,可以显著提高传输效率。可以使用__attribute__((aligned(32)))指定对齐方式。
-
电源设计:摄像头模组对电源噪声敏感,建议使用LDO单独供电,并添加适当的滤波电容。
-
调试技巧:
- 可以先使用较低的时钟频率调试,稳定后再提高
- 使用逻辑分析仪抓取DCMI接口信号非常有助于排查问题
- 分段测试:先确保SCCB配置正确,再测试DCMI数据传输
这个项目充分展示了STM32H723处理图像数据的能力,为更复杂的嵌入式视觉应用打下了良好基础。通过合理的硬件设计和软件优化,可以在资源有限的嵌入式系统中实现相当不错的图像采集和处理性能。