基於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的初步理解,還有很多不懂的地方,後續有進一步研究再補充

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章