第四章:图像采集与显示通路
摄像头接口(OV5640)
做图像加速,第一步就是搞定数据源。我最早接触OV5640时,觉得500万像素挺唬人,后来发现真正麻烦的不是像素多,而是时序。
OV5640用的是DVP并行接口,说白了就是8位数据线加同步信号。它的核心信号就这几个:
- PCLK:像素时钟,每个上升沿传一个字节
- VSYNC:帧同步,高电平表示新一帧开始
- HREF:行同步,高电平表示有效像素
- DATA[7:0]:像素数据,YUV格式下每两个时钟传一个像素
我个人习惯把摄像头配置放在上电后的前100ms完成。为什么?因为OV5640默认输出的是640x480的测试图,你不配置它就一直出彩条。我在项目里遇到过,板子一上电看到彩条还以为摄像头坏了,查了半天才发现是没写寄存器。
关键配置项:
- 输出格式:RGB565 或 YUV422
- 分辨率:1280x720 或 1920x1080
- 帧率:30fps 或 60fps
- 镜像翻转:根据安装方向调整
配置OV5640要用SCCB总线,其实就是I2C的变种。我建议你直接用Xilinx的I2C IP核,省得自己写时序。不过要注意,OV5640的SCCB地址是0x3C,写操作是0x78,读操作是0x79。这个坑我踩过,地址搞反了摄像头死活不响应。
HDMI输出
图像采集进来,总得让人看到吧?HDMI输出就是干这个的。Zynq上做HDMI,我推荐用Xilinx的Video PHY Controller加DMA的方式。
HDMI的核心是TMDS编码,说白了就是把8位数据转成10位,再串行化发送。不过咱们不用自己写编码器,Xilinx的IP核都封装好了。你需要关注的是时钟:
| 分辨率 | 像素时钟 | TMDS时钟 |
|---|---|---|
| 640x480@60 | 25.175 MHz | 251.75 MHz |
| 1280x720@60 | 74.25 MHz | 742.5 MHz |
| 1920x1080@60 | 148.5 MHz | 1.485 GHz |
嗯,这里要注意。TMDS时钟是像素时钟的10倍,因为每个像素要串行化成10位。Zynq的GTX收发器最高能跑到12.5Gbps,所以1080p完全没问题。但如果你要做4K,就得用Zynq UltraScale+了。
曾经踩过的坑:HDMI的EDID读取。有些显示器会要求你先读EDID再输出信号,否则黑屏。我有一块板子,接AOC显示器正常,接DELL就黑屏,查了两天才发现是EDID时序没处理好。
AXI4-Stream数据流设计
摄像头和HDMI之间怎么连?答案就是AXI4-Stream。这是Xilinx定义的一种流式数据传输协议,说白了就是数据加握手信号。
AXI4-Stream的核心信号就四个:
- TVALID:发送方说「我有数据」
- TREADY:接收方说「我能收」
- TDATA:数据总线,宽度可以自定义
- TLAST:一帧或一行的结束标志
你想想看,摄像头采集的数据是并行的,HDMI输出也是并行的,但中间经过DDR缓存时,数据必须串行化。AXI4-Stream就是干这个的。
我一般这样设计数据通路:
- OV5640输出DVP并行数据
- 用Video In to AXI4-Stream IP核转成Stream
- 经过VDMA写入DDR
- VDMA从DDR读出Stream数据
- 用AXI4-Stream to Video Out IP核转回并行
- 送给HDMI TX芯片
这个流程里,VDMA是关键。它负责把Stream数据缓存到DDR,解决摄像头和显示器帧率不匹配的问题。比如摄像头是30fps,显示器是60fps,VDMA就会把一帧数据存下来,然后让显示器读两遍。
个人经验:VDMA的帧缓冲建议设成3帧。为什么?因为摄像头在写第N帧时,显示器在读第N-1帧,同时第N-2帧作为备用。这样即使摄像头偶尔丢一帧,显示器也不会卡顿。我试过2帧缓冲,在某些显示器上会出现撕裂现象。
AXI4-Stream的握手逻辑也很重要。TVALID和TREADY必须同时为高,数据才算传输成功。如果接收方来不及处理,TREADY拉低,发送方就得等待。这个机制保证了数据不会丢失。
我曾经在调试时发现图像有花屏,查了半天发现是TLAST信号没对齐。TLAST应该在每行最后一个像素时拉高,但我的逻辑提前了一个时钟。这种问题用ILA抓一下波形就能看出来。
整体数据通路
把上面三个模块串起来,就是完整的图像采集与显示通路。我画了个框图,你看看就明白了:
这个通路看起来简单,但实际调试时问题不少。我总结几个常见坑:
- 时钟域同步:摄像头时钟和AXI总线时钟不同频,必须用异步FIFO隔离。我习惯用Xilinx的FIFO Generator,设置成独立时钟模式。
- 数据对齐:OV5640输出的是8位数据,但RGB565需要16位。两个时钟拼一个像素,这个逻辑写不对就会出颜色错乱。
- 帧同步:VSYNC和TLAST要配合好。我建议在VSYNC上升沿时,强制把TLAST拉高,确保帧边界对齐。
核心要点:图像采集与显示通路的设计,本质上是解决三个问题——数据从哪里来(摄像头)、数据存哪里(DDR)、数据去哪里(HDMI)。AXI4-Stream就是连接这三者的桥梁。你只要把桥搭好了,剩下的就是调参数。
嗯,这一章的内容就这些。摄像头接口、HDMI输出、AXI4-Stream数据流,这三个模块是图像加速的基础。你先把它们调通,后面做算法加速就顺了。