OV5640模组架构
该模组最大支持2592x1944尺寸的图像输出,这里注意以下信号即可
XVCLK:输出时钟,该时钟输入后可以通过PLL分频/倍频后提供给模组各个功能子模块。
PWDN:掉电使能信号,正常工作时应保持为低电平
PCLK:随像素同步输出的像素时钟
HREF:随像素同步输出的行数据有效信号(参考VGA时序介绍)
VSYNC:场同步信号
SIOC:SCCB信号时钟
SIOD:SCCB信号数据
D[9:0]:DVP数据 输出
MCP/N:MIPI时钟
MDP/N[1:0]:MIPI 数据输出
OV5640模组原理图
D[9:0](D9:MSB、D0:LSB)是传感器RGBRAW10位输出。D[9:2](D9:MSB、D2:LSB)为8位输出。
MCP/MCN:MIPI差分时钟输出
MDP0/MDN0:第一路数据
MDP1/MDN1:第二路数据
通过上述原理图,DVP和MIPI输出功能是共用一些引脚的,所以只能选择一种作为数据输出,输出类型可以通过SCCB总线配置摄像头寄存器(0x300e寄存器)来进行控制的。
SCCB总线实际上就是IIC的裁剪版本,可以参考接口协议学习(三):SCCB(与I2C比较)_sccb i2c-CSDN博客
ATK-MC5640 V1.2模块
该模块采用 OmniVision 公司的 OV5640 摄像头传感器作为核心,OV5640 是一颗 1/4 英寸 CMOS QSXGA (2592*1944)的图像传感器。
ATK-MC5640 模块的原理图如下:

ATK-MC5640 模块自带了有源晶振,用于产生 24MHz 的时钟作为 OV5640 传感器的 XCLK 输入,模块的闪光灯(LED1 和 LED2)可由 OV5640 的 STROBE 脚控制(可编程控制)或外部引脚控制。ATK-MC5640 模块通过一个 2*9 的排针(P1)同外部电路连接,各引脚的详细描述, 如下表所示:
正点原子给的模组输出数据部分只接了D[9:2],DVP输出RAW的时候会有精度损失。
摄像头配置
摄像头的通用配置总结大致包括以下:
输出尺寸配置、输出格式配置、时钟相关配置、使能配置、其他功能配置
输出尺寸配置
OV5640图像传感器的窗口描述如下图所示:

与图像传感器的窗口配置寄存器如上图,我们要配置成输出2592x1944,physical pixel size的尺寸为2624x1952,配置X_ADDR_ST和Y_ADDR_ST为都为0,X_OFFSET为16,Y_OFFSET为8,得到的pre-scaling size为2592x1944(2592=2624-16x2,1944=1952-8x2),data output size上设置成与pre-scaling size一样,当数据输出窗口的宽高比例与预缩放窗口的宽高比例不一致时,输出的图像数据会变形,只有当两者比例一致时,输出图像的尺寸才不会变形。
///都配置为0表示开窗起始为X和Y都为0
sccb_write_reg16(0x3800, 0x00); //X_ADDR_ST高字节[11:8]
sccb_write_reg16(0x3801, 0x00); //X_ADDR_ST低字节
sccb_write_reg16(0x3802, 0x00); //Y_ADDR_ST高字节[10:8]
sccb_write_reg16(0x3803, 0x00); //Y_ADDR_ST低字节
//X_ADDR_END和Y_ADDR_END
sccb_write_reg16(0x3804, 0x0a);
sccb_write_reg16(0x3805, 0x3f); //0x0a3f=2623 ,0~2623
sccb_write_reg16(0x3806, 0x07);
sccb_write_reg16(0x3807, 0x9f); //0x079f=1951 ,0~1951
//配置输出尺寸为2592x1944
sccb_write_reg16(0x3808, 0x0a); //DVP 输出水平像素点数高4位
sccb_write_reg16(0x3809, 0x20); //DVP 输出水平像素点数低8位 0x0a20=2592
sccb_write_reg16(0x380a, 0x07); //DVP 输出垂直像素点数高3位
sccb_write_reg16(0x380b, 0x98); //DVP 输出垂直像素点数低8位 0x0798=1944
sccb_write_reg16(0x380c, 0x0b); //水平总像素大小高5位
sccb_write_reg16(0x380d, 0x1c); //水平总像素大小低8位 HTS 0x0b1c=2844
sccb_write_reg16(0x380e, 0x07); //垂直总像素大小高5位
sccb_write_reg16(0x380f, 0xb0); //垂直总像素大小低8位 VTS 0x07b0=1968
sccb_write_reg16(0x3810, 0x00);
sccb_write_reg16(0x3811, 0x10); //X_OFFSET 0x0010=16 ,2624-16x2=2592
sccb_write_reg16(0x3812, 0x00);
sccb_write_reg16(0x3813, 0x04); //Y_OFFSET 0x0004=4 ,1952-8x2 =1944 输出窗口的宽高比例与预缩放窗口宽高比例一致(1:1),不会变形
代码中需要注意的是HTS(H-Total)和VTS(V-Total)寄存器,也就是除了有效数据(HREF有效)外的一些空白地方。帧率FPS = PCLK / (VTS * HTS )
输出格式配置
OV5640支持多种输出格式,如RawRGB、RGB565、RGB555、RGB444、CCIR656、YUV422、YUV420、YCbCr422 和压缩图像(JPEG)输出格式。甚至RAW的格式(RGGB、GBRG、GRBG、BGGR)也可以通过formattter module进行设置。输出格式的主要使用的寄存器为FORMAT CONTROL00(0x4300)寄存器。该寄存器的bit[7:4]设置从formatter module输出的格式,bit[3:0]设置该格式下像素的顺序。
实际上,直接Bypass formatter module,然后直接输出RAW即可,因此该寄存器的配置如下:
sccb_write_reg16(0x4300, 0xf8);
时钟相关配置
时钟配置可参考:OV5640 PCLK计算方法_ov5640的pclk-CSDN博客
OV5640内部PLL的时钟树如下所示,XVCLK为24MHz输入时钟,项目中PCLK需要配置成96MHz【96M/(2844x1968) = 17左右】,因此这样配置实际输出的RAW图像帧率是17 FPS
根据以上时钟树,96MHz时钟生成过程如下:
1、24M/3=8M (0x3037[3:0]=3)
2、8Mx120=960M (0x3037[7]=0 && 0x3036[6:0]=120 )
3、960M/1=960M (0x3035[7:4]=1)
4、960M/2=480M (0x3037[4]=1)
5、480M/2.5=192M (0x3034[3:0]=a)
6、192M/1=192M (0x3108[5:4]=0)
7、192/(1x2)=96M (0x3035[3:0]=1 && DVP) 即为PCLK
这里有个DIV_PCLK不知道干啥的
sccb_write_reg16(0x3008, 0x42); //取消软件复位
sccb_write_reg16(0x3103, 0x03); //时钟从PLL获取
//分频参考:https://blog.csdn.net/wolfhunterhu/article/details/135264200
// 24M/3=8M (0x3037[3:0]=3)
// 8Mx120=960M (0x3037[7]=0 && 0x3036[6:0]=120 )
// 960M/1=960M (0x3035[7:4]=1)
// 960M/2=480M (0x3037[4]=1)
// 480M/2.5=192M (0x3034[3:0]=a)
// 192M/1=192M (0x3108[5:4]=0)
// 192/(1x2)=96M (0x3035[3:0]=1 && DVP) 即为PCLK
sccb_write_reg16(0x3034, 0x1a);
//系统时钟分频 Bit[7:4]:系统时钟分频 input clock =24Mhz, PCLK = 96Mhz
sccb_write_reg16(0x3035,0x11);
// sccb_write_reg16(0x3036,0x3c); //PLL倍频 //48M
// sccb_write_reg16(0x3036, 0x5A); //PLL倍频 //72M
sccb_write_reg16(0x3036, 0x78); //PLL倍频 //96M即PCLK
//后续试一试更高频率的下高速时钟
sccb_write_reg16(0x3037, 0x13); //PLL分频控制
sccb_write_reg16(0x3108, 0x01); //系统根分频器
使能配置
配置0x3017和0x3018寄存器,对应位置1使能时序信号和数据信号的输出
sccb_write_reg16(0x3017, 0xff);
sccb_write_reg16(0x3018, 0xff);
由于需要输出RAW原始图,因此对于OV5640内部对于图像操作的模块进行Disable以保证输出的RAW图是直接从图像传感器输出的且未经任何处理。
sccb_write_reg16(0x5000, 0x00); //ISP CONTROL00 ,不使能相关算法
sccb_write_reg16(0x5001, 0x00); //ISP CONTROL01 ,同样不使能算法
其他功能配置
其他配置如AEC曝光相关的寄存器配置、AGC模拟增益相关的配置,这与自动曝光算法相关,后续在讲解自动曝光算法时统一介绍。还有一些寄存器配置手册里没提到,先保持默认配置。
总的配置代码如下:
sccb_write_reg16(0x3008, 0x42); //取消软件复位
sccb_write_reg16(0x3103, 0x03); //时钟从PLL获取
//使能FREX、VSYNC、HREF、PCLK、D[9:0]、GPIO0/GPIO1输出
sccb_write_reg16(0x3017, 0xff);
sccb_write_reg16(0x3018, 0xff);
// 24M/3=8M (0x3037[3:0]=3)
// 8Mx120=960M (0x3037[7]=0 && 0x3036[6:0]=120 )
// 960M/1=960M (0x3035[7:4]=1)
// 960M/2=480M (0x3037[4]=1)
// 480M/2.5=192M (0x3034[3:0]=a)
// 192M/1=192M (0x3108[5:4]=0)
// 192/(1x2)=96M (0x3035[3:0]=1 && DVP) 即为PCLK
sccb_write_reg16(0x3034, 0x1a);
//系统时钟分频 Bit[7:4]:系统时钟分频 input clock =24Mhz, PCLK = 96Mhz
sccb_write_reg16(0x3035,0x11);
// sccb_write_reg16(0x3036,0x3c); //PLL倍频 //48M
// sccb_write_reg16(0x3036, 0x5A); //PLL倍频 //72M
sccb_write_reg16(0x3036, 0x78); //PLL倍频 //96M即PCLK
//后续试一试更高频率的下高速时钟
sccb_write_reg16(0x3037, 0x13); //PLL分频控制
sccb_write_reg16(0x3108, 0x01); //系统根分频器
sccb_write_reg16(0x3630, 0x36);
sccb_write_reg16(0x3631, 0x0e);
sccb_write_reg16(0x3632, 0xe2);
sccb_write_reg16(0x3633, 0x12);
sccb_write_reg16(0x3621, 0xe0);
sccb_write_reg16(0x3704, 0xa0);
sccb_write_reg16(0x3703, 0x5a);
sccb_write_reg16(0x3715, 0x78);
sccb_write_reg16(0x3717, 0x01);
sccb_write_reg16(0x370b, 0x60);
sccb_write_reg16(0x3705, 0x1a);
sccb_write_reg16(0x3905, 0x02);
sccb_write_reg16(0x3906, 0x10);
sccb_write_reg16(0x3901, 0x0a);
sccb_write_reg16(0x3731, 0x12);
sccb_write_reg16(0x3600, 0x08);
sccb_write_reg16(0x3601, 0x33);
sccb_write_reg16(0x302d, 0x60);
sccb_write_reg16(0x3620, 0x52);
sccb_write_reg16(0x371b, 0x20);
sccb_write_reg16(0x471c, 0x50);
sccb_write_reg16(0x3a13, 0x43); //AEC CTRL13 Bit[6]:pre-gain enable Bit[5:0]:pre-gain=3
sccb_write_reg16(0x3a18, 0x00); //AEC GAIN CEILING[9:8]
sccb_write_reg16(0x3a19, 0xf8); //AEC GAIN CEILING[7:0]
sccb_write_reg16(0x3635, 0x13);
sccb_write_reg16(0x3636, 0x03);
sccb_write_reg16(0x3634, 0x40);
sccb_write_reg16(0x3622, 0x01);
sccb_write_reg16(0x3c01, 0x34); // (50/60HZ detect) 5060HZ CTRL01
sccb_write_reg16(0x3c04, 0x28); // 5060HZ CTRL04
sccb_write_reg16(0x3c05, 0x98); // 5060HZ CTRL05
sccb_write_reg16(0x3c06, 0x00); // LIGHT METER1 THRESHOLD[15:8]
sccb_write_reg16(0x3c07, 0x08); // LIGHT METER1 THRESHOLD[7:0]
sccb_write_reg16(0x3c08, 0x00); // LIGHT METER2 THRESHOLD[15:8]
sccb_write_reg16(0x3c09, 0x1c); // LIGHT METER2 THRESHOLD[7:0]
sccb_write_reg16(0x3c0a, 0x9c); // SAMPLE NUMBER[15:8]
sccb_write_reg16(0x3c0b, 0x40); // SAMPLE NUMBER[7:0]
sccb_write_reg16(0x3820, 0x46); // ISP vflip和Sensor vflip
sccb_write_reg16(0x3821, 0x00); // JPEG mirror H-binning相关
///都配置为0表示开窗起始为X和Y都为0
sccb_write_reg16(0x3800, 0x00); //X_ADDR_ST高字节[11:8]
sccb_write_reg16(0x3801, 0x00); //X_ADDR_ST低字节
sccb_write_reg16(0x3802, 0x00); //Y_ADDR_ST高字节[10:8]
sccb_write_reg16(0x3803, 0x00); //Y_ADDR_ST低字节
//X_ADDR_END和Y_ADDR_END
sccb_write_reg16(0x3804, 0x0a);
sccb_write_reg16(0x3805, 0x3f); //0x0a3f=2623 ,0~2623
sccb_write_reg16(0x3806, 0x07);
sccb_write_reg16(0x3807, 0x9f); //0x079f=1951 ,0~1951
//配置输出尺寸为2592x1944
sccb_write_reg16(0x3808, 0x0a); //DVP 输出水平像素点数高4位
sccb_write_reg16(0x3809, 0x20); //DVP 输出水平像素点数低8位 0x0a20=2592
sccb_write_reg16(0x380a, 0x07); //DVP 输出垂直像素点数高3位
sccb_write_reg16(0x380b, 0x98); //DVP 输出垂直像素点数低8位 0x0798=1944
sccb_write_reg16(0x380c, 0x0b); //水平总像素大小高5位
sccb_write_reg16(0x380d, 0x1c); //水平总像素大小低8位 HTS 0x0b1c=2844
sccb_write_reg16(0x380e, 0x07); //垂直总像素大小高5位
sccb_write_reg16(0x380f, 0xb0); //垂直总像素大小低8位 VTS 0x07b0=1968
sccb_write_reg16(0x3810, 0x00);
sccb_write_reg16(0x3811, 0x10); //X_OFFSET 0x0010=16 ,2624-16x2=2592
sccb_write_reg16(0x3812, 0x00);
sccb_write_reg16(0x3813, 0x04); //Y_OFFSET 0x0004=4 ,1952-8x2 =1944 输出窗口的宽高比例与预缩放窗口宽高比例一致(1:1),不会变形
sccb_write_reg16(0x3814, 0x11);
sccb_write_reg16(0x3815, 0x11);
sccb_write_reg16(0x3618, 0x00);
sccb_write_reg16(0x3612, 0x29);
sccb_write_reg16(0x3708, 0x64);
sccb_write_reg16(0x3709, 0x52);
sccb_write_reg16(0x370c, 0x03);
sccb_write_reg16(0x3a02, 0x03); //禁用了夜间模式
sccb_write_reg16(0x3a03, 0xd8);
sccb_write_reg16(0x3a08, 0x01); //AEC B50 STEP[9:8]
sccb_write_reg16(0x3a09, 0x27); //AEC B50 STEP[7:0]
sccb_write_reg16(0x3a0a, 0x00); //AEC B60 STEP[9:8]
sccb_write_reg16(0x3a0b, 0xf6); //AEC B60 STEP[7:0]
sccb_write_reg16(0x3a0e, 0x03); //AEC CTRL0E
sccb_write_reg16(0x3a0d, 0x04); //AEC CTRL0D
sccb_write_reg16(0x3a14, 0x03); //AEC MAX EXPO(50Hz) [15:8]
sccb_write_reg16(0x3a15, 0xd8); //AEC MAX EXPO(50Hz) [7:0]
sccb_write_reg16(0x4001, 0x02); //BLC CTRL01(BLC start line)
sccb_write_reg16(0x4004, 0x02); //BLC CTRL04
sccb_write_reg16(0x3000, 0x00); //SYSTEM RESET00 复位相关模块
sccb_write_reg16(0x3002, 0x1c); //SYSTEM RESET02
sccb_write_reg16(0x3004, 0xff); //CLOCK ENABLE00
sccb_write_reg16(0x3006, 0xc3); //CLOCK ENABLE02
sccb_write_reg16(0x300e, 0x58); //MIPI CONTROL00 Bit[2]:mipi_en 在该处配置成了dvp模式
sccb_write_reg16(0x302e, 0x00);
sccb_write_reg16(0x4300, 0xf8); //Format Control00 Raw
sccb_write_reg16(0x501f, 0x03); //FORMAT MUX CONTROL :ISP RAW(DPC)
sccb_write_reg16(0x4713, 0x03); //JPEG MODE SELECT
sccb_write_reg16(0x4407, 0x04); //JPEG CTRL07
sccb_write_reg16(0x440e, 0x00);
sccb_write_reg16(0x460b, 0x37);
sccb_write_reg16(0x460c, 0x20); // VIFIFO CTRL0C
sccb_write_reg16(0x4837, 0x22); // DVP CLK divider
sccb_write_reg16(0x3824, 0x02); // DVP CLK divider
sccb_write_reg16(0x5000, 0x00); //ISP CONTROL00 ,不使能相关算法
sccb_write_reg16(0x5001, 0x00); //ISP CONTROL01 ,同样不使能算法
//AEC使用寄存器(0x3A0F)、(0x3A10)、(0x3A1B)和(0x3A1E)来控制图像亮度,目标亮度AVG(0x56A1)
sccb_write_reg16(0x3a0f, 0x36); //高阈值
sccb_write_reg16(0x3a10, 0x2e); //低阈值
sccb_write_reg16(0x3a1b, 0x38); //从稳定状态变为不稳定状态的高阈值 ,图像亮度平均值应该保持在这个范围内
sccb_write_reg16(0x3a1e, 0x2c); //从稳定状态变为不稳定状态的低阈值
//寄存器(0x3A11)和寄存器(0x3A1F)在手动速度选择中控制快速AEC范围。如果目标图像AVG读出(0x56A1)大于(0x3A11),则AEC将减少一半。如果寄存器AVG读数(0x56A1)小于(0x3A1F),则AEC将翻倍。
sccb_write_reg16(0x3a11, 0x70);
sccb_write_reg16(0x3a1f, 0x18);
sccb_write_reg16(0x3008, 0x02); //software power down/software reset
sccb_write_reg16(0x3400, 0x04); //AWB R GAIN[11:8]
sccb_write_reg16(0x3401, 0x00); //AWB R GAIN[7:0]
sccb_write_reg16(0x3402, 0x04); //AWB G GAIN[11:8]
sccb_write_reg16(0x3403, 0x00); //AWB G GAIN[7:0]
sccb_write_reg16(0x3404, 0x04); //AWB B GAIN[11:8]
sccb_write_reg16(0x3405, 0x00); //AWB B GAIN[7:0]
sccb_write_reg16(0x3406, 0x01); //AWB MANUAL CONTROL :Manual
sccb_write_reg16(0x4000, 0x88); //BLC CTRL00 没使能
sccb_write_reg16(0x3503, 0x03); //AEC PK MANUAL :AEC/AGC manual enable
unsigned int cmos_exposure = 0x300;
unsigned int cmos_gain = 0xa0;
//AEC manual
sccb_write_reg16(0x3500, 0x00);// Exposure [19:16]
sccb_write_reg16(0x3501, (cmos_exposure>>4)&0x3f);// Exposure [15:8]
sccb_write_reg16(0x3502, (cmos_exposure&0x0f)<<4);// Exposure [7:0]
//AGC manual
sccb_write_reg16(0x350a, (cmos_gain>>8)&0x3); // Real gain[9:8]
sccb_write_reg16(0x350b, cmos_gain&0x0ff); // Real gain[7:0]
参考
blog.csdn.net/baidu_38797690/article/details/125292046
720P MIPI配置:OV5640_MIPI_1LEN调试记录_ov5640 mipi-CSDN博客