//读取坐标点的值
else databuf[pixcnt]=0Xffff;//补充白色的像素.
pixcnt++; tx++;
}
hbmp.bmiHeader.biHeight--;
res=f_write(f_bmp,(u8*)databuf,bi4width,&bw);//写入数据
}
f_close(f_bmp);
}
#if BMP_USE_MALLOC == 1 //使用malloc
myfree(SRAMIN,databuf);
myfree(SRAMIN,f_bmp);
#endif
return res;
}
该函数实现了对LCD屏幕的任意指定区域进行截屏保存,用到的方法就是48.1节我们所介绍的方法,该函数实现了将LCD任意指定区域的内容,保存个为16位BMP格式,存放在指定位置(由filename决定)。注意,代码中的BMP_USE_MALLOC是在bmp.h定义的一个宏,用于设置是否使用malloc,本章我们选择使用malloc。
保存bmp.c,然后在bmp.h里面添加bmp_encode函数的申明,并保存bmp.h文件。
剩下的,我们就只需要修改主函数即可了,打开test.c,修改该文件代码如下:
extern u8 ov_sta; //在exit.c里面定义
extern u8 ov_frame; //在timer.c里面定义
//更新LCD显示
void camera_refresh(void)
{
u32 j;
u16 color;
if(ov_sta==2)
{
LCD_Scan_Dir(U2D_L2R); //从上到下,从左到右
LCD_SetCursor(0x00,0x0000); //设置光标位置
LCD_WriteRAM_Prepare(); //开始写入GRAM
OV7670_RRST=0; //开始复位读指针
OV7670_RCK=0;
OV7670_RCK=1;
OV7670_RCK=0;
OV7670_RRST=1; //复位读指针结束
OV7670_RCK=1;
for(j=0;j<76800;j++)
{
OV7670_RCK=0;
color=GPIOC->IDR&0XFF; //读数据
OV7670_RCK=1;
color<<=8;
OV7670_RCK=0;
color|=GPIOC->IDR&0XFF; //读数据
OV7670_RCK=1;
LCD->LCD_RAM=color;
}
EXTI->PR=1<<8; //清除LINE8上的中断标志位
ov_sta=0; //开始下一次采集
ov_frame++;
LCD_Scan_Dir(DFT_SCAN_DIR); //恢复默认扫描方向
}
}
//文件名自增(避免覆盖)
//组合成:形如\"0:PHOTO/PIC13141.bmp\"的文件名
void camera_new_pathname(u8 *pname)
{
u8 res;
u16 index=0;
while(index<0XFFFF)
{
sprintf((char*)pname,\"0:PHOTO/PIC%05d.bmp\",index);
res=f_open(ftemp,(const TCHAR*)pname,FA_READ);//尝试打开这个文件
if(res==FR_NO_FILE)break; //该文件名不存在=正是我们需要的.
index++;
}
}
int main(void)
{
u8 res;
u8 *pname; //带路径的文件名
u8 key; //键值
u8 i;
u8 sd_ok=1; //0,sd卡不正常;1,SD卡正常.
Stm32_Clock_Init(9); //系统时钟设置
delay_init(72); //延时初始化
uart_init(72,9600); //串口1初始化
LCD_Init(); //初始化液晶
LED_Init(); //LED初始化
BEEP_Init(); //蜂鸣器初始化
KEY_Init(); //按键初始化
usmart_dev.init(72); //usmart初始化
mem_init(SRAMIN); //初始化内部内存池
exfuns_init(); //为fatfs相关变量申请内存
f_mount(0,fs[0]); //挂载SD卡
f_mount(1,fs[1]); //挂载FLASH.
piclib_init(); //初始化画图
POINT_COLOR=RED;
while(font_init()) //检查字库
{
LCD_ShowString(60,50,200,16,16,\"Font Error!\"); delay_ms(200);
LCD_Fill(60,50,240,66,WHITE);//清除显示
}
Show_Str(60,50,200,16,\"战舰 STM32开发板\",16,0);
Show_Str(60,70,200,16,\"照相机实验\",16,0);
Show_Str(60,90,200,16,\"WK_UP:拍照\",16,0);
Show_Str(60,110,200,16,\"正点原子@ALIENTEK\",16,0);
Show_Str(60,130,200,16,\"2012年8月10日\",16,0);
res=f_mkdir(\"0:/PHOTO\"); //创建PHOTO文件夹
if(res!=FR_EXIST&&res!=FR_OK) //发生了错误
{
Show_Str(60,150,240,16,\"SD卡错误!\",16,0); delay_ms(200);
Show_Str(60,170,240,16,\"拍照功能将不可用!\",16,0);sd_ok=0;
}else
{
Show_Str(60,150,240,16,\"SD卡正常!\",16,0); delay_ms(200);
Show_Str(60,170,240,16,\"KEY_UP:拍照\",16,0); sd_ok=1;
}
pname=mymalloc(SRAMIN,30); //为带路径的文件名分配30个字节的内存
while(pname==NULL) //内存分配出错
{
Show_Str(60,190,240,16,\"内存分配失败!\",16,0); delay_ms(200);
LCD_Fill(60,190,240,146,WHITE); delay_ms(200);//清除显示
}
while(OV7670_Init())//初始化OV7670
{
Show_Str(60,190,240,16,\"OV7670 错误!\",16,0) ;delay_ms(200);
LCD_Fill(60,190,239,206,WHITE); delay_ms(200);
}
Show_Str(60,190,200,16,\"OV7670 正常\",16,0); delay_ms(1500);
TIM6_Int_Init(10000,7199); //10Khz计数频率,1秒钟中断
EXTI8_Init(); //使能定时器捕获
OV7670_Window_Set(10,174,240,320);//设置窗口
OV7670_CS=0;
while(1)
{
key=KEY_Scan(0);//不支持连按
if(key==KEY_UP)
{
if(sd_ok)
{
LED1=0; //点亮DS1,提示正在拍照
camera_new_pathname(pname);//得到文件名
if(bmp_encode(pname,0,0,240,320,0))//拍照有误
{
Show_Str(40,130,240,12,\"写入文件错误!\",12,0);
}else
{
Show_Str(40,130,240,12,\"拍照成功!\",12,0);
Show_Str(40,150,240,12,\"保存为:\",12,0);
Show_Str(40+42,150,240,12,pname,12,0);
BEEP=1; //蜂鸣器短叫,提示拍照完成
delay_ms(100);
}
}else //提示SD卡错误
{
Show_Str(40,130,240,12,\"SD卡错误!\",12,0);
Show_Str(40,150,240,12,\"拍照功能不可用!\",12,0);
}
BEEP=0;//关闭蜂鸣器
LED1=1;//关闭DS1
delay_ms(1800);//等待1.8秒钟
}else delay_ms(10);
camera_refresh();//更新显示
i++;
if(i==20) { i=0; LED0=!LED0;}//DS0闪烁.
}
}
此部分代码,和第四十一章的代码有点类似,只是这里我们多了一个camera_new_pathname函数,用于获取新的bmp文件名字(不覆盖旧的)。在main函数里面,我们通过WK_UP按键控制拍照(调用bmp_encode函数实现),其他部分我们就不多介绍了,至此照相机实验代码编写完成。
最后,本实验可以通过USMART来测试BMP编码函数,将bmp_encode函数添加到USMART管理,即可通过串口自行控制拍照,方便测试。
48.4 下载验证 在代码编译成功之后,我们通过下载代码到ALIENTEK战舰STM32开发板上,得到如图48.4.1所示界面:
图48.4.1 程序运行效果图
随后,进入监控界面。此时,我们可以按下WK_UP即可进行拍照。拍照得到的照片效果如图48.4.2所示:
图48.4.2 拍照样图
最后,我们还可以通过USMART调用bmp_encode函数,实现串口控制拍照,还可以拍成各种尺寸哦(不过必须小于240*320)!
[ 本帖最后由 正点原子 于 2013-4-10 23:08 编辑 ]本文来自论坛,点击查看完整帖子内容。