1. 程式人生 > >STM32F103實現OV7725拍照儲存為BMP點陣圖

STM32F103實現OV7725拍照儲存為BMP點陣圖

1.首先需要我們定義一下BMP的資料結構,需要定義幾個結構體型別:分別為:BITMAPINFOHEADER(BMP的資訊頭)、BITMAPFILEHEADER(BMP檔案的資訊頭)、RGBQUAD(彩色表,存放RGB565編碼)以及BITMAPINFO(綜合上面的三個結構體)。



2.設定點陣圖資訊,並寫入SD卡。

注意非常重要的一點是,如果OV7725輸出為RGB565格式,一定要配置壓縮型別為3,同時需要配置彩色表,如下所示:


3.逐畫素地寫入資料到點陣圖檔案中。


最後,為了大家參考方便,奉上原始碼。

bmp.h

#ifndef __BMP_H__
#define __BMP_H__
#include "sys.h"
//////////////////////////////////////////////////////////////////////////////////	 

//********************************************************************************
//升級說明
//V2.0
//1,將jpeg解碼庫換成了TJPGD,支援更多的jpg/jpeg檔案,支援小尺寸圖片快速jpeg顯示 
//2,pic_phy裡面新增3個函式,用於開窗顯示,以提高小尺寸jpg圖片的顯示速度
//3,ai_load_picfile函式,新增一個引數:fast,用於設定是否使能jpeg/jpg快速顯示
//注意:這裡的小尺寸是指:jpg/jpeg圖片尺寸小於等於LCD尺寸.
//////////////////////////////////////////////////////////////////////////////////
					    
//////////////////////////////////////////使用者配置區///////////////////////////////
#define BMP_USE_MALLOC		1 		//定義是否使用malloc,這裡我們選擇使用malloc
#define BMP_DBUF_SIZE		2048	//定義bmp解碼陣列的大小(最少應為LCD寬度*3)
//////////////////////////////////////////////END/////////////////////////////////

//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 ;
//BMP標頭檔案
typedef __packed struct
{
    u16  bfType ;     //檔案標誌.只對'BM',用來識別BMP點陣圖型別
    u32  bfSize ;	  //檔案大小,佔四個位元組
    u16  bfReserved1 ;//保留
    u16  bfReserved2 ;//保留
    u32  bfOffBits ;  //從檔案開始到點陣圖資料(bitmap data)開始之間的的偏移量
}BITMAPFILEHEADER ;
//彩色表 
typedef __packed struct 
{
    u8 rgbBlue ;    //指定藍色強度
    u8 rgbGreen ;	//指定綠色強度 
    u8 rgbRed ;	  	//指定紅色強度 
    u8 rgbReserved ;//保留,設定為0 
}RGBQUAD ;
//點陣圖資訊頭
typedef __packed struct
{ 
	BITMAPFILEHEADER bmfHeader;
	BITMAPINFOHEADER bmiHeader;  
	u32 RGB_MASK[3];			//調色盤用於存放RGB掩碼.
	//RGBQUAD bmiColors[256];  
}BITMAPINFO; 
typedef RGBQUAD * LPRGBQUAD;//彩色表  

//圖象資料壓縮的型別
#define BI_RGB	 		0  //沒有壓縮.RGB 5,5,5.
#define BI_RLE8 		1  //每個象素8位元的RLE壓縮編碼,壓縮格式由2位元組組成(重複象素計數和顏色索引);
#define BI_RLE4 		2  //每個象素4位元的RLE壓縮編碼,壓縮格式由2位元組組成
#define BI_BITFIELDS 	3  //每個象素的位元由指定的掩碼決定。 (儲存為RGB565格式點陣圖時需要設定壓縮型別為3) 
		       
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//BMP編解碼函式
u8 stdbmp_decode(const u8 *filename);
u8 minibmp_decode(u8 *filename,u16 x,u16 y,u16 width,u16 height,u16 acolor,u8 mode);//尺寸小於240*320的bmp圖片解碼.
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#endif

bmp.c

#include "piclib.h"
#include "bmp.h"
#include "string.h"

//********************************************************************************
//升級說明
//V2.0
//1,將jpeg解碼庫換成了TJPGD,支援更多的jpg/jpeg檔案,支援小尺寸圖片快速jpeg顯示 
//2,pic_phy裡面新增3個函式,用於開窗顯示,以提高小尺寸jpg圖片的顯示速度
//3,ai_load_picfile函式,新增一個引數:fast,用於設定是否使能jpeg/jpg快速顯示
//注意:這裡的小尺寸是指:jpg/jpeg圖片尺寸小於等於LCD尺寸.
//////////////////////////////////////////////////////////////////////////////////

//不使用記憶體分配
#if BMP_USE_MALLOC == 0	
FIL f_bfile;
u8 bmpreadbuf[BMP_DBUF_SIZE];
#endif 				    

//標準的bmp解碼,解碼filename這個BMP檔案	
//速度比較慢.主要	
//filename:包含路徑的檔名	       	  			  
//返回值:0,成功;
//		 其他,錯誤碼.
u8 stdbmp_decode(const u8 *filename) 
{
	FIL* f_bmp;
    u16 br;

    u16 count;		    	   
	u8  rgb ,color_byte;
	u16 x ,y,color;	  
	u16 countpix=0;//記錄畫素 	 

	//x,y的實際座標	
	u16  realx=0;
	u16 realy=0;
	u8  yok=1;  				   
	u8 res;


	u8 *databuf;    		//資料讀取存放地址
 	u16 readlen=BMP_DBUF_SIZE;//一次從SD卡讀取的位元組數長度

	u8 *bmpbuf;			  	//資料解碼地址
	u8 biCompression=0;		//記錄壓縮方式
	
	u16 rowlen;	  		 	//水平方向位元組數  
	BITMAPINFO *pbmp;		//臨時指標
	
#if BMP_USE_MALLOC == 1	//使用malloc	
	databuf=(u8*)mymalloc(SRAMIN,readlen);		//開闢readlen位元組的記憶體區域
	if(databuf==NULL)return PIC_MEM_ERR;	//記憶體申請失敗.
	f_bmp=(FIL *)mymalloc(SRAMIN,sizeof(FIL));	//開闢FIL位元組的記憶體區域 
	if(f_bmp==NULL)							//記憶體申請失敗.
	{		 
		myfree(SRAMIN,databuf);
		return PIC_MEM_ERR;				
	} 	 
#else				 	//不使用malloc
	databuf=bmpreadbuf;
	f_bmp=&f_bfile;
#endif
	res=f_open(f_bmp,(const TCHAR*)filename,FA_READ);//開啟檔案	 						  
	if(res==0)//開啟成功.
	{ 
		f_read(f_bmp,databuf,readlen,(UINT*)&br);	//讀出readlen個位元組  
		pbmp=(BITMAPINFO*)databuf;					//得到BMP的頭部資訊   
		count=pbmp->bmfHeader.bfOffBits;        	//資料偏移,得到資料段的開始地址
		color_byte=pbmp->bmiHeader.biBitCount/8;	//彩色位 16/24/32  
		biCompression=pbmp->bmiHeader.biCompression;//壓縮方式
		picinfo.ImgHeight=pbmp->bmiHeader.biHeight;	//得到圖片高度
		picinfo.ImgWidth=pbmp->bmiHeader.biWidth;  	//得到圖片寬度 
		ai_draw_init();//初始化智慧畫圖			
		//水平畫素必須是4的倍數!!
		if((picinfo.ImgWidth*color_byte)%4)rowlen=((picinfo.ImgWidth*color_byte)/4+1)*4;
		else rowlen=picinfo.ImgWidth*color_byte;
		//開始解碼BMP   
		color=0;//顏色清空	 													 
		x=0 ;
		y=picinfo.ImgHeight;
		rgb=0;      
		//對於尺寸小於等於設定尺寸的圖片,進行快速解碼
		realy=(y*picinfo.Div_Fac)>>13;
		bmpbuf=databuf;
		while(1)
		{				 
			while(count<readlen)  //讀取一簇1024扇區 (SectorsPerClust 每簇扇區數)
		    {
				if(color_byte==3)   //24位顏色圖
				{
					switch (rgb) 
					{
						case 0:				  
							color=bmpbuf[count]>>3; //B
							break ;	   
						case 1: 	 
							color+=((u16)bmpbuf[count]<<3)&0X07E0;//G
							break;	  
						case 2 : 
							color+=((u16)bmpbuf[count]<<8)&0XF800;//R	  
							break ;			
					}   
				}else if(color_byte==2)  //16位顏色圖
				{
					switch(rgb)
					{
						case 0 : 
							if(biCompression==BI_RGB)//RGB:5,5,5
							{
								color=((u16)bmpbuf[count]&0X1F);	 	//R
								color+=(((u16)bmpbuf[count])&0XE0)<<1; //G
							}else		//RGB:5,6,5
							{
								color=bmpbuf[count];  			//G,B
							}  
							break ;   
						case 1 : 			  			 
							if(biCompression==BI_RGB)//RGB:5,5,5
							{
								color+=(u16)bmpbuf[count]<<9;  //R,G
							}else  		//RGB:5,6,5
							{
								color+=(u16)bmpbuf[count]<<8;	//R,G
							}  									 
							break ;	 
					}		     
				}else if(color_byte==4)//32位顏色圖
				{
					switch (rgb)
					{
						case 0:				  
							color=bmpbuf[count]>>3; //B
							break ;	   
						case 1: 	 
							color+=((u16)bmpbuf[count]<<3)&0X07E0;//G
							break;	  
						case 2 : 
							color+=((u16)bmpbuf[count]<<8)&0XF800;//R	  
							break ;			
						case 3 :
							//alphabend=bmpbuf[count];//不讀取  ALPHA通道
							break ;  		  	 
					}	
				}else if(color_byte==1)//8位色,暫時不支援,需要用到顏色表.
				{
				} 
				rgb++;	  
				count++ ;		  
				if(rgb==color_byte) //水平方向讀取到1畫素數資料後顯示
				{	
					if(x<picinfo.ImgWidth)	 					 			   
					{	
						realx=(x*picinfo.Div_Fac)>>13;//x軸實際值
						if(is_element_ok(realx,realy,1)&&yok)//符合條件
						{						 				 	  	       
							pic_phy.draw_point(realx+picinfo.S_XOFF,realy+picinfo.S_YOFF-1,color);//顯示圖片	
							//POINT_COLOR=color;		 
							//LCD_DrawPoint(realx+picinfo.S_XOFF,realy+picinfo.S_YOFF); 
							//SRAMLCD.Draw_Point(realx+picinfo.S_XOFF,realy+picinfo.S_YOFF,color);
						}   									    
					}
					x++;//x軸增加一個畫素 
					color=0x00; 
					rgb=0;  		  
				}
				countpix++;//畫素累加
				if(countpix>=rowlen)//水平方向畫素值到了.換行
				{		 
					y--; 
					if(y==0)break;			 
					realy=(y*picinfo.Div_Fac)>>13;//實際y值改變	 
					if(is_element_ok(realx,realy,0))yok=1;//此處不改變picinfo.staticx,y的值	 
					else yok=0; 
					x=0; 
					countpix=0;
					color=0x00;
					rgb=0;
				}	 
			} 		
			res=f_read(f_bmp,databuf,readlen,(UINT *)&br);//讀出readlen個位元組
			if(br!=readlen)readlen=br;	//最後一批資料		  
			if(res||br==0)break;		//讀取出錯
			bmpbuf=databuf;
	 	 	count=0;
		}  
		f_close(f_bmp);//關閉檔案
	}  	
#if BMP_USE_MALLOC == 1	//使用malloc	
	myfree(SRAMIN,databuf);	 
	myfree(SRAMIN,f_bmp);		 
#endif	
	return res;		//BMP顯示結束.    					   
}		 
//小尺寸的bmp解碼,解碼filename這個BMP檔案		
//filename:包含路徑的檔名
//x,y,width,height:開窗大小
//acolor:附加的alphablend的顏色(這個僅對32位色bmp有效!!!)
//mode:模式(除了bit5,其他的均只對32位色bmp有效!!!)
//     bit[7:6]:0,僅使用圖片本身和底色alphablend;
//              1,僅圖片和acolor進行alphablend,並且不適用附加的透明度;
//              2,底色,acolor,圖片,一起進行alphablend;
//	   bit5:保留
//     bit4~0:0~31,使用附加alphablend的透明程度 	      	  			  
//返回值:0,成功;
//    其他,錯誤碼.
u8 minibmp_decode(u8 *filename,u16 x,u16 y,u16 width,u16 height,u16 acolor,u8 mode)//尺寸小於240*320的bmp圖片解碼.
{
	FIL* f_bmp;
    u16 br;
	u8  color_byte;
	u16 tx,ty,color;	 
	//tx,ty的實際座標	
	u8 res;
	u16 i,j;
	u8 *databuf;    		//資料讀取存                                                                       放地址
 	u16 readlen=BMP_DBUF_SIZE;//一次從SD卡讀取的位元組數長度,不能小於LCD寬度*3!!!

	u8 *bmpbuf;			  	//資料解碼地址
	u8 biCompression=0;		//記錄壓縮方式
	
	u16 rowcnt;				//一次讀取的行數
	u16 rowlen;	  		 	//水平方向位元組數  
	u16 rowpix=0;			//水平方向畫素數	  
	u8 rowadd;				//每行填充位元組數

	u16 tmp_color;

	u8 alphabend=0xff;		//代表透明色為0,完全不透明
	u8 alphamode=mode>>6;	//得到模式值,0/1/2
	BITMAPINFO *pbmp;   	//臨時指標		 
	//得到窗體尺寸
	picinfo.S_Height=height;
	picinfo.S_Width=width;
		
#if BMP_USE_MALLOC == 1	//使用malloc	
	databuf=(u8*)mymalloc(SRAMIN,readlen);		//開闢readlen位元組的記憶體區域
	if(databuf==NULL)return PIC_MEM_ERR;		//記憶體申請失敗.
	f_bmp=(FIL *)mymalloc(SRAMIN,sizeof(FIL));	//開闢FIL位元組的記憶體區域 
	if(f_bmp==NULL)								//記憶體申請失敗.
	{		 
		myfree(SRAMIN,databuf);
		return PIC_MEM_ERR;				
	} 	 
#else
	databuf=bmpreadbuf;
	f_bmp=&f_bfile;
#endif
	res=f_open(f_bmp,(const TCHAR*)filename,FA_READ);//開啟檔案	 						  
	if(res==0)//開啟成功.
	{ 
		f_read(f_bmp,databuf,sizeof(BITMAPINFO),(UINT*)&br);//讀出BITMAPINFO資訊 
		pbmp=(BITMAPINFO*)databuf;					//得到BMP的頭部資訊   
		color_byte=pbmp->bmiHeader.biBitCount/8;	//彩色位 16/24/32  
		biCompression=pbmp->bmiHeader.biCompression;//壓縮方式
		picinfo.ImgHeight=pbmp->bmiHeader.biHeight;	//得到圖片高度
		picinfo.ImgWidth=pbmp->bmiHeader.biWidth;  	//得到圖片寬度   
		//水平畫素必須是4的倍數!!
		if((picinfo.ImgWidth*color_byte)%4)rowlen=((picinfo.ImgWidth*color_byte)/4+1)*4;
		else rowlen=picinfo.ImgWidth*color_byte;
		rowadd=rowlen-picinfo.ImgWidth*color_byte;	//每行填充位元組數
 		//開始解碼BMP   
		color=0;//顏色清空	 													 
		tx=0 ;
		ty=picinfo.ImgHeight-1;
		if(picinfo.ImgWidth<=picinfo.S_Width&&picinfo.ImgHeight<=picinfo.S_Height)
		{  							   
			rowcnt=readlen/rowlen;						//一次讀取的行數
			readlen=rowcnt*rowlen;						//一次讀取的位元組數
			rowpix=picinfo.ImgWidth;					//水平畫素數就是寬度 
			f_lseek(f_bmp,pbmp->bmfHeader.bfOffBits);	//偏移到資料起始位置 	  
			while(1)
			{	     
				res=f_read(f_bmp,databuf,readlen,(UINT *)&br);	//讀出readlen個位元組
				bmpbuf=databuf;									//資料首地址  
				if(br!=readlen)rowcnt=br/rowlen;				//最後剩下的行數
				if(color_byte==3)  			//24位BMP圖片
				{
					for(j=0;j<rowcnt;j++)	//每次讀到的行數
					{
						for(i=0;i<rowpix;i++)//寫一行畫素
						{
							color=(*bmpbuf++)>>3;		   		 	//B
							color+=((u16)(*bmpbuf++)<<3)&0X07E0;	//G
							color+=(((u16)*bmpbuf++)<<8)&0XF800;	//R
 						 	pic_phy.draw_point(x+tx,y+ty,color);//顯示圖片	
							tx++;
						}
						bmpbuf+=rowadd;//跳過填充區
						tx=0;
						ty--;
					}
				}else if(color_byte==2)//16位BMP圖片
				{
					for(j=0;j<rowcnt;j++)//每次讀到的行數
					{
						if(biCompression==BI_RGB)//RGB:5,5,5
						{
							for(i=0;i<rowpix;i++)
							{
								color=((u16)*bmpbuf&0X1F);			//R
								color+=(((u16)*bmpbuf++)&0XE0)<<1; 	//G
		 						color+=((u16)*bmpbuf++)<<9;  	    //R,G	 
							    pic_phy.draw_point(x+tx,y+ty,color);//顯示圖片	
								tx++;
							}
						}else  //RGB 565
						{
							for(i=0;i<rowpix;i++)
							{											 
								color=*bmpbuf++;  			//G,B
		 						color+=((u16)*bmpbuf++)<<8;	//R,G	 
							  	pic_phy.draw_point(x+tx,y+ty,color);//顯示圖片	
								tx++;
							}
						}
						bmpbuf+=rowadd;//跳過填充區
						tx=0;
						ty--;
					}	
				}else if(color_byte==4)		//32位BMP圖片
				{
					for(j=0;j<rowcnt;j++)	//每次讀到的行數
					{
						for(i=0;i<rowpix;i++)
						{
							color=(*bmpbuf++)>>3;		   		 	//B
							color+=((u16)(*bmpbuf++)<<3)&0X07E0;	//G
							color+=(((u16)*bmpbuf++)<<8)&0XF800;	//R
							alphabend=*bmpbuf++;					//ALPHA通道
							if(alphamode!=1) //需要讀取底色
							{
								tmp_color=pic_phy.read_point(x+tx,y+ty);//讀取顏色		   
							    if(alphamode==2)//需要附加的alphablend
								{
									tmp_color=piclib_alpha_blend(tmp_color,acolor,mode&0X1F);	//與指定顏色進行blend		 
								}
								color=piclib_alpha_blend(tmp_color,color,alphabend/8); 			//和底色進行alphablend
							}else tmp_color=piclib_alpha_blend(acolor,color,alphabend/8);		//與指定顏色進行blend
 							pic_phy.draw_point(x+tx,y+ty,color);//顯示圖片				   
							tx++;//x軸增加一個畫素 	  
						}
						bmpbuf+=rowadd;//跳過填充區
						tx=0;
						ty--;
					}

				}
				if(br!=readlen||res)break;	 
			}	 
		}	
		f_close(f_bmp);//關閉檔案      
	}else res=PIC_SIZE_ERR;//圖片尺寸錯誤	
#if BMP_USE_MALLOC == 1	//使用malloc	
	myfree(SRAMIN,databuf);	 
	myfree(SRAMIN,f_bmp);		 
#endif	
	return res;
}            

main.c

#include "delay.h"
#include "sys.h"
#include "lcd.h"
#include "usart.h"	 
#include "piclib.h"
#include "ov7725.h"
#include "key.h"
#include "exti.h"
#include "led.h"

extern u8 ov_sta;	//在exit.c裡面定義

//由於OV7725感測器安裝方式原因,OV7725_WINDOW_WIDTH相當於LCD的高度,OV7725_WINDOW_HEIGHT相當於LCD的寬度
//注意:此巨集定義只對OV7725有效
#define  OV7725_WINDOW_WIDTH		320 // <=320
#define  OV7725_WINDOW_HEIGHT		240 // <=240

FRESULT res_sd;//檔案操作結果
FIL fnew; //檔案對
UINT fnum; //檔案成功讀寫數量

//更新LCD顯示
void camera_refresh(void)
{
	u32 i,j;
 	u16 color;
	BITMAPINFO bmp;
	int s1 = 0;
	int s2 = 0;
	int s3 = 0;
	int s4 = 0;
	
	//按下S2顯示圖片
	if(KEY_Scan(1) == S2)
	{
		LCD_Clear(BLACK);
		ai_load_picfile("0:test1.bmp",0,0,lcddev.width,lcddev.height,1);//顯示圖片
		delay_ms(5000);      //清屏函式LCD_Clear(BLACK),可以消除分屏現象。
return; } //按下S1拍攝圖片 if(ov_sta && KEY_Scan(1) == S1) { //開啟檔案,若不存在就建立 res_sd = f_open(&fnew, "0:test1.bmp", FA_OPEN_ALWAYS | FA_WRITE); //檔案開啟成功 if(res_sd == FR_OK) { //填寫檔案資訊頭資訊 bmp.bmfHeader.bfType = 0x4D42; //bmp型別 bmp.bmfHeader.bfOffBits=sizeof(bmp.bmfHeader) + sizeof(bmp.bmiHeader) + sizeof(bmp.RGB_MASK); //點陣圖資訊結構體所佔的位元組數 bmp.bmfHeader.bfSize= bmp.bmfHeader.bfOffBits + 320*240*2; //檔案大小(資訊結構體+畫素資料) bmp.bmfHeader.bfReserved1 = 0x0000; //保留,必須為0 bmp.bmfHeader.bfReserved2 = 0x0000; //填寫點陣圖資訊頭資訊 bmp.bmiHeader.biSize=sizeof(bmp.bmiHeader); //點陣圖資訊頭的大小 bmp.bmiHeader.biWidth=320; //點陣圖的寬度 bmp.bmiHeader.biHeight=240; //影象的高度 bmp.bmiHeader.biPlanes=1; //目標設別的級別,必須是1 bmp.bmiHeader.biBitCount=16; //每畫素位數 bmp.bmiHeader.biCompression=3; //每個象素的位元由指定的掩碼(RGB565掩碼)決定。 (非常重要) bmp.bmiHeader.biSizeImage=320*240*2; //實際點陣圖所佔用的位元組數(僅考慮點陣圖畫素資料) bmp.bmiHeader.biXPelsPerMeter=0; //水平解析度 bmp.bmiHeader.biYPelsPerMeter=0; //垂直解析度 bmp.bmiHeader.biClrImportant=0; //說明影象顯示有重要影響的顏色索引數目,0代表所有的顏色一樣重要 bmp.bmiHeader.biClrUsed=0; //點陣圖實際使用的彩色表中的顏色索引數,0表示使用所有的調色盤項 //RGB565格式掩碼 bmp.RGB_MASK[0] = 0X00F800; bmp.RGB_MASK[1] = 0X0007E0; bmp.RGB_MASK[2] = 0X00001F; //寫檔案頭進檔案 res_sd= f_write(&fnew, &bmp, sizeof(bmp), &fnum); //讀指標復位 OV7725_RRST=0; //開始復位讀指標 OV7725_RCK_L; OV7725_RCK_H; OV7725_RCK_L; OV7725_RRST=1; //復位讀指標結束 OV7725_RCK_H; /*影象花屏的原因在於讀取時的干擾和讀取時漏掉幾個畫素*/ for(i=0;i<240;i++) { for(j=0;j<320;j++) { OV7725_RCK_L; color=GPIOC->IDR&0XFF; //讀資料 OV7725_RCK_H; color<<=8; OV7725_RCK_L; color|=GPIOC->IDR&0XFF; //讀資料 OV7725_RCK_H; //寫點陣圖資訊頭進記憶體卡 f_write(&fnew, &color, sizeof(color), &fnum); } } //關閉檔案 f_close(&fnew); delay_ms(1000); return; } } //沒有按鍵按下,重新整理LCD if(ov_sta) { LCD_Scan_Dir(U2D_L2R); //從上到下,從左到右 LCD_WriteRAM_Prepare(); //開始寫入GRAM //讀指標復位 OV7725_RRST=0; //開始復位讀指標 OV7725_RCK_L; OV7725_RCK_H; OV7725_RCK_L; OV7725_RRST=1; //復位讀指標結束 OV7725_RCK_H; /*影象花屏的原因在於讀取時的干擾和讀取時漏掉幾個畫素*/ for(i=0;i<240;i++) { for(j=0;j<320;j++) { OV7725_RCK_L; color=GPIOC->IDR&0XFF; //讀資料 OV7725_RCK_H; color<<=8; OV7725_RCK_L; color|=GPIOC->IDR&0XFF; //讀資料 OV7725_RCK_H; LCD->LCD_RAM=color; } } ov_sta=0; //開始下一次採集 LCD_Scan_Dir(DFT_SCAN_DIR); //恢復預設掃描方向 } } int main(void) { u8 lightmode=0,saturation=2,brightness=2,contrast=2,effect=0; u8 i = 0; delay_init(); //延時函式初始化 uart_init(9600); //串列埠初始化為9600 LCD_Init(); //初始化LCD液晶顯示屏 KEY_Init(); //按鍵初始化 exfuns_init(); //為fatfs相關變數申請記憶體 f_mount(0,fs[0]); //掛載SD卡 piclib_init(); //初始化畫圖 while(OV7725_Init() != 0); //初始化OV7725攝像頭 LCD_ShowString(60,210,200,16,16,"OV7725 Init OK"); //特效 OV7725_Light_Mode(lightmode); OV7725_Color_Saturation(saturation); OV7725_Brightness(brightness); OV7725_Contrast(contrast); OV7725_Special_Effects(effect); //設定輸出格式 OV7725_Window_Set(OV7725_WINDOW_WIDTH,OV7725_WINDOW_HEIGHT,0);//QVGA模式輸出 //輸出使能 OV7725_CS=0; EXTI8_Init(); //使能定時器捕獲 LCD_Clear(BLACK); while(1) { camera_refresh();//更新顯示 i++; if(i==15)//DS0閃爍. { i=0; LED0=!LED0; } } }
有關OV7725配置的程式碼暫時不貼了。

另外需要注意的是,拍照過程中可能會出現割屏現象(即螢幕分成幾塊),這個時候可以通過清屏函式LCD_Clear(BLACK)消除該現象。

附原始碼Github地址:https://github.com/jack13163/OV7725_BMP