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(先进先出队列) 就是解决这个问题的**“数据蓄水池”**。
实际流程是这样的:
- 攒够一波再出发:DCMI 收到第1个字节,放进 FIFO 的第1格;收到第2个字节,放进第2格;收到第3个、第4个……
- 触发“批发”传输:当 FIFO 里攒够了 4个字(16个字节,即32bit x 4) 时,DCMI 会立刻向 DMA(直接内存访问控制器)发出一个请求:“我这里满了,快来一次性搬走这16个字节!”
- DMA 响应:DMA 收到请求,暂停一下当前工作,通过总线把这16个字节一口气搬运到你指定的内存缓冲区(SRAM)里。
- 清空蓄水池:搬走后,FIFO 里的数据被清空,腾出格子继续接收摄像头新吐出来的像素。
第四步:直到攒成一整帧(内存层)
摄像头持续吐像素,DCMI 持续往 FIFO 里塞,DMA 持续把 FIFO 里的数据搬到 SRAM。
- 当 VSYNC(帧同步)信号告诉你“这一帧结束了”时,SRAM 里的那个缓冲区恰好被填满了 307,200 个像素的数据。
- 此时,你内存里才有了这一帧完整的图像数据。
FIFO 的作用到底是什么?
如果去掉 FIFO:DCMI 收到一个字节,就叫 DMA 来搬一次。DMA 被频繁打断,搬数据的时间还没等请求的时间长,CPU和总线效率极其低下,甚至因为搬运太慢,下一个像素来了上一个还没搬走,导致数据覆盖丢失。
有了 FIFO(蓄水池): DCMI 把零散的字节拼装成 16 字节的数据包再发给 DMA。DMA 一次性搬走一大块。