基于STM32F1系列的OV7725摄像头初步使用(用于摄像头循迹)

最近做项目需要用到OV7725,于是花了些时间研究。由于OV7725对于工作频率的要求较高,因此使用带FIFO的摄像头模块。代码参考自正点原子官方。

OV7725资源

引脚说明

以下时关于十八个引脚的说明(来自正点原子的用户手册)
在这里插入图片描述
其中,OV_SCL和OV_SDA组成SCCB,即串行摄像头控制总线,它的通信机制类似于IIC,有使用过IIC总线的较容易理解。OV_VSYNC为帧同步信号,该引脚产生信号时,意味着一帧数据传输完成后,下一帧数据传输即将开始(这里,从OV7725传输至FIFO)。FIFO_D[7:0] 是FIFO的数据引脚,用于数据传输。当发生帧同步信号时,复位FIFO_WRST写指针信号,使能FIFO_WEN写使能信号,则OV7725开始往FIFO写数据,并置位帧中断标志位(该标志位在读数据完成后被清零),保证FIFO的数据被读取完成之前不会被覆盖,具体见下面的中断服务程序。帧中断标志位有效时,就复位RIFO_RRST读指针信号,然后在每个FIFO_RCLK读时钟信号,使用STM32去读取FIFO_D[7:0] 的数据。FIFO_OE片选信号在初始化之后就拉低,使之有效。

寄存器

这是来自datasheet的寄存器描述,看手册,英文很重要:
在这里插入图片描述
这些寄存器在代码里表现为一堆宏定义

  /*OV7725寄存器宏定义*/
#define GAIN      0x00
#define BLUE      0x01
#define RED       0x02
#define GREEN     0x03
#define BAVG      0x05
#define GAVG      0x06
…………

模块初始化

引脚定义

//D0~D7:PA0~PA7       VSYNC:PA8
//WRST:PB13  RRST:PB14  OE:PB5  RCLK:PB6  WEN:PB7  SDA:PB8  SCL:PB9    
#define OV7725_VSYNC    PAin(8)			
#define OV7725_WRST		PBout(13)		
#define OV7725_WREN		PBout(7)		
#define OV7725_RCK_H	GPIOB->BSRR=1<<6
#define OV7725_RCK_L	GPIOB->BRR=1<<6
#define OV7725_RRST		PBout(14)  	
#define OV7725_CS		PBout(5)  
#define SCCB_SCL    		PBout(9)	 	//SCL
#define SCCB_SDA    		PBout(8) 		//SDA	 

#define SCCB_READ_SDA    	PBin(8)  		//ÊäÈëSDA   

我使用的是杜邦线连接如,IO口是自己重新定义的(全使用普通IO即可),STM32F1系列的PB3,PB4,PA13,PA14,PA15用于JTAG,如果有使用到其中的引脚,需要进行特殊配置,具体可参考网上更多教程。当时使用PB3,PB4作为SCCB的引脚,出现问题才发现这个原因。

初始化

写寄存器的函数,寄存器的配置都是通过这个函数

u8 SCCB_WR_Reg(u8 reg,u8 data)
{
	u8 res=0;
	SCCB_Start(); 		 	//启动SCCB传输	 	
	if(SCCB_WR_Byte(SCCB_ID))res=1;	//写器件ID,为0x42
	delay_us(100);
  	if(SCCB_WR_Byte(reg))res=1;		//写寄存器地址,直接写对应的寄存器地址
	delay_us(100);
  	if(SCCB_WR_Byte(data))res=1; 	//写数据,根据寄存器功能写对应数据
  	SCCB_Stop();	  
  	return	res;
}		  	

将要配置的寄存器地址和对应的值,存在一个二维数组里边

//初始化寄存器系列及其对应的值
const u8 ov7725_init_reg_tb1[][2]= 
{   
	/*输出窗口设置*/
	{CLKRC,     0x00}, //clock config
	{COM7,      0x06}, //VGA RGB565
	{HSTART,    0x3f}, //水平起始位置
	{HSIZE,     0x50}, //水平尺寸
	{VSTRT,     0x03}, //垂直其实位置
	......

初始化时,在循环语句调用写寄存器的函数,依次写入寄存器的地址和对应的值,即可完成寄存器的配置

 	//初始化OV7725,采用QVGA分辨率(320*240)  
	for(i=0;i<sizeof(ov7725_init_reg_tb1)/sizeof(ov7725_init_reg_tb1[0]);i++)
	{								
	   	SCCB_WR_Reg(ov7725_init_reg_tb1[i][0],ov7725_init_reg_tb1[i][1]);
 	} 

帧中断和数据处理

发生帧中断时

u8 ov_sta;	//帧中断标记
//中断处理函数
void EXTI9_5_IRQHandler(void)
{		 		
	if(EXTI_GetITStatus(EXTI_Line8)==SET)//是8线的中断
	{      
		if(ov_sta==0)
		{
			OV7725_WRST=0;	//复位写指针		 
			OV7725_WRST=1;	
			OV7725_WREN=1;	//允许写入FIFO 	 
			ov_sta++;		//帧中断加1
		}else OV7725_WREN=0;//禁止写入FIFO
	}
	EXTI_ClearITPendingBit(EXTI_Line8);  //清除中断标志位					  
} 

数据处理

if(ov_sta)//判断是否有帧中断发生
{
	OV7725_RRST=0;		  //复
	OV7725_RCK_L;         //位
	OV7725_RCK_H;         //读
	OV7725_RCK_L;         //指
	OV7725_RRST=1;		  //针
	OV7725_RCK_H; 
	for(i=0;i<OV7725_WINDOW_HEIGHT;i++)//循环语句读取FIFO的数据
	{
		for(j=0;j<OV7725_WINDOW_WIDTH;j++)
		{
			//将数据填入相应缓冲区
			......
		}
	}
	ov_sta=0;  //清零帧中断标志
}

以上是对于OV7725的初步理解,还有很多不懂的地方,后续有进一步研究再补充

发布了3 篇原创文章 · 获赞 6 · 访问量 275

猜你喜欢

转载自blog.csdn.net/weixin_40134414/article/details/105046927