1)摘自【正点原子】领航者 ZYNQ 之嵌入式开发指南

2)实验平台:正点原子领航者ZYNQ开发板
3)平台购买地址:https://item.taobao.com/item.htm?&id=606160108761
4)全套实验源码+手册+视频下载:http://www.openedv.com/docs/boards/fpga/zdyz_linhanz.html
5)对正点原子FPGA感兴趣的同学可以加群讨论:876744900
6)关注正点原子公众号,获取最新资料

第十九章SD卡读BMP图片LCD显示实验
在“SD卡读写TXT文本实验”中,我们利用FATFS在SD卡中实现了TXT文本的创建、写入与读取。在本次实验中,我们将学习如何从SD卡中读取BMP图片,并将其显示在LCD上。
本章包括以下几个部分:
1919.1简介
19.2实验任务
19.3硬件设计
19.4软件设计
19.5下载验证
19.1简介
我们常用的图片格式有很多,一般最常用的有三种:JPEG(或JPG)、BMP和GIF。其中JPEG(或JPG)和BMP是静态图片,而GIF则是可以实现动态图片。在本次实验中,我们选择使用BMP图片格式。
BMP(全称Bitmap)是Window操作系统中的标准图像文件格式,文件后缀名为“.bmp”,使用非常广。它采用位映射存储格式,除了图像深度可选以外,不采用其他任何压缩,因此,BMP文件所占用的空间很大,但是没有失真。BMP文件的图像深度可选lbit、4bit、8bit、16bit、24bit及32bit。BMP文件存储数据时,图像的扫描方式是按从下到上、从左到右的顺序。
典型的BMP图像文件由四部分组成:   
1、BMP文件头,它包含BMP图像文件的类型、大小等信息;
2、BMP信息头,它包含有BMP图像的宽、高、压缩方法,以及定义颜色等信息;
3、调色板,这个部分是可选的,如果使用索引来表示图像,调色板就是索引与其对应颜色的映射表;   
4、位图数据,即图像数据,在位深度为24位时直接使用RGB格式,而小于24位时使用调色板中颜色的索引值。
各个部分的大小如下图所示:

图 19.1.1 BMP文件各部分及其大小

我们一般见到的图像以24位图像为主,即R、G、B三种颜色各用8个bit来表示,这样的图像我们称之为真彩色。在这种情况下是不需要调色板的,位图信息头后面紧跟的就是位图数据了。也就是说,位图文件从文件头开始偏移54个字节就是图像数据了。在这里我们就以一幅24位BMP图片为例,如图 19.1.2所示,详细介绍其文件结构。

图 19.1.2 示例图片:24位BMP图片

首先我们来看一下该图片在Window中的属性信息,如下图所示:

图 19.1.3 示例图片属性

图 19.1.3中包括BMP图片的文件属性以及其图像属性,文件大小为1.09MB,图像分辨率为800*480,每个像素点的颜色使用24位表示。
接下来,我们使用Notepad++以十六进制格式打开该BMP文件,如下图所示:

图 19.1.4 示例图片16进制数据

图 19.1.4中红色矩形区域为BMP文件头,共14字节;蓝色区域为BMP信息头,共40字节;剩余部分为图像数据。左下角红色椭圆区域表明整个BMP文件共1152054个字节,除去文件头和信息头所占的54个字节,图像数据为1152000字节。由于示例图片每个像素点使用3个字节表示颜色,因此我们可以计算出图像数据的大小为800*480*3 = 1152000字节,与Notepad++中计算得到的结果一致。
首先来了解一下BMP文件头的数据结构,如下表所示:

表 19.1.1 BMP文件头数据结构

我们将表 19.1.1中橙色区域与下图矩形区域中的数据一一对应:

图 19.1.5 BMP文件头

对比后可得到如下结果:
1、bf_Size:位图文件的大小为0x119436,即1152054字节(1.09MB),与示例图片属性一致。需要注意的是,在BMP文件中,如果一个数据需要用几个字节来表示的话,那么该数据的低字节存放在低地址,高字节存放在高地址;
2、bfOffBits:文件头到图像数据之间的偏移量为0x36,即54字节。这个偏移量非常有用,我们可以利用它快速定位BMP文件中的图像数据的位置。
接下来是BMP信息头的数据结构,如下表所示:

表 19.1.2 BMP信息头数据结构

同样,将中橙色区域与下图矩形区域中的数据一一对应:

图 19.1.6 BMP信息头

对比后可得到如下结果:
1、biWidth:图像的宽度为0x320,即800像素;
2、biHeight:图像的高度为0x1e0,即480像素;
3、biBitCount:像素的位深度为0x18,即24位;
4、biSizeImage:图像的大小为0x119400,即1152000字节。
19.2实验任务
本章的实验任务是使用领航者ZYNQ开发板读取SD卡中存放的BMP格式图片,分辨率为800*480,并将其显示在LCD上。
19.3硬件设计
根据实验任务我们可以画出本次实验的系统框图,如下图所示:

图 19.3.1 系统框图

图 19.3.1与“PS通过VDMA驱动LCD显示实验”中的系统框图基本相同,其中各个模块的功能介绍请大家参考相应的章节。唯一不同的地方是,在“PS通过VDMA驱动LCD显示实验”中我们显示在LCD上的是CPU在DDR3内存中绘制的彩条图案。而在本次实验中,我们需要从SD卡中读取BMP图片,并将其写到DDR3相应的内存空间,用于LCD显示。
本次实验的硬件环境可以在“PS通过VDMA驱动LCD显示实验”的基础上搭建。由于需要读SD卡的功能,因此在配置ZYNQ7 PS模块时,需要使能SD卡控制器外设,具体方法请参考“SD卡读写TXT文本实验”中的硬件设计部分。
19.4软件设计
为了能够在软件中读取SD卡中的文件,我们需要设置BSP工程,添加并设置FATFS库。具体的方法请参考“SD卡读写TXT文本实验”软件设计部分。
接下来修改main.c文件中的代码,修改完成后代码的主体部分如下所示:

  1. 1 #include
  2. 2 #include
  3. 3 #include
  4. 4 #include "xil_types.h"
  5. 5 #include "xil_cache.h"
  6. 6 #include "xparameters.h"
  7. 7 #include "xgpio.h"
  8. 8 #include "xaxivdma.h"
  9. 9 #include "xaxivdma_i.h"
  10. 10 #include "display_ctrl/display_ctrl.h"
  11. 11 #include "vdma_api/vdma_api.h"
  12. 12 #include "ff.h"
  13. 13
  14. 14 //宏定义
  15. 15 #define BYTES_PIXEL 3 //像素字节数,RGB888占3个字节
  16. 16 #define DYNCLK_BASEADDR XPAR_AXI_DYNCLK_0_BASEADDR //动态时钟基地址
  17. 17 #define VDMA_ID XPAR_AXIVDMA_0_DEVICE_ID //VDMA器件ID
  18. 18 #define DISP_VTC_ID XPAR_VTC_0_DEVICE_ID //VTC器件ID
  19. 19 #define AXI_GPIO_0_ID XPAR_AXI_GPIO_0_DEVICE_ID //PL端 AXI GPIO 0(lcd_id)器件ID
  20. 20 #define AXI_GPIO_0_CHANEL 1 //PL按键使用AXI GPIO(lcd_id)通道1
  21. 21
  22. 22 //函数声明
  23. 23 void load_sd_bmp(u8 *frame);
  24. 24
  25. 25 //全局变量
  26. 26 XAxiVdma vdma;
  27. 27 DisplayCtrl dispCtrl;
  28. 28 XGpio axi_gpio_inst; //PL端 AXI GPIO 驱动实例
  29. 29 VideoMode vd_mode;
  30. 30 //frame buffer的起始地址
  31. 31 unsigned int const frame_buffer_addr = (XPAR_PS7_DDR_0_S_AXI_BASEADDR + 0x1000000);
  32. 32 unsigned int lcd_id=0; //LCD ID
  33. 33
  34. 34 int main(void)
  35. 35 {
  36. 36 //获取LCD的ID
  37. 37 XGpio_Initialize(&axi_gpio_inst,AXI_GPIO_0_ID);
  38. 38 lcd_id = LTDC_PanelID_Read(&axi_gpio_inst,AXI_GPIO_0_CHANEL);
  39. 39 xil_printf("LCD ID: %x",lcd_id);
  40. 40
  41. 41 //根据获取的LCD的ID号来进行video参数的选择
  42. 42 switch(lcd_id){
  43. 43 case 0x4342 : vd_mode = VMODE_480x272; break; //4.3寸屏,480*272分辨率
  44. 44 case 0x4384 : vd_mode = VMODE_800x480; break; //4.3寸屏,800*480分辨率
  45. 45 case 0x7084 : vd_mode = VMODE_800x480; break; //7寸屏,800*480分辨率
  46. 46 case 0x7016 : vd_mode = VMODE_1024x600; break; //7寸屏,1024*600分辨率
  47. 47 case 0x1018 : vd_mode = VMODE_1280x800; break; //10.1寸屏,1280*800分辨率
  48. 48 default : vd_mode = VMODE_800x480; break;
  49. 49 }
  50. 50
  51. 51 //配置VDMA
  52. 52 run_vdma_frame_buffer(&vdma, VDMA_ID, vd_mode.width, vd_mode.height,
  53. 53 frame_buffer_addr,0, 0,ONLY_READ);
  54. 54
  55. 55 //初始化Display controller
  56. 56 DisplayInitialize(&dispCtrl, DISP_VTC_ID, DYNCLK_BASEADDR);
  57. 57 //设置VideoMode
  58. 58 DisplaySetMode(&dispCtrl, &vd_mode);
  59. 59 DisplayStart(&dispCtrl);
  60. 60
  61. 61 //读取SD卡图片并显示
  62. 62 load_sd_bmp((u8*)frame_buffer_addr);
  63. 63
  64. 64 return 0;
  65. 65 }
  66. 66

主函数的代码与“PS通过VDMA驱动LCD显示实验”几乎完全相同,我们只需要将其中写彩条的函数修改为函数load_sd_bmp(u8 *frame)即可,如程序第23行和第62行所示。另外,由于对SD卡进行操作用到了FAT文件系统相关的函数,因此在程序的第12行还包含了ff.h头文件。
有关这部分代码更详细的介绍,请大家参考“PS通过VDMA驱动LCD显示实验”软件设计部分。
load_sd_bmp(u8 *frame)函数负责从SD卡中读取BMP格式的图片,并将其写入图片显存所对应的地址空间中,其代码如下所示:

  1. 67 //从SD卡中读取BMP图片
  2. 68 void load_sd_bmp(u8 *frame)
  3. 69 {
  4. 70 static FATFS fatfs;
  5. 71 FIL fil;
  6. 72 u8 bmp_head[54];
  7. 73 UINT *bmp_width,*bmp_height,*bmp_size;
  8. 74 UINT br;
  9. 75 int i;
  10. 76
  11. 77 //挂载文件系统
  12. 78 f_mount(&fatfs,"",1);
  13. 79
  14. 80 //打开文件
  15. 81 f_open(&fil,"fengjing.bmp",FA_READ);
  16. 82
  17. 83 //移动文件读写指针到文件开头
  18. 84 f_lseek(&fil,0);
  19. 85
  20. 86 //读取BMP文件头
  21. 87 f_read(&fil,bmp_head,54,&br);
  22. 88 xil_printf("fengjing.bmp head: ");
  23. 89 for(i=0;i<54;i++)
  24. 90 xil_printf(" %x",bmp_head);
  25. 91
  26. 92 //打印BMP图片分辨率和大小
  27. 93 bmp_width = (UINT *)(bmp_head + 0x12);
  28. 94 bmp_height = (UINT *)(bmp_head + 0x16);
  29. 95 bmp_size = (UINT *)(bmp_head + 0x22);
  30. 96 xil_printf(" width = %d, height = %d, size = %d bytes ",
  31. 97 *bmp_width,*bmp_height,*bmp_size);
  32. 98
  33. 99 //读出图片,写入DDR
  34. 100 for(i=*bmp_height-1;i>=0;i--){
  35. 101 f_read(&fil,frame+i*(*bmp_width)*3,(*bmp_width)*3,&br);
  36. 102 }
  37. 103
  38. 104 //关闭文件
  39. 105 f_close(&fil);
  40. 106
  41. 107 Xil_DCacheFlush(); //刷新Cache,数据更新至DDR3中
  42. 108 xil_printf("show bmp");
  43. 109 }
  44. 110

在上面的程序中,主要是通过调用FATFS库函数来读取SD卡中的BMP图片文件。本章的简介部分详细介绍了BMP图片的数据格式,我们首先要读取BMP文件前面54个字节的数据,如程序第87行所示,其中包含了BMP图片的分辨率等信息。然后在程序的92至97行,我们根据BMP信息头中各数据的偏移地址,找到并打印出图像的分辨率和大小等信息。
在读取BMP文件之前,我们先通过调用f_lseek(&fil,0)函数将文件的读写指针移动到文件开头。然后在读取54个字节的数据之后,读写指针便移动到了BMP文件中图像数据的起始位置。接下来就可以通过f_read()函数继续读取下面的图像数据。
我们需要注意的是程序的第99至102行。由于BMP文件存储数据时,图像的扫描方式是按从下到上、从左到右的顺序,因此如果我们直接将一整幅图片存入DDR显存,那么最终显示出来的将是一个上下颠倒的图片。在这里我们通过一个for循环来读取一整幅BMP图片,从上到下每次读取一行,然后把先读出来的数据放到了图片显存后面的位置。也就是说,读出来的第一行数据实际上是BMP图片的最后一行图像,因此要把它放在显存的最后一行。通过这个for循环,我们就可以将上下颠倒的图像给反过来。
最后通过调用Xil_DCacheFlush( )函数将缓存在DataCache中的数据刷新到DDR3中,供PL中的模块读取并在LCD上显示。
到这里本次实验的软件设计就介绍完了,如果大家对FATFS库函数的使用方法不熟悉的话,请参考“SD卡读写TXT文本实验”中的软件设计部分。
19.5下载验证
首先我们将下载器与领航者底板上的JTAG接口连接,下载器另外一端与电脑连接。然后使用Mini USB连接线将开发板左侧的USB_UART接口与电脑连接,用于串口通信。
接下来使用FPC排线将正点原子的RGB LCD屏幕连接到领航者底板上的LCD接口。然后把本章简介部分所给出的示例图片重命名为“fengjing.bmp”,并拷贝到SD卡的根目录下。最后将Micro SD卡插入领航者底板背面的卡槽中。
需要注意的是,拷贝到Micro SD卡中的BMP图片分辨率应与开发板所连接的LCD屏幕分辨率保持一致。我们在工程目录下新建了一个名为“风景图片”的文件夹,里面有四种不同分辨率的图片,如下图所示:

图 19.5.1 不同分辨率的BMP图片

比如本次实验使用的LCD屏幕分辨率为800*480,那么就将上图中名为“fengjing_800x480.bmp”的图片拷贝到Micro SD卡根目录下。在拷贝完成后,千万不要忘记将Micro SD中图片的名称修改为“fengjing.bmp”。
另外本次实验要求使用的Micro SD卡为FAT32格式,如果不是,那么在使用前需要将其格式化为FAT32格式。
准备工作完成之后,接下来连接开发板的电源,并打开电源开关。
在SDK软件下方的SDK Terminal窗口中点击右上角的加号来设置并连接串口。然后下载本次实验硬件设计过程中所生成的BIT文件,来对PL进行配置。最后下载软件程序,下载完成后,在下方的SDK Terminal中可以看到应用程序打印的信息,如下图所示:

图 19.5.2 串口打印信息

图 19.5.2中打印出了BMP图片的文件头和信息头等信息,与图 19.1.4中的数据保持一致。同时从数据中计算出BMP图片的宽度为800,高度为480。另外根据读出的LCD屏幕ID看出,所使用的LCD屏幕分辨率为800*480,与Micro SD卡中的BMP图片分辨率一致。如果不一致,那么屏幕上就无法正常显示图片。
LCD屏幕上显示的图片如下图所示,说明本次实验在领航者ZYNQ开发板上面下载验证成功。

图 19.5.3 下载验证

bmp文件头_「正点原子FPGA连载」第十九章SD卡读BMP图片LCD显示相关推荐

  1. 简述sd卡2.0协议_【正点原子FPGA连载】第十二章SD卡读写TXT文本实验-领航者 ZYNQ 之嵌入式开发指南...

    1)实验平台:正点原子领航者ZYNQ开发板 2)平台购买地址:https://item.taobao.com/item.htm?&id=606160108761 3)全套实验源码+手册+视频下 ...

  2. zynqsd的读写数据_【正点原子FPGA连载】 第十二章SD卡读写TXT文本实验-摘自【正点原子】领航者 ZYNQ 之嵌入式开发指南 (amobbs.com 阿莫电子论坛)...

    本帖最后由 正点原子 于 2020-10-24 10:25 编辑 QQ群头像.png (1.78 KB) 2020-10-24 10:25 上传5)关注正点原子公众号,获取最新资料 100846rel ...

  3. 【正点原子FPGA连载】第十四章SD卡读写TXT文本实验 摘自【正点原子】DFZU2EG_4EV MPSoC之嵌入式Vitis开发指南

    1)实验平台:正点原子MPSoC开发板 2)平台购买地址:https://detail.tmall.com/item.htm?id=692450874670 3)全套实验源码+手册+视频下载地址: h ...

  4. 韦东山 IMX6ULL和正点原子_「正点原子Linux连载」第十二章官方SDK移植试验

    1)实验平台:正点原子Linux开发板 2)摘自<正点原子I.MX6U嵌入式Linux驱动开发指南> 关注官方微信号公众号,获取更多资料:正点原子 第十二章官方SDK移植试验 在上一章中, ...

  5. linux键盘设置的文件在哪个文件夹,「正点原子Linux连载」第十五章按键输入试验...

    原标题:「正点原子Linux连载」第十五章按键输入试验 第十五章按键输入试验 前面几章试验都是讲解如何使用I.MX6U的GPIO输出控制功能,I.MX6U的IO不仅能作为输出,而且也可以作为输入.I. ...

  6. 扩展中断控制器8259实验_「正点原子FPGA连载」第十三章双核AMP实验

    1)摘自[正点原子]领航者 ZYNQ 之嵌入式开发指南 2)实验平台:正点原子领航者ZYNQ开发板 3)平台购买地址:https://item.taobao.com/item.htm?&id= ...

  7. 修改dts后重编译_「正点原子FPGA连载」第二十章另一种方式编译ZYNQ镜像

    1)摘自[正点原子]领航者 ZYNQ 之linux驱动开发指南 2)实验平台:正点原子领航者ZYNQ开发板 3)平台购买地址:https://item.taobao.com/item.htm?& ...

  8. 32 串口波特率_「正点原子FPGA连载」第五章串口中断实验

    1)实验平台:正点原子达芬奇FPGA开发板 2) 摘自[正点原子]达芬奇之Microblaze 开发指南 3)购买链接:https://detail.tmall.com/item.htm?id=624 ...

  9. qq自定义diy名片代码复制_「正点原子FPGA连载」第六章自定义IP核-呼吸灯实验

    1)摘自[正点原子]领航者 ZYNQ 之嵌入式开发指南 2)实验平台:正点原子领航者ZYNQ开发板 3)平台购买地址:https://item.taobao.com/item.htm?&id= ...

最新文章

  1. Linux的僵尸进程
  2. Timer计时不准确的解决方案 每次都重新调整,修正误差
  3. 1.4 计算机系统概述思维导图小结-常见问题和易混淆知识点(组成原理)
  4. 第三次学JAVA再学不好就吃翔(part3)--基础语法之常量
  5. CSS3常用属性及用法
  6. Spring 经典面试题汇总.pdf(2020版)
  7. 15个最新的HTML5及CSS3特效代码生成器
  8. PgSQL · 应用案例 · 逻辑订阅给业务架构带来了什么?
  9. (算法)最长回文子串
  10. 电脑重置后我的电脑没有了怎么办_笔记本电脑没有声音怎么办?
  11. 三维点云学习(3)8- 实现Spectral谱聚类
  12. 达观杯文本智能处理(6)
  13. 测试用例的定义,测试用例模板,测试用例的作用,测试用例编写注意事项
  14. Google测试之道读后感
  15. 华盛顿大学计算机专业硕士申请,华盛顿大学计算机科学与工程理学硕士研究生申请要求及申请材料要求清单...
  16. 中国移动的垃圾短信屏蔽算法?
  17. lintcode 输出赛程表
  18. python 检测车速_Python+树莓派监测汽车车速
  19. TypeScript 高级类型及用法
  20. 工业4.0智能工厂建设核心:APS高级计划排程

热门文章

  1. Spring配置文件中注入复杂类型属性
  2. spring bean 创建失败的常见原因
  3. Eclipse使用Tomcat发布项目时出现YadisException异常解决方案
  4. 新安装Ubuntu加载时提示“为/检查磁盘时发生严重错误”的解决方法
  5. hdu 5438 Ponds 拓扑排序
  6. Boost 1.53.0 发布,可移植的C++标准库
  7. 《OpenCV3编程入门》学习笔记3 HighGUI图形用户界面初步
  8. 仙居机器人_【101巨喜讯】又一个全国冠军!仙居学子机器人全国赛获奖啦!
  9. pip 升级_python的pip命令
  10. linux hexo写博客,自己centos7架设hexo网站