使用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等等其实都是基本数据类型的重定义。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | /*********** *********** *********** *********** *********** *********** *********** * 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大小的图像。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | //文件头结构体赋值 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中写入数据的函数实现如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | /*********** *********** *********** *********** *********** *********** *********** *功能:保存图片 *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; } |
产生测试图像
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | /*********** *********** *********** *********** *********** *********** *********** *功能:产生测试图像 *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中存储的图片在显示的时候,第一行变成了最后一行。最后一行变成了第一行。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | /*********** *********** *********** *********** *********** *********** *********** *功能:产生测试图像 *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之后,最终解决了这些问题,显示的颜色顺序也就都正常了。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | 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学院尤老师的哦