带FIFO的OV7725在原有的模块上都加了个AL422B(FIFO)芯片,加了个FIFO主要是为了兼容单片机的低速率考虑。
摄像头的(RGB)图像数据给FIFO的输入端,FIFO的输出端口则输出对应数据。
也就是说我们只要能顺利地读FIFO芯片数据,就能获取图像数据。
现在的目的就是:读FIFO
分辨率模式:VGA(640*480) 60fps QVGA(320*240) 120fps QQVGA(160*120)
时序输出模式:RGB565模式 VAG模式(不同于VGA分辨率)
端口
FIFO[0:7] :主要输出FIFO中存图像数据
FIFO RCLK:读CLK
FIFO WEN:写使能控制口之一.
WEN和HREF通过与非门对WE进行控制。只有WEN、HREF都为高电平时,WE才为低电平(有效),才能写入数据到FIFO
FIFO WRST:写复位
FIFO RRST:读复位
FIFO OE:片选信号
OV SCL:摄像头SCCB协议的clk
OV SDA:摄像头SCCB协议的DATA(双向通道)
OV VSYNC:帧同步
OV7725传感器像素输出相关的PCLK和D[0:7]并没有引出,因为这些引脚被连接到了FIFO的输入部分,OV7725的像素输出时序与FIFO的写入数据时序是一致的,所以在OV7725时钟PCLK的驱动下,它输出的数据会一个字节一个字节地被FIFO接收并存储起来
色彩模式选用VGA模式输出 摄像头到FIFO
一帧画面输出时间:每一帧一共用时510 个t_LINE
VSYNC上升沿,持续4*t_LINE时间,然后下降沿。代表帧同步信号发出,准备开始行同步
延时18*t_LINE
HSYNC下降沿,持续64tp,然后上升沿。代表行同步信号发出,准备开始发送行数据
延时37tp,
HREF上升沿,同时D[9:0]输出10bit图像数据,一共持续640tp,HREF下降沿
第二行
延时43tp(144tp-37tp-64tp=43tp),
HSYNC下降沿,持续64tp,然后上升沿。代表行同步信号发出,准备开始发生行数据
延时37tp,
HREF上升沿,同时D[9:0]输出10bit图像数据,一共持续640tp,HREF下降沿
第三行
延时43tp(144tp-37tp-64tp=43tp),
HSYNC下降沿,持续64tp,然后上升沿。代表行同步信号发出,准备开始发生行数据
延时37tp,
HREF上升沿,同时D[9:0]输出10bit图像数据,一共持续640tp,HREF下降沿
。。。。。。。
第480行
延时43tp(144tp-37tp-64tp=43tp),
HSYNC下降沿,持续64tp,然后上升沿。代表行同步信号发出,准备开始发生行数据
延时37tp,
HREF上升沿,同时D[9:0]输出10bit图像数据,一共持续640tp,HREF下降沿
到此480行本帧发送完毕
延时8t_LINE,可以开始发送下一帧的数据
1 t_LINE=784tp=784*2*t_PCLK(乘以2是因为2个时钟周期的数据拼成一个完整的数据,两个时钟周期才发生一组数据)
1s/一帧画面输出时间=1s能输出多少个画面=多少帧
因为OV7725的PCLK最高可达24Mhz,这里举例使用24Mhz,
则t_PCLK=1/24M
tp=2*t_PCLK=1/12M
t_LINE=784tp=784/12M=60.333333333us
510*t_LINE=一帧画面输出时间=30.8565ms
FIFO模块
FIFO输入的数据流程(VGA时序模式):
等待 VSYNC帧同步信号拉高后-》FIFO读指针复位-》4+18=22个t_LINE后-》FIFO写使能-》D[9:0]开始输出对应数据,写入FIFO->从开始写算起时间480个t_LINE后->写完一帧数据->延时8t_LINE->开始下一帧写入,等待第二帧VSYNC帧同步信号拉高后-》。。。。
其中在如果使用VGA分辨率(不同于VGA模式)每一帧数据写完前就要开始读取
(这个FIFO空间不足以完全存下一帧的数据,如果存满还没读取会覆盖原数据)
所以这里建议当储存写入一半时,就开始读数据,这样就没有覆盖了,覆盖之前数据也已经读走了
OV7725输出一帧的图像大小为240*320*2=153600字节,而本摄像头采用FIFO型号AL422B容量为393216字节,最多可以缓存2帧这样的图像,通过这样的方式,STM32无需直接处理OV7725高速输出的数据,但是配置OV7725为480*640分辨率时,其一帧图像的大小为480*640*2=614400字节,FIFO的容量不足以直接存储这样的图像,因此当OV7725往FIFO写入数据的时候,STM32端要同时读取数据,确保在OV7725覆盖旧数据之前,STM32端已经把这部分数据读取出来了。
FIFO输出数据的流程(读FIFO数据):
QVGA分辨率(320*240)
当储存了一帧数据时,就开始读取图像数据->FIFO读指针复位->给FIFO读时钟->读第一个像素高字节(8bit)->读第一个像素低字节(8bit)->【读完一帧数据】读完一帧数据,然后进制FIFO的写入,开始接收FIFO的一帧数据,FPGA收到一帧数据开始转化成HDMI一帧数据然后发出->FIFO读指针复位->给FIFO读时钟->读第2个像素高字节(8bit)->读第2个像素低字节(8bit)->..........->读完了所有的像素字节接收
FIFO的读时序类似,随着读时钟RCK的运转,在数据输出管脚DO[0:7]就会按地址递增的方式输出数据。在控制读出数据时,一般会先控制读指针作为一个复位操作,把RRST设置为低电平,读指针会复位到FIFO的0地址,然后FIFO数据从该地址开始按自增的方式输出。
编程总流程:
1.初始化SCCB有关的目标引脚(DATA CLK)和端口时钟
2.通过SCCB发送数据指令,设置OV7725
3.OV7725开始输出图像数据,VSYNC输出下降沿信号,FIFO写使能(FIFO WEN 给高电平),开始写入一帧数据
4.VSYNC出现第两次下降沿,写入一帧数据完成,写截止(FIFO WEN 给低电平)
5.FIFO读使能(FIFO RRST 给高电平),开始输出FIFO RCLK(读时钟),D[0:8]开始输出一帧数据给FPGA
从0 地址开始把FIFO 缓存的整帧图像数据读取出来。在这期间,OV7725是持续输出它采集到的图像数据的,但由于禁止写入FIFO,这些数据被丢弃了
6.读一帧数据完成
7.复位 写FIFO指针(FIFO WRST)给高电平,
8.开始下一帧数据写入 循环3-7过程
流程代码:
1.初始化SCCB有关的目标引脚(DATA CLK)和端口时钟
2.通过SCCB发送数据指令,设置OV7725
3.OV7725开始输出图像数据,VSYNC第一次输出下降沿信号,
4.(开始写入FIFO模式)复位 写FIFO指针(FIFO WRST给高电平)[此过程必须保证在开始写之前完成,这里建议在进入写模式前就复位],
FIFO写使能(FIFO WEN 给高电平),开始写入一帧数据
5. VSYNC出现第两次下降沿,写入一帧数据完成
写截止(FIFO WEN 给低电平) (结束写入FIFO模式)
6.(开始读FIFO模式)FIFO读指针复位(FIFO RRST 给高电平),开始输出FIFO RCLK(读时钟),D[0:8]开始输出一帧数据给FPGA
从0 地址开始把FIFO 缓存的整帧图像数据读取出来。在这期间,OV7725是持续输出它采集到的图像数据的,但由于禁止写入FIFO,这些数据也就写不进去了
当/RE和/OE均为低电平时,在RCK信号的上升沿,数据由DI7—DI0输出。
7.读取指定次数后(每次个RCLK并行输出8bit也就是1字节,这里使用的分辨率是320*240,而每两个字节16bit位组成一个元素数据,所以一共是320*240*2=153600次,也就是RCLK输出153600次,读取8bit位数也是153600次,最后存储了153600字节,320*240=76800个像素点数据),读一帧数据完成
8.(结束读FIFO模式)
9.[确定是可以直接读FIFO直接连线到HDMI模块输入口还是要转存一下]
分析:
位数分析:首先FIFO读,输出的8bit,要输出两次才能组成一个HDMI模块需要的16bit数据
所以从这点上来说就要中转
时钟分析:
时钟上来到时无所谓,读取的时钟可以和HDMI的模块保持一致,问题主要在位数上
对应这种位数不统一采取的
方法1:是FPGA的FIFO模块
方法2:来了第一字节后,先不发送,先暂存低8bit,第二字节接收完毕后,存高8bit,组 成16bit发送一次,也就是此模块输入8bit(FIFO的out8bit),奇数次rclk存低8bit,偶数次rclk存高8bit,然后每两个rclk时钟周期结束,发送16bit到HDMI模块
输出16bit给HDMI模块,HDMI模块将其转化为24bit的HDMI输出数据
9.开始下一帧数据写入 循环3-7过程
写入FIFO模式:持续时间在 第一个下降沿开始 第二个(偶数)下降沿结束
这个期间
不复位 写FIFO指针: FIFO WRST给低电平
FIFO写使能:FIFO WEN 给高电平
其余期间
复位 写FIFO指针: FIFO WRST给高电平
FIFO写失能:FIFO WEN 给低电平
读FIFO模式:第二个下降沿结束后开始读FIFO,读取指定的153600次RCLK后次数后一帧读完就结束读FIFO
VSYNC下降沿状态次数:全程只有这几种情况 0次 1次 2次