STM32F103实现OV7725拍照存储为BMP位图

article/2025/9/13 20:39:44

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、或32u32 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				 	//不使用mallocdatabuf=bmpreadbuf;f_bmp=&f_bfile;
#endifres=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; //Bbreak ;	   case 1: 	 color+=((u16)bmpbuf[count]<<3)&0X07E0;//Gbreak;	  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);	 	//Rcolor+=(((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; //Bbreak ;	   case 1: 	 color+=((u16)bmpbuf[count]<<3)&0X07E0;//Gbreak;	  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/2BITMAPINFO *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;				} 	 
#elsedatabuf=bmpreadbuf;f_bmp=&f_bfile;
#endifres=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;		   		 	//Bcolor+=((u16)(*bmpbuf++)<<3)&0X07E0;	//Gcolor+=(((u16)*bmpbuf++)<<8)&0XF800;	//Rpic_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);			//Rcolor+=(((u16)*bmpbuf++)&0XE0)<<1; 	//Gcolor+=((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,Bcolor+=((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;		   		 	//Bcolor+=((u16)(*bmpbuf++)<<3)&0X07E0;	//Gcolor+=(((u16)*bmpbuf++)<<8)&0XF800;	//Ralphabend=*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);		//与指定颜色进行blendpic_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 // <=240FRESULT 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;		//保留,必须为0bmp.bmfHeader.bfReserved2 = 0x0000;  			//填写位图信息头信息  bmp.bmiHeader.biSize=sizeof(bmp.bmiHeader);  				    //位图信息头的大小bmp.bmiHeader.biWidth=320;  														//位图的宽度bmp.bmiHeader.biHeight=240;  			    //图像的高度bmp.bmiHeader.biPlanes=1;  				    //目标设别的级别,必须是1bmp.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;}}//没有按键按下,刷新LCDif(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);	 	//串口初始化为9600LCD_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


http://chatgpt.dhexx.cn/article/vhZZGIPY.shtml

相关文章

OV7725摄像头模块SCCB通信

学习这款摄像头&#xff0c;首先是要了解SCCB通信协议 SCCB通信协议 这个协议与IIC通信协议很想&#xff0c;但是存在一点区别&#xff0c;如果想要更好了解这个协议&#xff0c;可以先学习一下IIC协议&#xff0c;这个协议讲解网上资源很全。 首先介绍一下这个协议&#xff0…

【一、视频处理】FPGA驱动OV7725摄像头模块

使用的模块是正点原子的ov7725不带fifo的摄像头&#xff0c;开发板是正点原子的开拓者。 一、SCCB协议与IIC协议的不同 摄像头采用的是SCCB协议&#xff0c;这个协议与I2C协议很像&#xff0c;但是有细微的区别。差别在于 SCCB传输协议中&#xff0c;第9位为不必关心位&#…

FPGA 20个例程篇:19.OV7725摄像头实时采集送HDMI显示(三)

第七章 实战项目提升&#xff0c;完善简历 19.OV7725摄像头实时采集送HDMI显示&#xff08;三&#xff09; 在详细介绍过OV7725 CMOS Sensor的相关背景知识和如何初始化其内部寄存器达到输出预期视频流的目的后&#xff0c;就到了该例程的核心内容即把OV7725输出的视频流预先缓…

OV7725的帧率和PCLK寄存器设置

一、OV7725的PCLK的改变和以下几个寄存器有关&#xff1a; 1&#xff1a;OX0D&#xff08;COM4&#xff09;&#xff1b; ------------------------------------------------------------------------------------------------------------------ 0X0D COM4 41 …

手把手教你写Ov7725摄像头数据采集模块(带Verilog代码)

上一节咱们学习了OV7725的VGA传输协议&#xff0c;对于数据传输的特点有了初步了解&#xff0c;这篇博客主要目的在于使用Verilog实现一个OV7725摄像头的数据采集模块&#xff0c;与咱们这个模块对接的是后一级的SDRAM存储器&#xff0c;其将作为数据的缓存仓库&#xff0c;以便…

STM32+ov7725+ESP8266实现无线图传-完成上位机图像显示

一、需求 stm32f407探索者开发板和STM32F103ZET6战舰开发板。接正点原子ov5640、OV7725、OV2640摄像头,通过esp8266Wi-Fi模块(透传模式)将摄像头采集到的rgb565格式图片通过tcp/ip协议上传到上位机显示。 二、设计思路 【1】使用QT开发上位机,建立TCP服务器,接收ESP8266…

FPGA 20个例程篇:19.OV7725摄像头实时采集送HDMI显示(二)

第七章 实战项目提升&#xff0c;完善简历 19.OV7725摄像头实时采集送HDMI显示&#xff08;二&#xff09; 在正式介绍OV7725 CMOS Sensor视频采集前&#xff0c;首先需要去详细说明OV7725的寄存器配置接口&#xff0c;这里有OmniVision公司推出的官方手册 “OV7725_software_…

OV7725寄存器配置

OV7725寄存器配置&#xff08;为了替换NT99141研究了很长一段时间&#xff09; 部分参考链接&#xff1a; OV7725 电器特性和时序图&#xff1a;https://www.cnblogs.com/raymon-tec/p/5087088.html OV7725摄像头的彩色图像采集原理与液晶显示(有必要了解框图)&#xff1a;htt…

基于STM32的OV7725摄像头拍照实验

平台&#xff1a;STM32ZET6&#xff08;核心板&#xff09;ST-LINK/V2SD卡USB串口线鹰眼OV7725摄像头&#xff08;注意&#xff0c;为了减少摄像头连线的麻烦&#xff0c;建议初学者选取单片机时选用带有摄像头接口的板子&#xff09; 工程介绍&#xff1a;需要移植FatFs文件系…

OV7725鹰眼摄像头

OV7725鹰眼摄像头如何使用&#xff1f; 目前的ov7725鹰眼摄像头&#xff0c;基本上用的都是山外的库&#xff0c;所以今天我们主要根据山外的库&#xff0c;基于k60芯片&#xff0c;给大家具体的讲解。 1.摄像头初始化 首先是摄像头的第一步就是初始化&#xff0c;这个我们直…

OV7725摄像头图像采集基础知识

目前FPGA用于图像采集 传输 处理 显示应用越来越多&#xff0c;主要原因是图像处理领域的火热以及FPGA强大的并行处理能力。本文以OV7725为例&#xff0c;对摄像头使用方面的基础知识做个小的总结&#xff0c;为后续做个铺垫。 XCLK:工作时钟输入&#xff0c;由主控器产生&…

FPGA--OV7725摄像头采集与VGA显示实验--1--OV7725使用与驱动协议

目录 前言 OV7725引脚及功能框图 参数指标 引脚 功能框图 SCCB时序及读写操作 SCCB时序特点 读写实现 OV7725寄存器常用配置参数 前言 摄像头采集是图像处理的第一步&#xff0c;本章节分为多部分&#xff0c;旨在让大家学会如何使用OV7725采集图像&#xff0c;并且…

【FPGA的基础快速入门22-------OV7725摄像头模块】

OV7725摄像头模块 OV7725是Omni Vision&#xff08;豪威科技&#xff09;公司生产的CMOS图像传感器&#xff0c;该传感器功耗低、可靠性高以及采集速率快&#xff0c;主要应用在玩具、安防监控、电脑多媒体等领域。 OV7725感光阵列达到640*480&#xff0c;能实现最快60fps VGA…

STM32 OV7725 传感器

目录 OV7725 传感器1、选择输出格式2、选择输出分辨率3、帧率调整4、夜间模式5、消除光带6、白平衡7、缺陷像素矫正8、黑电平矫正9、视频模式10、数字缩减 OV7725 函数1、光模式2、颜色饱和度3、亮度4、对比度5、特效 OV7725 设置参考 OV7725 传感器 OV7725摄像机™ 图像传感器…

OV7725摄像头之OV7725芯片

近日入手了一块正点原子家的OV7725摄像头模块&#xff0c;秉着小白尽可能学得透彻些的想法&#xff0c;选择了野火家的相同摄像头教学视频。链接如下&#xff1a;【单片机】野火STM32F103教学视频 (配套霸道/指南者/MINI)【全】(刘火良老师出品) (无字幕)_哔哩哔哩_bilibili 现…

二进制加法运算

两个二进制整数相加时&#xff0c;是位对位处理的&#xff0c;从最低的一对位&#xff08;右边&#xff09;开始&#xff0c;依序将每一对位进行加法运算。两个二进制数字相加&#xff0c;有四种结果&#xff0c;如下所示&#xff1a; 0 0 00 1 11 0 1 1 1 10 1 与 1 …

二进制加减法编程

1、二进制加法基本指令 &#xff08;1&#xff09;ADD指令 格式&#xff1a;ADD DST&#xff0c;SRC 该指令把源操作数&#xff08;SRC&#xff09;指向的数据与目的操作数&#xff08;DST&#xff09;相加后&#xff0c;将结果放到目的操作数&#xff08;DST&#xff09;中…

二进制乘除法运算原理

二进制乘除法原理 计算机所能完成的最基本操作是加减法和左右移。 虽然ISA中一般都有MUL类指令&#xff0c;但是这些经过译码之后最终的元操作还是加法和移位指令。 二进制乘法 假设不能使用乘除运算求ab的结果&#xff0c;当ab123时&#xff0c;最直接的方法是通过88个88相…

二进制加法计算

读计算机原理这本书的的时候涉及到二进制数的加法&#xff0c;个人做个直观的记录&#xff0c;防止遗忘。 计算时&#xff0c;先把两个二进制数对齐&#xff08;如同十进制一样&#xff0c; 从右向左&#xff09;11为10&#xff0c;此时向上一位进1,0写在本位&#xff08;如同十…

二进制加减乘除

最重要的,理解十进制的借位和进位.十进制中,由于一个循环是10,所以借1位,就相当于从高位借过来10,也就是常说的借1当10,同时,高位需要减去10(外在体现上是减去1,因为高位已经在高位了).反过来,进1,就等于高位加上10,但因为高位已经在高位了,所以去掉位数考虑,高位实际是加1,也就…