ZYNQ基础----使用SD卡保存图片(3)

使用ZYNQ向SD卡中写入测试彩条

  使用在ZYNQ中有两个A9的arm核,在PS部分可以像单片机那样去访问一些常用的接口。并且Xilinx已经为这些接口的使用提供了库可以在SDK中直接使用。想要使用SD卡存储图片,首先需要在ZYNQ核中打开SD卡设置。

搭建最小系统

  在ZYNQ核中,打开SD卡,然后导出bit文件到sdk中,接下来就可以在PS端来完成调用前面所介绍的函数,从而实现向SD卡中写入数据的操作。
在这里插入图片描述

在SDK中使用FATFS文件系统

  Xilinx已经将FATFS进行了移植,在使用的时候只需要打开所支持的库即可。在创建好工程后点击BSP设置,就可以看到其中所支持的库,需要勾选xilffs。
在这里插入图片描述

头文件

  在头文件中,需要将ff.h这个头文件进行引用,然后再头文件中需要使用到文件头和信息头的结构体。数据类型WORD等等其实都是基本数据类型的重定义。

/*********** *********** *********** *********** *********** *********** ***********
* definition :struct
* Description :位图文件头
*********** *********** *********** *********** *********** *********** ***********/
#pragma pack(1)/将结构体中成员按n字节对齐
typedef struct tagBITMAPFILEHEADER
{
    WORD bfType;文件类型,必须为BM
    DWORD bfSize;///指定文件大小,以字节为单位(3-6字节,低位在前)
    WORD bfReserved1;///文件保留字,必须为0
    WORD bfReserved2;///文件保留字,必须为0
    DWORD bfOffBits;从文件头到实际位图数据的偏移字节数(11-14字节,低位在前)
}BITMAPFILEHEADER;
/*********** *********** *********** *********** *********** *********** ***********
* definition :struct
* Description :位图信息头
*********** *********** *********** *********** *********** *********** ***********/
typedef struct tagBITMAPINFOHEADER
{
	DWORD biSize;///本结构所占用字节数,为40。注意:实际操作中则有44,这是字节补齐的原因
	LONGG biWidth;///位图的宽度,以像素为单位
	LONGG biHeight;//位图的高度,以像素为单位
	WORD biPlanes;//目标设备的级别,必须为1
	WORD biBitCount;每个像素所需的位数,1(双色),4(16色),8(256色)16(高彩色),24(真彩色)或32之一
	DWORD biCompression;位图压缩类型,0(不压缩),1(BI_RLE8压缩类型)或2(BI_RLE4压缩类型)之一
	DWORD biSizeImage;//位图的大小(其中包含了为了补齐行数是4的倍数而添加的空字节),以字节为单位
	LONGG biXPelsPerMeter;///位图水平分辨率,每米像素数
	LONGG biYPelsPerMeter;///位图垂直分辨率,每米像素数
	DWORD biClrUsed;位图实际使用的颜色表中的颜色数,若该值为0,则使用颜色数为2的biBitCount次方
	DWORD biClrImportant;///位图显示过程中重要的颜色数,若该值为0,则所有的颜色都重要
}BITMAPINFOHEADER;
#pragma pack()//取消自定义字节方式

  main函数中需要定义这两个结构体的对象,并且在main函数中对这两个结构体进行赋值。本次我做的是一个1024*768大小的图像。

	//文件头结构体赋值
	bmpFile_H.bfType = 0x4d42;  // 文件类型为BMP
	bmpFile_H.bfSize = 54 + 1024*768*3;	// 文件大小存储1024*768大小的图像数据
	bmpFile_H.bfReserved1 = 0;
	bmpFile_H.bfReserved2 = 0;
	bmpFile_H.bfOffBits = 54; //图像数据相较于文件头的偏移地址

	//信息头结构体赋值
	bmpInfo_H.biSize = 40; //信息头大小
	bmpInfo_H.biWidth = 1024; //BMP图像宽
	bmpInfo_H.biHeight = 768; //BMP图像高度
	bmpInfo_H.biPlanes = 1; //目标设备级别
	bmpInfo_H.biBitCount = 24; //像素为24位真彩色
	bmpInfo_H.biCompression = 0; //不压缩
	bmpInfo_H.biSizeImage = 1024 * 768 * 3; //位图的大小
	bmpInfo_H.biXPelsPerMeter = 0;//水平分辨率
	bmpInfo_H.biYPelsPerMeter = 0;//垂直分辨率
	bmpInfo_H.biClrImportant = 0;//色彩权重
	bmpInfo_H.biClrUsed = 0 ; //使用到的颜色

写入数据函数

  然后声明两个函数,一个函数用于向SD卡中写入数据,一个用于产生测试图像。向SD中写入数据的函数实现如下:

/*********** *********** *********** *********** *********** *********** ***********
*功能:保存图片
*parameter: @ bInfoHeader: BMP文件信息头
*parameter: @ bFileHeader:BMP文件头
*parameter: @ imageSrc :图像数据源
*parameter: @ fileName :图像要保存的文件
*return : 返回值判断图片是否被正确写入
*********** *********** *********** *********** *********** *********** ***********/
int writeSdCard(
		BITMAPFILEHEADER * bFileHeader,
		BITMAPINFOHEADER * bInfoHeader,
		u8 * imageSrc,
		char * fileName
		)
{
	FATFS fatFS; //FATFS 文件结构体对象
	const char * path = "0:/";//逻辑分区的指针编号
	FIL fil;
	UINT numWriteBytes;

	FRESULT fileOK;
	fileOK = f_mount(&fatFS, path, 0); //挂载
	fileOK = f_open(&fil,fileName, FA_CREATE_ALWAYS|FA_WRITE);//创建文件并对文件进行写入
	fileOK = f_lseek(&fil, 0); //指针指向文件开始的位置
	fileOK = f_write(&fil, bFileHeader, sizeof(BITMAPFILEHEADER), &numWriteBytes);//写入文件头
	fileOK = f_write(&fil, bInfoHeader, sizeof(BITMAPINFOHEADER), &numWriteBytes);//写入信息头
	fileOK = f_write(&fil, imageSrc , 1024*768*3 + 256, &numWriteBytes);//写入图像数据
	fileOK = f_sync(&fil); //同步
	fileOK = f_close(&fil);//关闭
	if (fileOK != FR_OK )
	{
		return XST_FAILURE;
	}
	return XST_SUCCESS;
}

产生测试图像

/*********** *********** *********** *********** *********** *********** ***********
*功能:产生测试图像
*parameter: @ imageSrc 测试图像的指针
*********** *********** *********** *********** *********** *********** ***********/
void genTestImage(u8 * imageSrc)
{
	for (int idxRow = 0; idxRow < 768; idxRow++)
	{
		for (int idxCol = 0; idxCol < 1024; idxCol++)
		{
			if ( idxCol >= 0 && idxCol < 341)
			{
				*(imageSrc + (1024*idxRow + idxCol)*3) = 0xFF;
				*(imageSrc + (1024*idxRow + idxCol)*3 + 1) = 0x00;
				*(imageSrc + (1024*idxRow + idxCol)*3 + 2) = 0x00;
			}
			else if (  idxCol >= 341 && idxCol < 682)
			{
				*(imageSrc + (1024*idxRow + idxCol)*3) = 0x00;
				*(imageSrc + (1024*idxRow + idxCol)*3 + 1) = 0xFF;
				*(imageSrc + (1024*idxRow + idxCol)*3 + 2) = 0x00;
			}
			else if ( idxCol >= 682 && idxCol < 1024)
			{
				*(imageSrc + (1024*idxRow + idxCol)*3) = 0x00;
				*(imageSrc + (1024*idxRow + idxCol)*3 + 1) = 0x00;
				*(imageSrc + (1024*idxRow + idxCol)*3 + 2) = 0xFF;
			}
		}
	}
}

将SD卡插入到开发板

  将SD卡插入到开发板后,就可以运行程序,然后就可以将程序运行起来,程序运行结束后,可以将SD插入到电脑上看到SD卡中出现了一幅bmp的图像。
在这里插入图片描述
  打开可以看到产生了测试的图像。虽然出现了图像,但是图像的与期望是不一样的,是相反的,图像彩条应该是RGB排列,但是现在得到的结果是BGR排列。这是与内部数据排列有关。
在这里插入图片描述
  通过更改测试图像的数据后可以看到图像数据确实发生了变化,可以看到BMP图像的存储,可以看到是由左下角开始的。需要注意在SD卡中存储的数据是低位在前,高位在后,因此在程序中设计的想要的每个像素RGB排列变成了BGR排列。并且可以看到,在SD中存储的图片在显示的时候,第一行变成了最后一行。最后一行变成了第一行。

/*********** *********** *********** *********** *********** *********** ***********
*功能:产生测试图像
*parameter: @ imageSrc 测试图像的指针
*********** *********** *********** *********** *********** *********** ***********/
void genTestImage(u8 * imageSrc)
{
	for (int idxRow = 0; idxRow < 768; idxRow++)
	{
		for (int idxCol = 0; idxCol < 1024; idxCol++)
		{
			if ( idxRow>=0 && idxRow <200 && idxCol >= 682 && idxCol < 1024)
			{
				*(imageSrc + (1024*idxRow + idxCol)*3) = 0xFF;
				*(imageSrc + (1024*idxRow + idxCol)*3 + 1) = 0xFF;
				*(imageSrc + (1024*idxRow + idxCol)*3 + 2) = 0xFF;
			}
			else if ( idxCol >= 0 && idxCol < 341)
			{
				*(imageSrc + (1024*idxRow + idxCol)*3) = 0xFF;
				*(imageSrc + (1024*idxRow + idxCol)*3 + 1) = 0x00;
				*(imageSrc + (1024*idxRow + idxCol)*3 + 2) = 0x00;
			}
			else if (  idxCol >= 341 && idxCol < 682)
			{
				*(imageSrc + (1024*idxRow + idxCol)*3) = 0x00;
				*(imageSrc + (1024*idxRow + idxCol)*3 + 1) = 0xFF;
				*(imageSrc + (1024*idxRow + idxCol)*3 + 2) = 0x00;
			}
			else
			{
				*(imageSrc + (1024*idxRow + idxCol)*3) = 0x00;
				*(imageSrc + (1024*idxRow + idxCol)*3 + 1) = 0x00;
				*(imageSrc + (1024*idxRow + idxCol)*3 + 2) = 0xFF;
			}
		}
	}
}

在这里插入图片描述
  经过一番debug之后,最终解决了这些问题,显示的颜色顺序也就都正常了。

void genTestImage(u8 * imageSrc)
{
	for (int idxRow = 0; idxRow < 768; idxRow++)
	{
		for (int idxCol = 0; idxCol < 1024; idxCol++)
		{
			if ( idxRow>=500 && idxRow <768 && idxCol >= 682 && idxCol < 1024)
			{
				*(imageSrc + (1024*idxRow + idxCol)*3) = 0xFF;
				*(imageSrc + (1024*idxRow + idxCol)*3 + 1) = 0xFF;
				*(imageSrc + (1024*idxRow + idxCol)*3 + 2) = 0xFF;
			}
			else if ( idxCol >= 0 && idxCol < 341)
			{
				*(imageSrc + (1024*idxRow + idxCol)*3) = 0x00;
				*(imageSrc + (1024*idxRow + idxCol)*3 + 1) = 0x00;
				*(imageSrc + (1024*idxRow + idxCol)*3 + 2) = 0xFF;
			}
			else if (  idxCol >= 341 && idxCol < 682)
			{
				*(imageSrc + (1024*idxRow + idxCol)*3) = 0x00;
				*(imageSrc + (1024*idxRow + idxCol)*3 + 1) = 0xFF;
				*(imageSrc + (1024*idxRow + idxCol)*3 + 2) = 0x00;
			}
			else
			{
				*(imageSrc + (1024*idxRow + idxCol)*3) = 0xFF;
				*(imageSrc + (1024*idxRow + idxCol)*3 + 1) = 0x00;
				*(imageSrc + (1024*idxRow + idxCol)*3 + 2) = 0x00;
			}
		}
	}

在这里插入图片描述


参考:V3学院尤老师的哦

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值