OV7620 cmos摄像头的使用Word下载.docx
- 文档编号:18727571
- 上传时间:2022-12-31
- 格式:DOCX
- 页数:16
- 大小:23.45KB
OV7620 cmos摄像头的使用Word下载.docx
《OV7620 cmos摄像头的使用Word下载.docx》由会员分享,可在线阅读,更多相关《OV7620 cmos摄像头的使用Word下载.docx(16页珍藏版)》请在冰豆网上搜索。
2-640x480
60Hz8BitYCrCb4:
RGBRawDataDigitalOutput16Bit/8Bitselectable
CCIR601,CCIR656,ZV端口:
支持8/16位视频数据
SCCB接口:
最大速率支持400kBit/s
YCrCB或YUV输出格式:
支持TV或监视器显示
摄像头工作原理按一定的分辨率,以隔行扫描的方式采集图像上的点,当扫描到某点时,就通过图像传感芯片将该点处图像的灰度转换成与灰度一一对应的电压值,然后将此电压值通过视频信号端输出。
具体而言(参见图5-1),摄像头连续地扫描图像上的一行,则输出就是一段连续的电压信号,电压信号的高低起伏反映了该行图像的灰度变化。
当扫描完一行,视频信号端就输出一个低于最低视频信号电压的电平(如0.3V),并保持一段时间。
这相当于,紧接着每行图像信号之后会有一个电压“凹槽”,此“凹槽”叫做行同步脉冲,它是扫描换行的标志。
然后,跳过一行后(因为摄像头是隔行扫描的),开始扫描新的一行,如此下去,直到扫描完该场的视频信号,接着会出现一段场消隐区。
该区中有若干个复合消隐脉冲,其中有个远宽于(即持续时间远长于)其它的消隐脉冲,称为场同步脉冲,它是扫描换场的标志。
场同步脉冲标志着新的一场的到来,不过,场消隐区恰好跨在上一场的结尾和下一场的开始部分,得等场消隐区过去,下一场的视频信号才真正到来。
摄像头每秒扫描25幅图像,每幅又分奇、偶两场,先奇场后偶场,故每秒扫描50场图像。
奇场时只扫描图像中的奇数行,偶场时则只扫描偶数行。
摄像头有两个重要的指标:
分辨率和有效像素。
分辨率实际上就是每场行同步脉冲数,这是因为行同步脉冲数越多,则对每场图像扫描的行数也越多。
事实上,分辨率反映的是摄像头的纵向分辨能力。
有效像素常写成两数相乘的形式,如“320x240”,其中前一个数值表示单行视频信号的精细程度,即行分辨能力;
后一个数值为分辨率,因而有效像素=行分辨能力×
分辨率。
OV7620功能寄存器的地址为0x00~0x7C(其中,不少是保留寄存器)。
通过设置相应的寄存器,可以使OV7620工作于不同的模式。
例如,设置OV7620为连续扫描、RGB原始数据16位输出方式,需要进行如下设置:
I2CSendByte()为写寄存器函数,它的第1个参数OV7620为宏定义的芯片地址0x42,第2个参数为片内寄存器地址,第3个参数为相应的寄存器设定值。
OV7620的控制采用SCCB(SeriaICameraControlBus)协议。
SCCB是简化的I2C协议,SIO-l是串行时钟输入线,SIO-O是串行双向数据线,分别相当于I2C协议的SCL和SDA。
SCCB的总线时序与I2C基本相同,它的响应信号ACK被称为一个传输单元的第9位,分为Don’tcare和NA。
Don’tcare位由从机产生;
NA位由主机产生,由于SCCB不支持多字节的读写,NA位必须为高电平。
另外,SCCB没有重复起始的概念,因此在SCCB的读周期中,当主机发送完片内寄存器地址后,必须发送总线停止条件。
不然在发送读命令时,从机将不能产生Don’tcare响应信号。
OV7620的使用智能车摄像头组的初期学习中,虽然有不少摄像头优于OV7620,但是相信大部分的车友第一个接触的都是OV7620。
下面从其特性和性能等角度,剖析摄像头的特点。
摄像头的输出格式有RGB565,YUY422等格式,我所接触的第一个摄像头OV7620的输出格式是YUV422。
下面给大家介绍一下YUV422。
1、什么是YUV422人的眼睛对低频信号比对高频信号具有更高的敏感度,事实上,人的眼睛对明视度的改变比对色彩的改变要敏感的多。
因此,人们将RGB三色信号改为YUV来表示,其中Y为灰度,UV为色差。
如果是表示一副彩色图像,同样的道理,YUV444是无损的存储方式,但是需要3个字节,存储空间开销很大。
由于Y分量比UV分量重要的多,因此人们用YUV422来表示。
这样一来图像被压缩了很多,一个字节就可以表示其彩色的信息。
对于OV7620,它有2组并行的数据口Y[7..0]和UV[7..0],其中对于数据口Y[7..0],输出的是灰度值Y,对于UV[7..0]输出的色度信号UV。
下图给出了k个像素(K个字节)输出的格式。
OV762的控制采用SCCB(SerialCameraControlBus)协议。
SCCB的简化的I2C协议,SIO-I是串行时钟输入线,SIO-O是串行双向数据线,分别相当于I2C协议的SCL和SDA。
SCCB的总线时序与I2C基本相同,他的响应信号ACK被陈伟一个传输单元的第9位,分别Donotcare和NA.Donotcare位由从机产生;
另外SCCB没有重复起始的概念,因此在SCCB的读周期中,当主机发送读命令时,从机将不能产生Donotcare响应信号。
由于I2C和SCCB的一些细微差别,所以采用GPIO模拟SCCB总线的方式,SCL所连接的引脚始终设为输出方式,而SDA所连接的引脚在数据传输过程中,通过设置IODIR的值,动态改变引脚的输入/输出方式。
SCCB的写周期直接使用I2C总线协议的写周期时序;
而SC-CB的读周期,则增加一个总线停止条件。
2、OV7620的几个优点第一,OV7620的电平兼容3.3V和5V。
目前智能车用户用到的处理器基本上可以分为XS128和K60和KL25三种控制器,而这三种控制器的工作电平分别是5V和3.3V和3.3V。
OV7620可以完全适应这两种电平,XS128和K60和KL25可以随性切换,无需做电平匹配。
(要注意的是当OV7620接5v和3.3v的时候,输出的效果是不同的,建议在5v的电压下使用,因为在3.3v的电压下使用比较难调,输出的16进制数据清一色偏小。
)
同样的情况下:
第二,OV7620的帧率是60帧/s。
新手学习摄像头的时候,误以为摄像头帧率越快越好,其实不然。
就拿OV7620来说,其PCLK(像素中断)的周期是73ns,该频率下的PCLK很容易被K60的IO捕捉,如果帧率更快的摄像头,其PCLK的周期就会更小,该频率下PCLK不易被K60的IO捕捉到。
(但是鹰眼摄像头不然,火哥的鹰眼摄像头理论上宣传的是150帧每秒,但是他并不是通过PCLK的周期减小从而获得效果的,鹰眼摄像头的高明之处在于它在硬件二值化之后,每一次PCLK中断对外输出了8个像素,而不是1个像素。
鹰眼摄像头已经买来了,以后有机会会试试效果。
第三:
OV7620的分辨率也是非常合适的,在第三篇也提到OV7620是隔行扫描,采集VSYN的话,其输出分辨率是640*240。
如果改为QVGA格式,默认输出分辨率是320*120,该分辨率下非常适合采集赛道,数据容量有限又不会失真图像。
(OV7620的分辨率可以通过SCCB修改,有兴趣修改的可以去查看OV7620的寄存器配置,然后通过SCCB修改。
只有掌握了OV7620的时序,才能灵活得使用OV7620。
下面开始本篇的重点:
OV7620时序分析。
对于OV7620,我们只关心场中断信号VSYN、行中断信号HREF、像素中断信号PCLK的波形。
用示波器去监控这三个波形,可以看到一下关系。
VSYN的周期是16.64ms,高电平时间为换场时间,约80us;
低电平时间内像素输出。
我们在采集VSYN脉冲时,既可以采集上升沿,也可以采集下降沿,采集下降沿更准确些,这也是一场的开始。
从VSYN的周期可以算出,1s/16.64ms=60帧,OV7620的帧率是60帧/s。
HREF的周期63.6us,高电平时间为像素输出时间,约47us;
低电平时间为换行时间,因此采集HREF一定要采集其上升沿,下降沿后的数据是无效的。
从HREF的周期可以算出,16.64ms/63.6us≈261,除去期间的间隙时间,可以算出每场图像有240行。
PCLK的周期是73ns,高电平输出像素,低电平像素无效。
PCLK是一直输出的,因此一定要在触发VSYN并且触发HREF以后,再去捕捉PCLK才能捕捉到像素数据。
从PCLK的周期可以算出,47us/73ns≈640,可以算出每行图像中有640个像素点。
程序如下
在这我分成两部分着重介绍7620的时序程序和贴上SCCB的协议程序(其实原理和处理情况和I2C差不多):
First:
首先要对使用到的一些IO口进行初始化处理,四个部分的初始化,
A.像素中断PCLK
B.行中断HREF
C.场中断VSYNC
D.DMA
程序如下:
[objc]viewplaincopy//初始化OV7620模块
voidOV7620_Init()
{
//像素中断PCLK
GPIO_InitStruct1.GPIO_Pin=OV7620_PCLK_PIN;
GPIO_InitStruct1.GPIO_InitState=Bit_SET;
GPIO_InitStruct1.GPIO_IRQMode=GPIO_IT_DMA_RISING;
GPIO_InitStruct1.GPIO_Mode=GPIO_Mode_IPD;
GPIO_InitStruct1.GPIOx=OV7620_PCLK_PORT;
GPIO_Init(
//行中断HREF
GPIO_InitStruct1.GPIO_Pin=OV7620_HREF_PIN;
GPIO_InitStruct1.GPIO_IRQMode=GPIO_IT_RISING;
GPIO_InitStruct1.GPIOx=OV7620_HREF_PORT;
//场中断VSYNC
GPIO_InitStruct1.GPIO_Pin=OV7620_VSYNC_PIN;
//GPIO_IT_RISING
//GPIO_Mode_IPD
GPIO_InitStruct1.GPIOx=OV7620_VSYNC_PORT;
//配置DMA
DMA_InitStruct1.Channelx=DMA_CH1;
//DMA1通道
DMA_InitStruct1.PeripheralDMAReq=PORTC_DMAREQ;
//C端口(PCLK)上升呀触发
DMA_InitStruct1.MinorLoopLength=170;
//传输次数超过摄像头每行像素数即可
DMA_InitStruct1.TransferBytes=1;
//每次传输1个字节
DMA_InitStruct1.DMAAutoClose=ENABLE;
//连续采集
DMA_InitStruct1.EnableState=ENABLE;
//初始化后立即采集
DMA_InitStruct1.SourceBaseAddr=(uint32_t)//摄像头端口接D0-D7
DMA_InitStruct1.SourceMajorInc=0;
//地址不增加
DMA_InitStruct1.SourceDataSize=DMA_SRC_8BIT;
//8BIT数据
DMA_InitStruct1.SourceMinorInc=0;
DMA_InitStruct1.DestBaseAddr=(uint32_t)DMABuffer;
//DMA内存//uint8_tDMABuffer[400];
DMA_InitStruct1.DestMajorInc=0;
DMA_InitStruct1.DestDataSize=DMA_DST_8BIT;
DMA_InitStruct1.DestMinorInc=1;
//每次传输+1个字节
DMA_Init(
}
然后开始编写场中断函数,编写之前我们需要在心里理一下思绪,在场中断函数里我们要按照顺序,做以下几件事情:
A.确认是否是场中断,确认之后进入处理。
B.清除标志位Flag。
(Flag是用来观察是否处理完一场图像的标志)
C.清除中断标志。
D.计数全部清零。
(因为新的一场已经开始)
E.打开行中断,关闭场中断。
[objc]viewplaincopyvoidPORTB_IRQHandler(void)//功能:
PORTB外部中断服务//V
u8i=9;
if((PORTB-》ISFR》》i)==1)
Flag=0;
PORTB-》ISFR|=(1《《9);
Row=0;
Row_Num=0;
NVIC_EnableIRQ(PORTA_IRQn);
//行
NVIC_DisableIRQ(PORTB_IRQn);
//场
接着编写行中断函数,在行中断中,我们要做以下几件事情:
A.确认是否是行中断。
B.关闭DMA中断,防止提前进入PCLK的采集。
C.跳过消隐区。
(消隐区:
消隐区的出现,在电视机原理上,是因为电子束结束一行扫描,从一行尾换到另一行头,期间的空闲期,这叫做行消隐信号;
同理,从一场尾换到另一场尾,期间也会有空闲期,这叫做场消隐信号。
D.进入行采集处理。
E.配置DMA,并且打开DMA中断。
F.行计数加1,表示已经采集完了一行。
(因为PCLK的中断周期远远小于HREF的中断周期,所以不需要杞人忧天,担心中断搞得混乱。
G.当采集完了自己的目标行数之后,标志位Flag修改。
并关闭行中断,打开场中断,等待下一次的场中断。
[objc]viewplaincopyvoidPORTA_IRQHandler(void)//功能:
PORTA外部中断服务//Herf
u8i=14;
DMA_SetEnableReq(DMA_CH1,DISABLE);
//closeDMAISr
if((PORTA-》ISFR》》i)==1);
PORTA-》ISFR|=(1《《14);
if(Row_Num++》15)//消隐区啦
if(Row_Num%5)//进入行采集
DMA_InitStruct1.DestBaseAddr=(uint32_t)Image[Row];
///////////////////////////////////////////////////////
Row++;
if(Row==MAX_ROW)
Flag=1;
NVIC_DisableIRQ(PORTA_IRQn);
NVIC_EnableIRQ(PORTB_IRQn);
最后给大家看一下,DMA的初始化函数,这个函数是超核的库里面的,不是我写的,但是上面的解释很详细了,相信都能看懂。
[objc]viewplaincopyvoidDMA_Init(DMA_InitTypeDef*DMA_InitStruct)
//参数检查
assert_param(IS_DMA_REQ(DMA_InitStruct-》PeripheralDMAReq));
assert_param(IS_DMA_ATTR_SSIZE(DMA_InitStruct-》SourceDataSize));
assert_param(IS_DMA_ATTR_DSIZE(DMA_InitStruct-》DestDataSize));
assert_param(IS_DMA_CH(DMA_InitStruct-》Channelx));
assert_param(IS_DMA_MINOR_LOOP(DMA_InitStruct-》MinorLoopLength));
//打开DMA0和DMAMUX时钟源
SIM-》SCGC6|=SIM_SCGC6_DMAMUX_MASK;
SIM-》SCGC7|=SIM_SCGC7_DMA_MASK;
//配置DMA触发源
DMAMUX-》CHCFG[DMA_InitStruct-》Channelx]=DMAMUX_CHCFG_SOURCE(DMA_InitStruct-》PeripheralDMAReq);
//设置源地址信息
DMA0-》TCD[DMA_InitStruct-》Channelx].SADDR=DMA_InitStruct-》SourceBaseAddr;
//执行完源地址操作后,是否在源地址基础上累加
DMA0-》TCD[DMA_InitStruct-》Channelx].SOFF=DMA_SOFF_SOFF(DMA_InitStruct-》SourceMinorInc);
//设置源地址传输宽度
DMA0-》TCD[DMA_InitStruct-》Channelx].ATTR=0;
DMA0-》TCD[DMA_InitStruct-》Channelx].ATTR|=DMA_ATTR_SSIZE(DMA_InitStruct-》SourceDataSize);
//主循环进行完后是否更改源地址
DMA0-》TCD[DMA_InitStruct-》Channelx].SLAST=DMA_InitStruct-》SourceMajorInc;
//设置目的地址信息
DMA0-》TCD[DMA_InitStruct-》Channelx].DADDR=DMA_InitStruct-》DestBaseAddr;
DMA0-》TCD[DMA_InitStruct-》Channelx].DOFF=DMA_DOFF_DOFF(DMA_InitStruct-》DestMinorInc);
//设置目的地址传输宽度
DMA0-》TCD[DMA_InitStruct-》Channelx].ATTR|=DMA_ATTR_DSIZE(DMA_InitStruct-》DestDataSize);
DMA0-》TCD[DMA_InitStruct-》Channelx].DLAST_SGA=DMA_InitStruct-》DestMajorInc;
//设置计数器长度循环次数
//设置数据长度长度每次递减也被称作当前主循环计数currentmajorloopcount
DMA0-》TCD[DMA_InitStruct-》Channelx].CITER_ELINKNO=DMA_CITER_ELINKNO_CITER(DMA_InitStruct-》MinorLoopLength);
//起始循环计数器当主循环计数器为0时候将装载起始循环计数器的值
DMA0-》TCD[DMA_InitStruct-》Channelx].BITER_ELINKNO=DMA_BITER_ELINKNO_BITER(DMA_InitStruct-》MinorLoopLength);
//设置每一次传输字节的个数个数到达上限时DMA便将数据存入RAM
DMA0-》TCD[DMA_InitStruct-》Channelx].NBYTES_MLNO=DMA_NBYTES_MLNO_NBYTES(DMA_InitStruct-》TransferBytes);
//设置DMATCD控制寄存器
DMA0-》TCD[DMA_InitStruct-》Channelx].CSR=0;
if(DMA_InitStruct-》DMAAutoClose==ENABLE)
DMA0-》TCD[DMA_InitStruct-》Channelx].CSR|=DMA_CSR_DREQ_MASK;
else
DMA0-》TCD[DMA_InitStruct-》Channelx].CSR
//使能此寄存器DMA开始工作
DMA_SetEnableReq(DMA_InitStruct-》Channelx,DMA_InitStruct-》EnableState);
//DMA通道使能
DMAMUX-》CHCFG[DMA_InitStruct-》Channelx]|=DMAMUX_CHCFG_ENBL_MASK;
Second:
讲完OV7620的一些中断处理函数之后,我们来看看SCCB的库程序,这个库可以通用,需要的车友可以直接添加,只需要对照自己
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- OV7620 cmos摄像头的使用 cmos 摄像头 使用
![提示](https://static.bdocx.com/images/bang_tan.gif)