基于zynq7100的OV5640摄像头照相机实验,提供工程源码和技术支持

1.设计架构

设计框图如下:
在这里插入图片描述
采用Xilinx官方推荐的VDMA架构实现图像缓存和显示,除OV5640摄像头采集和HDMI输出外,其他ip均采用Xilinx官方IP实现。
这里说明一下:
OV5640摄像头图像数据经VDMA三帧缓存后有2路输出
1路输出HDMI显示器显示;
1路通过FATFS文件系统写入sd卡中存放,存放的数据格式位bmp图片;

2.工程简介

开发板的zynq主控是zynq7100,工程实现功能如下:
1.实现OV5640摄像头HDMI输出;
2.实现sd卡FATFS文件系统简单读写测试;
3.实现OV5640摄像头循环拍照,3秒拍摄一张图片;
4.实现OV5640摄像头按键拍照,板载PS侧按键按一下拍照;
工程BD部分如下:
在这里插入图片描述
工程代码架构如下:
在这里插入图片描述
工程SDK代码架构如下:
在这里插入图片描述
SDK代码说明:
设置了2个宏定义:

//#define FATFS_TEST
//#define KEY_CAMERA

#define FATFS_TEST:FATFS文件系统测试:
默认为注释掉,程序执行摄像头循环拍照功能;
取消注释则程序执行FATFS文件系统读写测试;
#define KEY_CAMERA:摄像头按键拍照功能;
默认为注释掉,程序执行摄像头循环拍照功能;
取消注释则程序执行摄像头按键拍照功能;

3.zynq配置

zynq配置这里主要是要使能i2c外设和sd卡外设,i2c外设使能是为了配置OV5640摄像头,sd卡外设使能则是为了存放拍摄的照片,除此之外,还要使能一个mio,因为mio连接了一个PS侧的按键,后面要依靠此按键来触发拍照;
在这里插入图片描述
在这里插入图片描述

4.sd卡文件系统FATFS配置

在嵌入式领域,sd卡可以跑FATFS文件系统,Xilinx的SDK开发环境已经集成了FATFS库,所以我们只需在使用前配置一下就可以了,非常方便,设置方法如下:
1.vivado导出比特流并启动sdk;
2.sdk新建一个工程;
3.接下来添加 FATFS 库。需要注意的是,先关闭 system.mss 的界面,再添加 FATFS库,否则有可能导致 FATFS 库添加失败。
在这里插入图片描述
system.mss 界面关闭后,右击 micro_sd_rw_bsp,选择“Board Support Package Setting”。
在这里插入图片描述
在弹出的界面中勾选“xilffs”,xilffs 即为 FATFS 库
在这里插入图片描述
勾选后,会在左侧 Overview 的 standalone 一栏出现 xilffs,点击 xilffs。可以看到 use_lfn 的默认设置为
false,即不使能。use_lfn 用于设置是否使能长文件名以及文件名的小写字母,这里将 use_lfn 设置为 true,
点击“OK”按钮完成设置。
在这里插入图片描述
设置完成后,在 sd_rw_txt_bsp→ps_cortexa9_0→libsrc 一栏下,会多出 FATFS 的库函数。
在这里插入图片描述

5.sd卡文件系统FATFS读写测试

在摄像头拍照实验之前,需要先对FATFS文件系统进行测试,看是否在sd卡上能跑通;
测是方法如下:
第一步:在sd卡中新建一个txt文件;
第二步:新建的txt文件中写入一段测试字符串;
第三步:读出txt文件中上一步写入的测试字符串;
第四步:比较读写字符串内容是否完全一致;也可以拔出sd卡在电脑中查看内容;
在SDK中建立了sd读写的头文件和源文件,在源文件中含有读写测试的功能函数;
在进行sd卡文件系统FATFS读写测试之前,应在主函数中取消#define FATFS_TEST的注释:

#define FATFS_TEST
//#define KEY_CAMERA

写数据如下:

const char src_str[100] = "I love Xilinx FPGAs ~~~~~~~~~~~~"; //定义文本内容

下面给出读写测试函数源码;

int helai_sd_test(){
    int len;
    int i;
    char dest_str[100] = "";
    sd_mount();           //挂载SD卡
    len = strlen(src_str);         //计算字符串长度
    sd_write_data(FILE_NAME,(u32)src_str,len);	//SD卡写数据
    sd_read_data(FILE_NAME,(u32)dest_str,len);	//SD卡读数据
    //比较写入的字符串和读出的字符串是否相等
   //for(i=0;i<len;i++){
   // 	xil_printf("read data =%c\r\n",dest_str[i]);
   // }
    if (strcmp(src_str, dest_str) == 0) xil_printf("src_str is equal to dest_str,SD card test success!\n");
    else xil_printf("src_str is not equal to dest_str,SD card test failed!\n");
    return 0;
}

测试结果:
串口观测读写内容的对比结果为正确:
在这里插入图片描述
拔出SD卡用读卡器到电脑端直接查看内容:
在这里插入图片描述
在这里插入图片描述

6.OV5640摄像头显示测试

为了保证拍照的正确性,调试拍照之前,必须保证图像数据采集的正确,所以直接接上显示器输出,分辨率位720P,这部分由VDMA配置;

7.OV5640摄像头循环拍照测试

这部分功能为实现OV5640摄像头循环拍照,3秒拍摄一张图片;
bmp图片有固定的数据头,所以直接在程序中定义该部分,如下:

//BMP图片文件头
u8 bmp_head[54] = {
     0x42,0x4d,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x36,0x0,0x0,0x0,0x28,0x0,
	 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x0,0x18,0x0,0x0,0x0,
	 0x0,0x0,0x0,0x0,0x0,0x0,0xc4,0xe,0x0,0x0,0xc4,0x0e,0x0,0x0,0x0,0x0,
	 0x0,0x0,0x0,0x0,0x0,0x0 };

随后就是将图像的rgb数据部分和数据头部分一起写入sd卡中形成bmp图片;
直接给出主函数代码:

void main(){
	XGpioPs_Config_key=XGpioPs_LookupConfig(GPIO_KEY);
	XGpioPs_CfgInitialize(&XgpioPS_key, XGpioPs_Config_key, XGpioPs_Config_key->BaseAddr);
	XGpioPs_SetDirectionPin(&XgpioPS_key, 51, 0);
	// Initialize OV5640 regesiter
	int  rd_index;				//VDMA读通道操作的帧缓存编号
	unsigned int rd_fram_addr;	//VDMA读通道操作的帧缓存地址
	I2C_config_init();
	helai_vdma();
#ifdef FATFS_TEST
	helai_sd_test();
	while(1);
#else
	//最后一个参数表示清零的字节数,由于RGB888数据格式占用3个字节,因此最后乘以3
	memset(0x01000000,0,1280*720*3*3);
	Xil_DCacheFlush();
	//根据VDMA显存大小给BMP文件头赋值
	*bmp_width  = 1280;
	*bmp_height = 720;
	*bmp_size   = 1280*720*3;
	*bf_size    = *bmp_size + 54;
	f_mount(&fatfs,"",1);	//挂载文件系统
	while (1){
		#ifdef KEY_CAMERA
		int key;
		key=XGpioPs_ReadPin(&XgpioPS_key, 51);
		if(key==0){
			usleep(20000);
			if(key==0){
				printf("capture picture\n");
				rd_index = XAxiVdma_CurrFrameStore(&vdma, XAXIVDMA_READ);	//获取当前读通道操作的帧缓存编号
				printf("current read frame is %d\n",rd_index);
				XAxiVdma_StartParking(&vdma, rd_index, XAXIVDMA_READ);	//读通道驻停在当前帧
				rd_fram_addr = 0x01000000 + 1280*720*3*rd_index;	//并获取当前帧的起始地址
				memcpy((void *)bmp_addr,(void *)rd_fram_addr,1280*720*3);	//将当前帧的图像拷贝到抓拍图片缓存区域
				XAxiVdma_StopParking(&vdma, XAXIVDMA_READ);	//结束读通道驻停过程,继续在多帧之间进行切换
				write_sd_bmp((u8 *)bmp_addr);	//将抓拍图片缓存区域中的图像以BMP格式写入SD卡
				pic_cnt++;	//BMP图片编号累加
			}
		}
		#else
		printf("capture picture\n");
		rd_index = XAxiVdma_CurrFrameStore(&vdma, XAXIVDMA_READ);	//获取当前读通道操作的帧缓存编号
		printf("current read frame is %d\n",rd_index);
		XAxiVdma_StartParking(&vdma, rd_index, XAXIVDMA_READ);	//读通道驻停在当前帧
		rd_fram_addr = 0x01000000 + 1280*720*3*rd_index;	//并获取当前帧的起始地址
		memcpy((void *)bmp_addr,(void *)rd_fram_addr,1280*720*3);	//将当前帧的图像拷贝到抓拍图片缓存区域
		XAxiVdma_StopParking(&vdma, XAXIVDMA_READ);	//结束读通道驻停过程,继续在多帧之间进行切换
		write_sd_bmp((u8 *)bmp_addr);	//将抓拍图片缓存区域中的图像以BMP格式写入SD卡
		pic_cnt++;	//BMP图片编号累加
		sleep(3);
		#endif
	}
#endif
}

测试完成后,拔出SD卡用读卡器到电脑端直接查看内容:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

8.OV5640摄像头按键拍照测试

这部分功能为实现OV5640摄像头按键拍照,板载PS侧按键按一下拍照;
在使用之前,应在主函数中取消#define KEY_CAMERA的注释:

//#define FATFS_TEST
#define KEY_CAMERA

9.上板调试

开发板:zynq7100开发板;
开发环境:vivado2019.1;
输入:OV5640摄像头,720P,RGB888格式;
输出:HDMI输出,SD卡bmp图片;
如下:
在这里插入图片描述

10.福利领取

福利:工程代码的获取
代码太大,无法邮箱发送,以某度网盘链接方式发送,
资料获取方式:私,或者文章末尾的V名片。
网盘资料如下:
在这里插入图片描述

  • 5
    点赞
  • 35
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

9527华安

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值