第四章:图像采集与显示通路

摄像头接口(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就是干这个的。

我一般这样设计数据通路:

  1. OV5640输出DVP并行数据
  2. 用Video In to AXI4-Stream IP核转成Stream
  3. 经过VDMA写入DDR
  4. VDMA从DDR读出Stream数据
  5. 用AXI4-Stream to Video Out IP核转回并行
  6. 送给HDMI TX芯片

这个流程里,VDMA是关键。它负责把Stream数据缓存到DDR,解决摄像头和显示器帧率不匹配的问题。比如摄像头是30fps,显示器是60fps,VDMA就会把一帧数据存下来,然后让显示器读两遍。

个人经验:VDMA的帧缓冲建议设成3帧。为什么?因为摄像头在写第N帧时,显示器在读第N-1帧,同时第N-2帧作为备用。这样即使摄像头偶尔丢一帧,显示器也不会卡顿。我试过2帧缓冲,在某些显示器上会出现撕裂现象。

AXI4-Stream的握手逻辑也很重要。TVALID和TREADY必须同时为高,数据才算传输成功。如果接收方来不及处理,TREADY拉低,发送方就得等待。这个机制保证了数据不会丢失。

我曾经在调试时发现图像有花屏,查了半天发现是TLAST信号没对齐。TLAST应该在每行最后一个像素时拉高,但我的逻辑提前了一个时钟。这种问题用ILA抓一下波形就能看出来。

整体数据通路

把上面三个模块串起来,就是完整的图像采集与显示通路。我画了个框图,你看看就明白了:

OV5640 DVP接口 PCLK/DATA Video In to AXI4-Stream AXI4-Stream VDMA 帧缓冲 DDR控制 DDR4 AXI4-Stream AXI4-Stream to Video Out RGB/HS/VS HDMI TX 图像采集与显示通路框图 图例: 摄像头 格式转换 VDMA DDR 格式转换 HDMI输出

这个通路看起来简单,但实际调试时问题不少。我总结几个常见坑:

  • 时钟域同步:摄像头时钟和AXI总线时钟不同频,必须用异步FIFO隔离。我习惯用Xilinx的FIFO Generator,设置成独立时钟模式。
  • 数据对齐:OV5640输出的是8位数据,但RGB565需要16位。两个时钟拼一个像素,这个逻辑写不对就会出颜色错乱。
  • 帧同步:VSYNC和TLAST要配合好。我建议在VSYNC上升沿时,强制把TLAST拉高,确保帧边界对齐。

核心要点:图像采集与显示通路的设计,本质上是解决三个问题——数据从哪里来(摄像头)、数据存哪里(DDR)、数据去哪里(HDMI)。AXI4-Stream就是连接这三者的桥梁。你只要把桥搭好了,剩下的就是调参数。

嗯,这一章的内容就这些。摄像头接口、HDMI输出、AXI4-Stream数据流,这三个模块是图像加速的基础。你先把它们调通,后面做算法加速就顺了。

可可精品资料库