STM32F103实现OV7725拍照存储为BMP位图
程序员文章站
2024-01-24 17:12:52
...
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
上一篇: Pandas数据处理基础3
下一篇: JAVA实现对BMP图片的读取