赞
踩
目录
OV7670是由OV(OmniVision)公司生产的一颗1/6寸的CMOS VGA图像传感器。该传感器体积小、工作电压低,提供单片VGA摄像头和影像处理器的所有功能。通过SCCB总线控制,可以输出整帧、子采样、取窗口等方式的各种分辨率8位影像数据。该产品VGA图像最高达到30帧/秒,用户可以完全控制图像质量、数据格式和传输方式。
1.感光整列(Image Array ) OV7670 总共有656*488 个像素,其中640*480 个有效(即有效像素为30W )。
2.时序发生器(Video Timing Generator )
时序发生器具有的功能包括:整列控制和帧率发生(7 种不同格式输出)、内部信号发生器和分布、帧率时序、自动曝光控制、输出外部时序(VSYNC 、HREF/HSYNC 和PCLK )。
3.模拟信号处理(Analog Processing )
模拟信号处理所有模拟功能,并包括:自动增益(AGC )和自动白平衡(AWB )。
4.A/D 转换(A/D )
原始的信号经过模拟处理器模块之后 ,分G 和BR 两路进入一个 10 位的A/D转换器, A/D 转换器工作在12M 频率,与像素频率完全同步(转换的频率和帧率有关)。
除A/D 转换器外,该模块还有以下三个功能:
l 黑电平校正(BLC)
l U/V 通道延迟
l A/D 范围控制
A/D 范围乘积和A/D 的范围控制共同设置A/D 的范围和最大值,允许用户根据应用调整图片的亮度。
5.测试图案发生器(Test Pattern Generator)
测试图案发生器功能包括:八色彩色条图案、渐变至黑白彩色条图案和输出脚移位“1”。
6.数字处理器(DSP )
这个部分控制由原始信号插值到RGB信号的过程,并控制一些图像质量:
边缘锐化(二维高通滤波器)
l 颜色空间转换( 原始信号到RGB或者YUV/YCbYCr)
l RGB 色彩矩阵以消除串扰
l 色相和饱和度的控制
l 黑/ 白点补偿
l 降噪
l 镜头补偿
l 可编程的伽玛
l 十位到八位数据转换
7.缩放功能(Image Scaler )
这个模块按照预先设置的要求输出数据格式,能将YUV/RGB 信号从VGA 缩小到CIF以下的任何尺寸。
8.数字视频接口(Digital Video Port )
通过寄存器COM2[1:0],调节IOL/IOH 的驱动电流,以适应用户的负载。
9.SCCB 接口(SCCB Interface)
SCCB 接口控制图像传感器芯片的运行,详细使用方法参照光盘的《OmniVision Technologies Seril Camera Control Bus(SCCB) Specification》这个文档。
值得注意的是SCCB接口与IIC很相似,在SCCB_clk高电平期间拉低SCCB_SDA会产生起始信号;在SCCB_clk高电平期间恢复SCCB_SDA高电平会产生起始信号。
10.LED 和闪光灯的输出控制(LED and Storbe Flash Control Output )
OV7670 有闪光灯模式,可以控制外接闪光灯或闪光LED 的工作;
OV7670 的寄存器通过SCCB 时序访问并设置。
图1 OV7670的引脚定义
图2 ov7670输出时序图
图3 ov7670帧时序图
OV7670模块主要支持的分辨率:
VGA:640*480的输出模式
QVGA:320*240的输出模式
QQVGA:160*120的输出模式
在OV7670模块中,跟分辨率相关的寄存器有以下几个:
寄存器地址 | 寄存器名称 | 功能 |
---|---|---|
0x17 | HSTART | 行帧开始高八位(低三位在HREF[2:0]) |
0x18 | HSTOP | 行帧结束高八位(低三位在HREF[5:3]) |
0x19 | VSTART | 场频开始高八位(低两位在VREF[1:0]) |
0x1A | VSTOP | 场频结束高八位(低两位在VREF[3:2]) |
0x03 | VREF | 位[3:2]VREF结束低两位,位[1:0]VREF开始低两位 |
0x32 | HREF | 位[5:3]HREF结束低三位,位[2:0]VREF开始低三位 |
网上一般给出的参数设置方式是:QVGA RGB565 320*240
{0x17,0x17},
{0x18,0x05},
{0x19,0x02},
{0x1A,0x7B},
{0x03,0x0A}
{0x32,0x80},
HREF的计算 :
HREF = WEIGHT*2;每个像素点有两个数据
HSTOP = START + HREF
PCLK的计算:
VSYNC:510*Line = 3*tLINE+15*tLINE+480*tLINE
HREF:784*tp = 640*tp+144*tp
HSYNC:784*tp = 80*tp+45*tp+640*tp+19*tp
VGA RGB565,YUV 30 fps
PCLK = 784*510*30*2(byte)=24MHz
VSTART和VSTOP决定了采样的行数也就是高度,VSTART = HEIGHE*2 +VSTOP
注:QVAG的时序宽度是VGA的两倍,因此若VGA下为640*480,则在QVAG下为320*240。若HSTOP >784,即超出周期,需要进行取余操作。
图4 FIFO的读取示意图
在使用FIFO使还要注意FIFO的深度和宽度:
FIFO的宽度:用fifo_data_size表示,也就是每个数据的宽度
FIFO的深度:用fifo_addr_size表示,也就是地址的大小(可以储存多少个数据)。
图5 FIFO的示意图
写数据端口:
读数据端口:
此外,FIFO还根据w_clk 和 r_clk 是否一致划分为SCFIFO (同步FIFO) 和DCFIFO (异步FIFO) 。同步FIFO是指读时钟和写时钟为同一个时钟,在时钟沿来临时同时发生读写操作。异步FIFO是指读写时钟不一致,读写时钟是互相独立的。
AL422内置了3M的DRAM,提供了50%以上的内存以支持数字PC图形或视频应用程序的高分辨率。目前常用的主要有以下三种型号:
这里我们选用的是AL422B缓存芯片,如下图所示。
BMP(全称Bitmap)是Windows操作系统中的标准图像文件格式,可以分成两类:设备有向量相关位图(DDB)和设备无向量关位图(DIB),使用非常广。它采用位映射存储格式,除了图像深度可选以外,不采用其他任何压缩,因此,BMP文件所占用的空间很大。BMP文件的图像深度可选1bit、4bit、8bit及24bit。BMP文件存储数据时,图像的扫描方式是按从左到右、从下到上的顺序。由于BMP文件格式是Windows环境中交换与图有关的数据的一种标准,因此在Windows环境中运行的图形图像软件都支持BMP图像格式。
BMP是最简单的图片编码,是由文件头、位图信息头、颜色信息和图形数据等四部分组成。我们先来了解下这几个部分。
1、BMP 文件头(14 字节):BMP 文件头数据结构含有 BMP 文件的类型、文件大小和位图起始位置等信息。
- //BMP 文件头
- typedef __packed struct
- {
- u16 bfType ; //文件标志.只对'BM',用来识别 BMP 位图类型
- u32 bfSize ; //文件大小,占四个字节
- u16 bfReserved1 ; //保留
- u16 bfReserved2 ; //保留
- u32 bfOffBits ; //从文件开始到位图数据(bitmap data)开始之间的偏移量
- }BITMAPFILEHEADER ;
2、位图信息头(40 字节):BMP 位图信息头数据用于说明位图的尺寸等信息。
- typedef __packed struct
- {
- u32 biSize ; //说明 BITMAPINFOHEADER 结构所需要的字数。
- long biWidth ; //说明图象的宽度,以象素为单位
- long biHeight ; //说明图象的高度,以象素为单位
- u16 biPlanes ; //为目标设备说明位面数,其值将总是被设为 1
- u16 biBitCount ; //说明比特数/象素,其值为 1、4、8、16、24、或 32
- u32 biCompression ; //说明图象数据压缩的类型。其值可以是下述值之一:
- //BI_RGB:没有压缩;
- //BI_RLE8:每个象素 8 比特的 RLE 压缩编码,压缩格式由 2 字节组成
- //BI_RLE4:每个象素 4 比特的 RLE 压缩编码,压缩格式由 2 字节组成
- //BI_BITFIELDS:每个象素的比特由指定的掩码决定。
- u32 biSizeImage ;//说明图象的大小,以字节为单位。当用 BI_RGB 格式时,可设置为 0
- long biXPelsPerMeter ;//说明水平分辨率,用象素/米表示
- long biYPelsPerMeter ;//说明垂直分辨率,用象素/米表示
- u32 biClrUsed ; //说明位图实际使用的彩色表中的颜色索引数
- u32 biClrImportant ; //说明对图象显示有重要影响的颜色索引的数目,
- //如果是 0,表示都重要。
- }BITMAPINFOHEADER ;
3、颜色表(调色板):颜色表用于说明位图中的颜色,它有若干个表项,每一个表项是一个RGBQUAD 类型的结构,定义一种颜色。
- //颜色表
- typedef __packed struct
- {
- u8 rgbBlue ; //指定蓝色强度
- u8 rgbGreen ; //指定绿色强度
- u8 rgbRed ; //指定红色强度
- u8 rgbReserved ; //保留,设置为 0
- }RGBQUAD
-
- //BMP 文件头、位图信息头和颜色表组成位图信息
- typedef __packed struct
- {
- BITMAPFILEHEADER bmfHeader;
- BITMAPINFOHEADER bmiHeader;
- RGBQUAD bmiColors[1];
- }BITMAPINFO;
4、位图数据:位图数据记录了位图的每一个像素值,记录顺序是在扫描行内是从左到右,扫描行之间是从下到上。
biBitCount=16 表示位图最多有 65536 种颜色,每个像素用 16 位(2 个字节)表示。当 biCompression=BI_RGB(0) 时,采用RGB555格式,最高位恒为0;当biCompression=BI_BITFIELDS(3) 时, 红、绿、蓝的掩码分别是:0x7C00、0x03E0、0x001F。我们需要设置 biBitCount 的值为 16,这样得到新的位图信息(BITMAPINFO)结构体:
- typedef __packed struct
- {
- BITMAPFILEHEADER bmfHeader;
- BITMAPINFOHEADER bmiHeader;
- u32 RGB_MASK[3]; //调色板用于存放 RGB 掩码.
- }BITMAPINFO;
摄像头模块存储图像数据的过程为:
等待 OV7725 帧同步信号(利用外部中断)→FIFO 写指针复位→FIFO写使能→等待第二个 OV7725 帧同步信号→FIFO 写禁止。
注意:FIFO 写禁止操作不是必须的,只有当你想将一帧图片数据存储在 FIFO,并在外部 MCU 读取完这帧图片数据之前,不再采集新的图片数据的时候,才需要进行 FIFO 写禁止。
摄像头模块读取图像数据的过程为:
FIFO 读指针复位(FIFO_RRST=0)→给FIFO 读时钟(FIFO_RCLK)→读取第一个像素高字节→给 FIFO 读时钟→读取第一个像素低字节→给 FIFO 读时钟→读取第二个像素高字节→循环读取剩余像素→结束。
名称 | 功能 | 其他 |
---|---|---|
OV7670_Init(); | 定义I/O口 | |
SCCB_Init(); | 定义SCCB的时钟线和数据线 | |
OV7670_Light_Mode(u8 mode); | 设置色彩白平衡 | |
OV7670_Color_Saturation(u8 sat); | 设置色彩饱和度 | |
OV7670_Brightness(u8 bright); | 设置色彩亮度 | |
OV7670_Contrast(u8 contrast); | 设置色对比度 | |
OV7670_Window_Set(u16 s_x,u16 s_y,u16 width,u16 height); | 设置图像显示范围 | 设置QVAG |
EXTIx_IRQHandler(); | 帧中断标记,提醒MCU从FIFO取数据 | EXTI5-EXTI9共用一个中断程序 |
camer_refresh(); | 读取FIFO的数据并显示在LCD上 | 一帧要读取76800字节 |
- u8 OV7670_Init(void)
- {
- u8 temp;
- u16 i=0;
- GPIO_InitTypeDef GPIO_InitStructure;
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOC|RCC_APB2Periph_GPIOD|RCC_APB2Periph_GPIOG|RCC_APB2Periph_AFIO, ENABLE); //使能相关时钟
-
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
- GPIO_Init(GPIOA, &GPIO_InitStructure);
- GPIO_SetBits(GPIOA,GPIO_Pin_8);
-
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3|GPIO_Pin_4;
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
- GPIO_Init(GPIOB, &GPIO_InitStructure);
- GPIO_SetBits(GPIOB,GPIO_Pin_3|GPIO_Pin_4);
-
-
- GPIO_InitStructure.GPIO_Pin = 0xff;
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
- GPIO_Init(GPIOC, &GPIO_InitStructure);
-
-
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
- GPIO_Init(GPIOD, &GPIO_InitStructure);
- GPIO_SetBits(GPIOD,GPIO_Pin_6);
-
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_14|GPIO_Pin_15;
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
- GPIO_Init(GPIOG, &GPIO_InitStructure);
- GPIO_SetBits(GPIOG,GPIO_Pin_14|GPIO_Pin_15);
-
- GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable,ENABLE); //SWD
-
- SCCB_Init(); //初始化SCCB的I/O口
- if(SCCB_WR_Reg(0x12,0x80))return 1; //复位SCCB
- delay_ms(50);
- //读取型号
- temp=SCCB_RD_Reg(0x0b);
- if(temp!=0x73)return 2;
- temp=SCCB_RD_Reg(0x0a);
- if(temp!=0x76)return 2;
- //初始化序列
- for(i=0;i<sizeof(ov7670_init_reg_tbl)/sizeof(ov7670_init_reg_tbl[0]);i++)
- {
- SCCB_WR_Reg(ov7670_init_reg_tbl[i][0],ov7670_init_reg_tbl[i][1]);
- }
- return 0x00; //ok
- }
-
-
-
- void OV7670_Window_Set(u16 sx,u16 sy,u16 width,u16 height) //设置输出窗口
- {
- u16 endx;
- u16 endy;
- u8 temp;
- endx=sx+width*2; //V*2
- endy=sy+height*2;
- if(endy>784)endy-=784;
- temp=SCCB_RD_Reg(0X03); //读取Vref之前的值
- temp&=0XF0;
- temp|=((endx&0X03)<<2)|(sx&0X03);
- SCCB_WR_Reg(0X03,temp); //设置Vref的start和end的最低两位
- SCCB_WR_Reg(0X19,sx>>2); //设置Vref的start的高八位
- SCCB_WR_Reg(0X1A,endx>>2); //设置Vref的end的高八位
- temp=SCCB_RD_Reg(0X32); //读取Href的值
- temp&=0XC0;
- temp|=((endy&0X07)<<3)|(sy&0X07);
- SCCB_WR_Reg(0X17,sy>>3); //设置Href的start的高八位
- SCCB_WR_Reg(0X18,endy>>3); //设置Href的end的高八位
- }
本次的照相机实验是基于上一部分的摄像头实验,并在其基础上增加了SD卡和FATFS新建/存储文件的部分代码,对摄像头、外部中断和部分输出引脚的初始化不再赘述。
采集到图像→按键检测命令→利用f_open检测是否有命名,若没有创造路径→图像编码→图像数据保存。
函数名称 | 功能 | 其他 |
---|---|---|
bmp_encode | BMP编码 | 截屏大小不能超过分辨率 |
camera_new_pathname | 创建一个新的图片文件 | |
camera_refresh | 更新图像 | |
f_open | 打开/创建一个文件 | |
f_write | 写文件 |
这里的对SD卡操作主要是利用FATFS文件系统进行的,具体可以参考往期的笔记。
通过上述的学习,笔者想到了利用超声波模块HC_SR04与OV7670进行结合,当有物体靠近时会自动进行拍照记录,后续也可以利用FATFS进行图片查看,从而达到监视器的作用。在工作流程上只比上例多一个距离检测及判断,整体的工程量并不是很大。
注:HC-SR04的使用方法不难,网上的例程很多便不再赘述了,同样的也可以使用红外模块等进行检测。
- uint32_t Get_Timer() //获取传递时间
- {
- uint32_t t = 0;
- t = count*1000;
- t += TIM_GetCounter(TIM2);
- TIM2->CNT = 0;
- delay_ms(50);
- return t;
- }
-
-
-
- float Get_Length(){ //获取目标距离
- float t = 0,length = 0;
- GPIO_SetBits(GPIOx,trigGPIO);
- delay_us(20);
- GPIO_ResetBits(GPIOx,trigGPIO);
- while (GPIO_ReadInputDataBit(GPIOx,echoGPIO) == RESET){
- };
- OpenTIM2();
- while (GPIO_ReadInputDataBit(GPIOx,echoGPIO) == SET);
- CloseTIM2();
- t = Get_Timer() / 1000.0; //得出总传递时间
- length = t*34.0; //得出总传递路程
- return length/2; //返回实际距离
- }
具体代码可以点击链接:https://download.csdn.net/download/sincerelover/88760703
免责声明:本文所引用的各种资料均用于自己学习使用,这里感谢正点原子和野火官方的资料以及各位优秀的创作者。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。