1)实验平台:正点原子新起点V2开发板 2)平台购买地址:https://detail.tmall.com/item.htm?id=609758951113 2)全套实验源码+手册+视频下载地址:http://www.openedv.com/thread-300792-1-1.html 3)对正点原子FPGA感兴趣的同学可以加群讨论:994244016 4)关注正点原子公众号,获取最新资料更新
第四十七章SD卡读BMP图片LCD显示实验在“SD卡读写测试实验”中,我们成功地在开发板上实现了对SD卡的读写测试。在本次实验中,我们将学习如何从SD卡中循环读取两张BMP图片,并将其显示在LCD上。 本章分为以下几个章节: 4646.1简介 46.2实验任务 46.3硬件设计 46.4程序设计 46.5下载验证 47.1简介 我们常用的图片格式有很多,一般最常用的有四种:JPEG(或JPG)、BMP、PNG和GIF。其中JPEG(或JPG)、BMP和PNG是静态图片,而GIF则是动态图片。BMP全称是Bitmap(位图)的缩写,其特点是几乎不进行压缩,由此导致了它与生俱来的缺点,即占用磁盘空间较大;而其它三种图片格式均进行了不同程度的压缩,以节省磁盘空间。在本次实验中,我们选择使用不压缩的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位时使用调色板中颜色的索引值。 各个部分的大小如下图所示:
图 47.1.1 BMP文件各部分及其大小 我们一般见到的图像以24位图像为主,即R、G、B三种颜色各用8个bit来表示,这样的图像我们称之为真彩色。在这种情况下是不需要调色板的,位图信息头后面紧跟的就是位图数据了。也就是说,位图文件从文件头开始偏移54个字节就是图像数据了。在这里我们就以一幅24位BMP图片为例,如图 47.1.2所示,详细介绍其文件结构。
图 47.1.2 示例图片:24位BMP图片 首先我们来看一下该图片在Window中的属性信息,如下图所示:
图 47.1.3 示例图片属性 图 47.1.3中包括BMP图片的文件属性以及其图像属性,文件大小为1.09MB,图像分辨率为800*480,每个像素点的颜色使用24位表示。 接下来,我们使用Notepad++以十六进制格式打开该BMP文件,如下图所示:
图 47.1.4 示例图片16进制数据 图 47.1.4中红色矩形区域为BMP文件头,共14字节;蓝色区域为BMP信息头,共40字节;剩余部分为图像数据。左下角红色椭圆区域表明整个BMP文件共1152054个字节,除去文件头和信息头所占的54个字节,图像数据为1152000字节。由于示例图片每个像素点使用3个字节表示颜色,因此我们可以计算出图像数据的大小为8004803 = 1152000字节,与Notepad++中计算得到的结果一致。 首先来了解一下BMP文件头的数据结构,如下表所示:
我们将表 47.1.1中橙色区域与下图矩形区域中的数据一一对应:
图 47.1.5 BMP文件头 对比后可得到如下结果: 1、bf_Size:位图文件的大小为0x119436,即1152054字节(1.09MB),与示例图片属性一致。需要注意的是,在BMP文件中,如果一个数据需要用几个字节来表示的话,那么该数据的低字节存放在低地址,高字节存放在高地址; 2、bfOffBits:文件头到图像数据之间的偏移量为0x36,即54字节。这个偏移量非常有用,我们可以利用它快速定位BMP文件中的图像数据的位置。 接下来是BMP信息头的数据结构,如下表所示: 表 47.1.2 BMP信息头数据结构
同样,将表中橙色区域与下图矩形区域中的数据一一对应:
图 47.1.6 BMP信息头 对比后可得到如下结果: 1、biWidth:图像的宽度为0x320,即800像素; 2、biHeight:图像的高度为0x1e0,即480像素; 3、biBitCount:像素的位深度为0x18,等于24位,即RGB888数据格式; 4、biSizeImage:图像的大小为0x119400,即1152000字节。 BMP信息头之后,如果没有调色板,紧跟着就是BMP的位图数据了,位图数据存储了BMP有效的图像数据,其数据个数由图片的分辨率和颜色深度决定。需要说明的,BMP图像数据格式是BGR,以BMP 24位真彩色为例,颜色分量“B”位于低地址位,颜色分量“G”位于中间地址位,颜色分量“R”位于高地址位。 以上部分是对BMP图片格式的介绍,接下来结合本次实验所要实现的功能,来分析下从TF卡中读出图片数据之后,如何进行存储和显示。 我们在“SD卡读写测试实验”中介绍过,SD卡在SD2.0版本协议下,SPI模式的理论最大传输速率为50Mbps,在SDIO模式下理论传输速率为200Mbps,加上命令号以及等待SD卡返回响应信号的时间,实际上的传输速率会比理论传输速率下降不少。对于采用分辨率为800480@60Hz的LCD液晶屏来说,一幅图像的数据量达到80048016bit(RGB565为例)=6144000bit=6000Kbit(1Kbit=1024bit),每秒钟刷新60次,那么每秒钟需要传输的数据量达到6000Kbit60=360000Kbit=351.56Mbit(1Mbit=1024Kbit)。由此可以看出,SD卡的读写速度完全跟不上LCD液晶屏的刷新速度,因此必须先缓存一幅图像,再通过LCD屏显示。我们在前面多次提到过,FPGA的片内存储资源较少,对于缓存如此大量的数据,只能使用开发板上的SDRAM存储器缓存数据。 本次实验使用SDRAM存储器来缓存图片数据,图片数据来自于TF(Micro SD)卡,那么我们就需要事先向TF卡中导入两张图片,也就是从电脑中拷贝两张图片放入TF卡。由于本次实验只是从TF卡的固定扇区地址中读取图片数据,并没有实现文件系统的功能,因此需要使用WinHex软件查看两个BMP图片的扇区地址,此时查询到的扇区地址就是BMP文件存放的起始扇区地址,我们只需要按照这个起始扇区地址,按顺序读出SD卡中的数据即可,直到读完一张图片中的所有数据。 SD卡的一个扇区存放512个字节,也就是256个16位数据,对于分辨率为800480,24位真彩色的图片来说,共需要读出2250(8004803/512)个扇区数据。由于BMP图片除有些图像数据外,还有文件头和信息头共54个字节,因此还需要多读一个扇区,共2251个扇区。我们只需要将有效的图像数据写入SDRAM帧缓存中,那么LCD驱动模块就可以从帧缓存中读出数据,将图片显示在LCD液晶屏上。 我们在“SD卡读写测试实验”中对SD卡的协议规范作了详细的介绍,包括SD卡的接口说明、初始化以及读写操作等。如果大家对这部分内容不是很熟悉的话,请参考“SD卡读写测试实验”中的SD卡简介部分。 47.2实验任务 本章的实验任务是使用新起点开发板循环读取SD卡中存放的两张BMP格式图片,分辨率为800480,并将其显示在LCD液晶屏上(其它分辨率的LCD屏只需按照本章下载验证部分,稍作修改即可)。 47.3硬件设计 SD卡接口部分的硬件设计请参考“SD卡读写测试实验”中的硬件设计部分。 由于SDRAM、SD卡和LCD接口的引脚数目较多且在前面相应的章节中已经给出它们的管脚列表,这里不再列出管脚分配。 47.4程序设计 根据实验任务我们可以画出本次实验的系统框图,如下图所示。
图 47.4.1 SD卡读BMP图片LCD显示系统框图 图 47.4.1是根据本章实验任务画出的系统框图。时钟模块为其它各模块提供驱动时钟;SD卡/SDRAM参数计算模块根据LCD ID,为SD卡读取图片控制模块和SDRAM控制器模块提供参数;SD卡读取图片控制模块控制SD卡控制器的读接口,以及将SD卡中读出的RGB888格式数据转换成RGB565格式数据,写入SDRAM控制器中;最后LCD顶层模块从SDRAM控制器中读出图片数据,显示到LCD液晶屏上。 顶层模块的原理图如下图所示:
图 47.4.2 顶层模块原理图 FPGA顶层模块(sd_bmp_lcd)例化了以下六个模块:时钟模块(pll_clk)、SD卡/SDRAM参数计算模块(sd_sdram_size)、SD卡读取图片控制模块(sd_read_photo)、SD卡控制器模块(sd_ctrl_top)、SDRAM控制器模块(sdram_top)和LCD顶层模块(lcd_rgb_top)。 顶层模块(sd_bmp_lcd):顶层模块主要完成对其余各模块的例化,实现各模块之间的数据交互。需要注意的是,系统初始化完成是在SD卡以及SDRAM都初始化完成后才开始拉高的,该信号控制着SD卡读取图片控制模块的复位信号,因此SD卡读取图片控制模块是在系统初始化完成后才工作的,防止因SD卡或者SDRAM初始化未完成导致数据错误。 时钟模块(pll_clk):时钟模块通过调用时钟IP核实现,共输出4个时钟,频率分别为100Mhz、100Mhz(相位偏移-75度)、50Mhz和50Mhz(相位偏移180度)时钟。100Mhz时钟和100Mhz(相位偏移-75度)时钟作为SDRAM读写控制模块的驱动时钟;50Mhz 时钟和50Mhz(相位偏移180度)作为SD卡/SDRAM参数计算模块、SD卡读取图片控制模块、SD卡控制器模块和LCD顶层模块的驱动时钟。 SD卡/SDRAM参数计算模块(sd_sdram_size):由于不同分辨率的LCD屏,SD卡中存放的BMP分辨率不一样,所以该模块根据LCD ID,为SD卡读取图片控制模块提供需要从SD卡中的扇区个数,和SDRAM读写的最大地址。除此之外,该模块也负责将SD卡中读取的RGB888格式的数据,转换成16位RGB565数据(因为SDRAM控制器和LCD预留的用户接口都是16位)。 SD卡读取图片控制模块(sd_read_photo):SD卡读取图片控制模块通过控制SD卡控制器的读接口,从SD卡中读取图像数据,并在读完一张图片后延时一段时间,再去读取另一张图片数据,实现两张图片的循环切换读取。 SD卡控制器模块(sd_ctrl_top):SD卡控制器模块负责驱动SD卡,该模块将SD卡的SPI读写操作封装成方便用户使用的接口。有关该模块的详细介绍请大家参考“SD卡读写测试实验”章节。 SDRAM控制器模块(sdram_top):SDRAM读写控制器模块负责驱动SDRAM片外存储器,缓存从SD卡中读出的图像数据。该模块将SDRAM复杂的读写操作封装成类似FIFO的用户接口,非常方便用户的使用。有关该模块的详细介绍请大家参考“SDRAM读写测试实验”章节。 LCD顶层模块(lcd_rgb_top):LCD顶层模块根据获取到的LCD ID,驱动LCD液晶屏的显示。 时钟模块、SD卡控制器模块、SDRAM控制器模块和LCD顶层模块在前面相应的章节中都有做详细的介绍,这里不再赘述,本章节我们主要介绍SD卡/SDRAM参数计算模块和SD卡读取图片控制模块。 SD卡/SDRAM参数计算模块代码如下:
1 module sd_sdram_size (
2 input clk , //时钟
3 input rst_n , //复位,低电平有效
4
5 input [15:0] ID_lcd , //LCD ID
6
7 output reg [23:0] sdram_max_addr, //SDRAM读写最大地址
8 output reg [15:0] sd_sec_num //SD卡读扇区个数
9 );
10
11 //parameter define
12 parameter ID_4342 = 16'h4342;
13 parameter ID_4384 = 16'h4384;
14 parameter ID_7084 = 16'h7084;
15 parameter ID_7016 = 16'h7016;
16 parameter ID_1018 = 16'h1018;
17
18 //*****************************************************
19 //** main code
20 //*****************************************************
21
22 //根据LCD ID,计算SDRAM最大读写地址和SD卡读扇区个数
23 always @(posedge clk or negedge rst_n) begin
24 if(!rst_n) begin
25 sdram_max_addr
关注
打赏
最近更新
- 深拷贝和浅拷贝的区别(重点)
- 【Vue】走进Vue框架世界
- 【云服务器】项目部署—搭建网站—vue电商后台管理系统
- 【React介绍】 一文带你深入React
- 【React】React组件实例的三大属性之state,props,refs(你学废了吗)
- 【脚手架VueCLI】从零开始,创建一个VUE项目
- 【React】深入理解React组件生命周期----图文详解(含代码)
- 【React】DOM的Diffing算法是什么?以及DOM中key的作用----经典面试题
- 【React】1_使用React脚手架创建项目步骤--------详解(含项目结构说明)
- 【React】2_如何使用react脚手架写一个简单的页面?