📄 ov7670.c
字号:
/*******************************************************************************
* Copyright (C) 2012 All Rights Reserved
*
* 软件作者: 骑飞家族
* 版权所有: 骑飞电子
* 创建日期: 2010年6月10日
* 软件历史: 2010年11月2日修改
2012年09月10日修改
* Version: 3.0
* Demo 淘宝地址:http://qifeidz.taobao.com
**********************************************************************************************************************************************
**********************************************************************************************************************************************/
#include "OV7670.h"
#include "delay.h"
#include "stm32f10x_lib.h"
// GND PIN1
// HREF PC8 PIN2 PC8
// VSYNC PIN3 PC11
// PWDN GND PIN4
// PCLK PC9 PIN5 没有用到 PC(
// AVDD 2.8V PIN6
// DVDD 2.8V PIN7
// SIOD PA6 PIN8
// XCLK1 PA8 PIN9
// SIOC PA7 PIN10
// D0 PC0 PIN11
// D1 PC1 PIN12
// D2 PC2 PIN13
// D3 PC3 PIN14
// GND PIN15
// D4 PC4 PIN16
// D5 PC5 PIN17
// D6 PC6 PIN18
// D7 PC7 PIN19
// RST GND PIN20
//extern const char change_reg[CHANGE_REG_NUM][2];
////////////////////////////
//功能:提供7670时钟
//返回:无
void CLK_init_ON(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP ;
GPIO_Init(GPIOA, &GPIO_InitStructure);
RCC_MCOConfig(RCC_MCO_HSE );//hsi
}
void CLK_init_OFF(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOA, &GPIO_InitStructure);
}
void OV7670_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
/* Enable GPIOC clock */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);
GPIO_InitStructure.GPIO_Pin = 0X0BFF;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;//GPIO_Mode_AF_OD GPIO_Mode_AF_PP GPIO_Mode_IPU GPIO_Mode_IN_FLOATING
//GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOC, &GPIO_InitStructure);
}
void OV7670_GPIO_CONTRL_CONFIG(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
GPIO_InitStructure.GPIO_Pin = LCD_HREF_BIT|LCD_VSYNC_BIT|LCD_PCLK_BIT;
//GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOC, &GPIO_InitStructure);
RCC_MCOConfig(RCC_MCO_HSE );//hsi
}
////////////////////////////
//功能:写OV7670寄存器
//返回:1-成功 0-失败
unsigned char wrOV7670Reg(unsigned char regID, unsigned char regDat)
{
startSCCB();
if(0==SCCBwriteByte(0x42))
{
stopSCCB();
return(0);
}
delay_us(100);
if(0==SCCBwriteByte(regID))
{
stopSCCB();
return(0);
}
delay_us(100);
if(0==SCCBwriteByte(regDat))
{
stopSCCB();
return(0);
}
stopSCCB();
return(1);
}
////////////////////////////
//功能:读OV7670寄存器
//返回:1-成功 0-失败
unsigned char rdOV7670Reg(unsigned char regID, unsigned char *regDat)
{
//通过写操作设置寄存器地址
startSCCB();
if(0==SCCBwriteByte(0x42))
{
stopSCCB();
return(0);
}
delay_us(100);
if(0==SCCBwriteByte(regID))
{
stopSCCB();
return(0);
}
stopSCCB();
delay_us(100);
//设置寄存器地址后,才是读
startSCCB();
if(0==SCCBwriteByte(0x43))
{
stopSCCB();
return(0);
}
delay_us(100);
*regDat=SCCBreadByte();
noAck();
stopSCCB();
return(1);
}
//(140,16,640,480) is good for VGA
//(272,16,320,240) is good for QVGA
/* config_OV7670_window */
void OV7670_config_window(unsigned int startx,unsigned int starty,unsigned int width, unsigned int height)
{
unsigned int endx;
unsigned int endy;// "v*2"必须
unsigned char temp_reg1, temp_reg2;
unsigned char temp=0;
endx=(startx+width);
endy=(starty+height+height);// "v*2"必须
rdOV7670Reg(0x03, &temp_reg1 );
temp_reg1 &= 0xf0;
rdOV7670Reg(0x32, &temp_reg2 );
temp_reg2 &= 0xc0;
// Horizontal
temp = temp_reg2|((endx&0x7)<<3)|(startx&0x7);
wrOV7670Reg(0x32, temp );
temp = (startx&0x7F8)>>3;
wrOV7670Reg(0x17, temp );
temp = (endx&0x7F8)>>3;
wrOV7670Reg(0x18, temp );
// Vertical
temp =temp_reg1|((endy&0x3)<<2)|(starty&0x3);
wrOV7670Reg(0x03, temp );
temp = starty>>2;
wrOV7670Reg(0x19, temp );
temp = endy>>2;
wrOV7670Reg(0x1A, temp );
}
set_OV7670reg(void)
{
//wrOV7670Reg(0x8c, 0x00); //写RGB444寄存器 RGB444非使能 xRGB
wrOV7670Reg(0x3a, 0x04); //TSLB 行缓冲器测试选项 使用通用UV输出 输出顺序 YUYV 当分辨率改变时传感器不会自动设置窗口,后端处理器能够自动调整窗口
wrOV7670Reg(0x40, 0xd0); //COM15 数据输出范围(00-ff) RGB565
wrOV7670Reg(0x8c, 0x00);
wrOV7670Reg(0x12, 0x14); //COM7 SCCB不复位 输出格式QVGA RGB输出
wrOV7670Reg(0x32, 0x80); //HREF控制 HREF沿距离数据输出的偏移为10 HREF(行频率)开始的低三位及结束的低三位都为0
wrOV7670Reg(0x17, 0x16); //行频开始的高8位 wrOV7670Reg(0x18, 0x04); //行频结束的高8位
wrOV7670Reg(0x19, 0x02); //场频开始的高8位
wrOV7670Reg(0x1a, 0x7b); //场频结束的高8位
wrOV7670Reg(0x03, 0x06); //场频开始的低2位及结束的低两位
wrOV7670Reg(0x0c, 0x04); //COM3 输出数据高位与地位不交换 在省电模式下输出时钟为3态 缩放禁止 数据控制字使能
wrOV7670Reg(0x3e, 0x00); // 复位值 正常PCLK(即不分频) 缩放参数不能手动调节
wrOV7670Reg(0x70, 0x3a); //复位值 无测试图案输出 水平缩放系数为0x3a
wrOV7670Reg(0x71, 0x35); // 复位值 ............. 垂直缩放系数为0x35
wrOV7670Reg(0x72, 0x11); // 复位值 DCW控制 垂直均值舍去 垂直 down samping 舍去 垂直down samping率为2采一 水平同垂直
wrOV7670Reg(0x73, 0x00); //复位值 旁路dsp缩放时钟使能 dsp缩放时钟分频控制无效
wrOV7670Reg(0xa2, 0x00); //缩放输出延时
wrOV7670Reg(0x11, 0xff); //直接使用外部时钟(没有预分频)内部时钟分频 内部时钟=输入时钟/位(【5:0】+1) 为64KHZ
//wrOV7670Reg(0x15 , 0x31);//复位值 HREF不转变为HSYNC PCLK 连续输出 PLK不反相 HREF不反相 VSYC在PCLK下降沿改变VSNC 及HSYNC负有效
wrOV7670Reg(0x7a, 0x20); //SLOP 伽玛曲线最高段斜率 斜率(SLOP【7:0】)=(0x100-GAM15【7:0】)*4/3
wrOV7670Reg(0x7b, 0x1c); //伽玛曲线1节输入结束点0x04输出值
wrOV7670Reg(0x7c, 0x28); //.......2............0x08......
wrOV7670Reg(0x7d, 0x3c); //.......3...........0x10.....
wrOV7670Reg(0x7e, 0x55); //.......4...........0x20......
wrOV7670Reg(0x7f, 0x68); //.......5...........0x28......
wrOV7670Reg(0x80, 0x76); //.......6...........0x30......
wrOV7670Reg(0x81, 0x80); //.......7...........0x38......
wrOV7670Reg(0x82, 0x88); //.......8...........0x40......
wrOV7670Reg(0x83, 0x8f); //.......9...........0x48......
wrOV7670Reg(0x84, 0x96); //.......10...........0x50......
wrOV7670Reg(0x85, 0xa3); //.......11...........0x60......
wrOV7670Reg(0x86, 0xaf); //.......12...........0x70......
wrOV7670Reg(0x87, 0xc4); //.......13...........0x90......
wrOV7670Reg(0x88, 0xd7); //.......14...........0xb0......
wrOV7670Reg(0x89, 0xe8); //伽玛曲线15节输入结束点0xd0输出值
wrOV7670Reg(0x32,0xb6); //HREF控制 HREF沿距离数据输出的偏移 【7:6】 HREF(行频率)开始的低三位及结束的低三位都为110
wrOV7670Reg(0x13, 0xff); //使能AGC/AEC算法 AEC不限制步长 条纹滤波器开 AGC,AWB,AEC使能
wrOV7670Reg(0x00, 0x00); //AGC(自动增益控制) 由0x00【7:0】及0x03寄存器【7:6】(高两位)
wrOV7670Reg(0x10, 0x00); //AEC (曝光值)由寄存器 07的【5:0】表示AEC的[15:10] 寄存器10的【7:0】表示AEC【9:2】由寄存器0x04的【1:0】表示AEC的低两位
wrOV7670Reg(0x0d, 0x00); //AEC的窗口选择 全窗口
wrOV7670Reg(0x14, 0x4e); //最大AGC值 32*AGC 不是固定的AGC/AEC
wrOV7670Reg(0xa5, 0x05); //50Hz条纹滤波器步长限制
wrOV7670Reg(0xab, 0x07); //60Hz滤波器步长限制
wrOV7670Reg(0x24, 0x75); //AGC/AEC稳定运行区域(上限)
wrOV7670Reg(0x25, 0x63); //AGC/AEC稳定运行区域(下限)
wrOV7670Reg(0x26, 0xA5); //AGC/AEC快速稳定运行 【7:4】上限 【3:0】下限
wrOV7670Reg(0x9f, 0x78); //基于直方图的AGC/AEC控制1
wrOV7670Reg(0xa0, 0x68); //基于直方图的AGC/AEC控制2
// wrOV7670Reg(0xa1, 0x03);//0x0b,
wrOV7670Reg(0xa6, 0xdf); ////基于直方图的AGC/AEC控制3
wrOV7670Reg(0xa7, 0xdf); //基于直方图的AGC/AEC控制4
wrOV7670Reg(0xa8, 0xf0); //基于直方图的AGC/AEC控制5
wrOV7670Reg(0xa9, 0x90); //基于直方图的AGC/AEC控制6
wrOV7670Reg(0xaa, 0x94); //AEC公式选择 基于直方图的AEC算法
//wrOV7670Reg(0x13, 0xe5);
wrOV7670Reg(0x0e, 0x61); //通用控制5 保留
wrOV7670Reg(0x0f, 0x43); //在光学黒行输出时禁止HREF 当格式变化时复位所有时序
wrOV7670Reg(0x16, 0x02); //RSVD 保留
wrOV7670Reg(0x1e, 0x37); // 水平翻转不使能 竖直翻转不使能 (black sun 使能 )
wrOV7670Reg(0x21, 0x02); //保留
wrOV7670Reg(0x22, 0x91); //保留
wrOV7670Reg(0x29, 0x07); //保留
wrOV7670Reg(0x33, 0x0b); //感光阵列电流控制
wrOV7670Reg(0x35, 0x0b); //保留
wrOV7670Reg(0x37, 0x3f); //ADC控制
wrOV7670Reg(0x38, 0x01); //ADC和模拟共模控制
wrOV7670Reg(0x39, 0x00); //ADC偏移控制
wrOV7670Reg(0x3c, 0x78); //在VSYNC为底时没有HREF
wrOV7670Reg(0x4d, 0x40); //保留
wrOV7670Reg(0x4e, 0x20); //保留
wrOV7670Reg(0x69, 0x00); //Gr,Gb,R,B通道的固定增益值为1*AEC
wrOV7670Reg(0x6b, 0x4a); // 输入时钟*4 校准器控制 使能内部校准器
wrOV7670Reg(0x74, 0x19); //选择VREF【7:6】(即0x03寄存器)为控制数字增益
wrOV7670Reg(0x8d, 0x4f); // 保留
wrOV7670Reg(0x8e, 0x00); // 保留
wrOV7670Reg(0x8f, 0x00); //保留
wrOV7670Reg(0x90, 0x00); //保留
wrOV7670Reg(0x91, 0x00); //保留
wrOV7670Reg(0x92, 0x00); //空行低8位
wrOV7670Reg(0x96, 0x00); //保留
wrOV7670Reg(0x9a, 0x80); //保留
wrOV7670Reg(0xb0, 0x84); //保留
wrOV7670Reg(0xb1, 0x0c); //自动黑电平校准禁使能
wrOV7670Reg(0xb2, 0x0e); //保留
wrOV7670Reg(0xb3, 0x82); //自动黑电平矫正目标值
wrOV7670Reg(0xb8, 0x0a); //保留
wrOV7670Reg(0x43, 0x14); //保留
wrOV7670Reg(0x44, 0xf0); //保留
wrOV7670Reg(0x45, 0x34);
wrOV7670Reg(0x46, 0x58);
wrOV7670Reg(0x47, 0x28);
wrOV7670Reg(0x48, 0x3a); //保留
wrOV7670Reg(0x59, 0x88); //AWB控制(59-61 )
wrOV7670Reg(0x5a, 0x88);
wrOV7670Reg(0x5b, 0x44);
wrOV7670Reg(0x5c, 0x67);
wrOV7670Reg(0x5d, 0x49);
wrOV7670Reg(0x5e, 0x0e);
wrOV7670Reg(0x64, 0x04); //镜头补偿选项3 G通道补偿系数
wrOV7670Reg(0x65, 0x20); //镜头补偿选项4 避免补偿半径
wrOV7670Reg(0x66, 0x05); //RGB镜头补偿系数由寄存器0x64(G) )0x94(R)0x95(B)
wrOV7670Reg(0x94, 0x04); //R通道补偿系数
wrOV7670Reg(0x95, 0x08); //B通道补偿系数
wrOV7670Reg(0x6c, 0x0a); // AWB控制3
wrOV7670Reg(0x6d, 0x55); //AWB控制2
wrOV7670Reg(0x6e, 0x11); //AWB控制1
wrOV7670Reg(0x6f, 0x9f); //AWB控制0
wrOV7670Reg(0x6a, 0x40); //G通道AWB增益
wrOV7670Reg(0x01, 0x40); //B通道AWB增益
wrOV7670Reg(0x02, 0x40); //r通道AWB增益
//wrOV7670Reg(0x13, 0xe7);
wrOV7670Reg(0x15, 0x00); // /复位值 HREF不转变为HSYNC PCLK 连续输出 PLK不反相 HREF不反相 VSYC在PCLK下降沿改变VSNC 及HSYNC正有效
wrOV7670Reg(0x4f, 0x80); //色彩矩阵系数1
wrOV7670Reg(0x50, 0x80); //色彩矩阵系数2
wrOV7670Reg(0x51, 0x00); //色彩矩阵系数3
wrOV7670Reg(0x52, 0x22); //色彩矩阵系数4
wrOV7670Reg(0x53, 0x5e); //色彩矩阵系数5
wrOV7670Reg(0x54, 0x80); //色彩矩阵系数6
wrOV7670Reg(0x58, 0x9e); //色彩矩阵系数5-0 对比度中心使能 寄存器0x57自动更新
wrOV7670Reg(0x41, 0x08); //针对YUV边缘增强阀值自动调整禁止 AWB(白平衡)增益使能
wrOV7670Reg(0x3f, 0x00); //边缘增强调整【4:0】边缘增强系数
wrOV7670Reg(0x75, 0x05); //边缘增强下限【4:0】
wrOV7670Reg(0x76, 0xe1); //黑点纠正使能 白点纠正使能 边缘增强上限【4:0】
wrOV7670Reg(0x4c, 0x00); //噪声抑制强度
wrOV7670Reg(0x77, 0x01); //噪声去除偏移
wrOV7670Reg(0x3d, 0xc1); //Camma使能 uv饱和度自动调整,结果存入寄存器0xc9的【3:】uv不交换位置
wrOV7670Reg(0x4b, 0x09); //uv平均使能
wrOV7670Reg(0xc9, 0x60); //饱和度控制【7:4】饱和度控制最小值【3:0】饱和度控制结果
//wrOV7670Reg(0x41, 0x38);
wrOV7670Reg(0x56, 0x40); //对比度控制 复位值
wrOV7670Reg(0x34, 0x11); //感光阵列参考电压控制 复位值
wrOV7670Reg(0x3b, 0x02); //禁止夜晚模式 失能50/60Hz自动侦测 选择BD60ST作为条纹滤波值 曝光时间可以小于条纹滤波器限制
wrOV7670Reg(0xa4, 0x89); //帧率减半 在4*增益插入空行
wrOV7670Reg(0x96, 0x00); //保留
wrOV7670Reg(0x97, 0x30);
wrOV7670Reg(0x98, 0x20);
wrOV7670Reg(0x99, 0x30);
wrOV7670Reg(0x9a, 0x84);
wrOV7670Reg(0x9b, 0x29);
wrOV7670Reg(0x9c, 0x03); //保留
wrOV7670Reg(0x9d, 0x4c); //50hz条纹滤波器的值
wrOV7670Reg(0x9e, 0x3f); //60hz条纹滤波器的值
wrOV7670Reg(0x09, 0x00); //输出驱动能力1*
wrOV7670Reg(0x3b, 0xc2); //失能夜晚模式1/4普通帧率 失能50/60Hz自动侦测 选择BD60ST作为条纹滤波值 曝光时间可以小于条纹滤波器限制
}/* OV7670_init() */
//返回1成功,返回0失败
unsigned char OV7670_init(void)
{
unsigned char temp;
// unsigned int i=0;
OV7670_GPIO_Init();
OV7670_GPIO_CONTRL_CONFIG();
SCCB_GPIO_Config(); // io init..
CLK_init_ON();
temp=0x80;
if(0==wrOV7670Reg(0x12, temp)) //Reset SCCB
{
return 0 ;
}
delay_ms(100);
set_OV7670reg();
OV7670_config_window(272,12,320,240);// set 240*320
return 0x01; //ok
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -