Digital Camera Interface(数字摄像头接口)

  • HSYNC(行同步):指示一行数据的开始和结束

  • VSYNC(帧同步):指示一帧数据的开始和结束

  • PIXCLK(像素时钟):由摄像头提供给主控芯片的同步时钟,每个时钟周期传输一个像素的数据

  • 数据总线D[0:13]:并行输入数据线,位宽可达14位,根据摄像头支持的像素深度传输数据

  • **XCLK/MCLK:**有些摄像头需要MCU/SOC提供基准时钟。有些摄像头自带晶振提供基准时钟。有些摄像头自带了晶振,但这个晶振只给摄像头外围电路提供时钟,没有给摄像头提供,还是要MCU/SOC提供基准时钟。

FIFO

第一步:摄像头如何“吐”数据?(物理层)

DVP摄像头有两条关键信号线:

  • PCLK(像素时钟):好比心跳,每跳一次,摄像头就吐出一个像素的数据。
  • 数据线(D0-D7):一个心跳周期内,线上传输1个字节(比如YUV格式的灰度值,或RAW RGB的低8位)。

假设你的屏幕分辨率是 640x480,那就是 307,200 个像素。摄像头会以极快的心跳(比如每秒 30 帧,PCLK 高达 24MHz~80MHz),把这 30 多万个像素一个一个地、像流水一样推出来。


第二步:DCMI 接收数据(接口层)

DCMI 的作用是接口协议解析。它负责在 PCLK、VSYNC(帧同步)、HREF(行同步)等信号的控制下,把这些串行(8位/10位/12位/14位)的像素数据捕获下来。

关键点来了: DCMI 收到一个字节,就把这个字节放在一个临时的寄存器里。但是,系统总线(AHB)不是随时随地都能被占用的,CPU或DMA可能正在忙别的。


第三步:FIFO 插入(核心缓冲层)

如果 DCMI 每收到一个字节,就立刻去请求总线写内存,会产生巨大的开销,系统会卡死。 FIFO(先进先出队列) 就是解决这个问题的**“数据蓄水池”**。

实际流程是这样的:

  1. 攒够一波再出发:DCMI 收到第1个字节,放进 FIFO 的第1格;收到第2个字节,放进第2格;收到第3个、第4个……
  2. 触发“批发”传输:当 FIFO 里攒够了 4个字(16个字节,即32bit x 4) 时,DCMI 会立刻向 DMA(直接内存访问控制器)发出一个请求:“我这里满了,快来一次性搬走这16个字节!”
  3. DMA 响应:DMA 收到请求,暂停一下当前工作,通过总线把这16个字节一口气搬运到你指定的内存缓冲区(SRAM)里。
  4. 清空蓄水池:搬走后,FIFO 里的数据被清空,腾出格子继续接收摄像头新吐出来的像素。

第四步:直到攒成一整帧(内存层)

摄像头持续吐像素,DCMI 持续往 FIFO 里塞,DMA 持续把 FIFO 里的数据搬到 SRAM。

  • 当 VSYNC(帧同步)信号告诉你“这一帧结束了”时,SRAM 里的那个缓冲区恰好被填满了 307,200 个像素的数据。
  • 此时,你内存里才有了这一帧完整的图像数据。
FIFO 的作用到底是什么?

如果去掉 FIFO:DCMI 收到一个字节,就叫 DMA 来搬一次。DMA 被频繁打断,搬数据的时间还没等请求的时间长,CPU和总线效率极其低下,甚至因为搬运太慢,下一个像素来了上一个还没搬走,导致数据覆盖丢失。

有了 FIFO(蓄水池): DCMI 把零散的字节拼装成 16 字节的数据包再发给 DMA。DMA 一次性搬走一大块。