本文共 3559 字,大约阅读时间需要 11 分钟。
1. 系统概述
本设计采用NIOS2 32位处理器,通过SPI接口将SD/TF卡中的BMP图片数据读取到内存中,SD/TF卡的文件系统为FAT32,NIOS2软件实现BMP解码后,启动framereader和Clocked Video Output模块,最终在VGA显示器上显示BMP图像,系统框图如下:
2. BMP格式
BMP(Bitmap)是Windows操作系统中的标准图像文件格式,采用位映射存储格式,没有采用任何压缩技术。图像深度可为1、4、8和24bit,图像的扫描方式是按照从左到右、从下到上的顺序。
BMP图像文件由四部分组成:
位图头文件数据结构
位图信息数据结构
调色板(可选)
位图数据
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 | //位图文件头 typedef struct tagBITMAPFILEHEADER { WORD bfType; //位图文件的类型,必须为BM-0x424d(1-2字节) DWORD bfSize; //位图文件的大小,以字节为单位(3-6字节,低位在前) WORD bfReserved1; //位图文件保留字,必须为0(7-8字节) WORD bfReserved2; //位图文件保留字,必须为0(9-10字节) DWORD bfOffBits; //位图数据的起始位置,以相对于位图(11-14字节,低位在前) //文件头的偏移量表示,以字节为单位 }BITMAPFILEHEADER; //位图信息头 typedef struct tagBITMAPINFOHEADER{ DWORD biSize; //本结构所占用字节数(15-18字节) LONG biWidth; //位图的宽度,以像素为单位(19-22字节) LONG biHeight; //位图的高度,以像素为单位(23-26字节) WORD biPlanes; //目标设备的级别,必须为1(27-28字节) WORD biBitCount; //每个像素所需的位数,必须是1(双色),(29-30字节) //4(16色),8(256色)16(高彩色)或24(真彩色)之一 DWORD biCompression; //位图压缩类型,必须是0(不压缩),(31-34字节) //1(BI_RLE8压缩类型)或2(BI_RLE4压缩类型)之一 DWORD biSizeImage; //位图的大小(其中包含了为了补齐行数是4的倍数而添加的空字节),以字节为单位(35-38字节) LONG biXPelsPerMeter; //位图水平分辨率,每米像素数(39-42字节) LONG biYPelsPerMeter; //位图垂直分辨率,每米像素数(43-46字节) DWORD biClrUsed; //位图实际使用的颜色表中的颜色数(47-50字节) DWORD biClrImportant; //位图显示过程中重要的颜色数(51-54字节) }BITMAPINFOHEADER; |
3. 搭建Qsys
在博文的基础上,在Qsys平台上添加framereader和Clocked Video Output组件,设置分辨率为640*480,VGA相关内容可以参考博文。
搭好的Qsys平台如下图:
4. NIOS2软件设计
往SD卡中保存一幅分辨率为640*480的24位BMP格式图片,图片名为:friend.bmp,电脑中打卡如下图:
在博文的软件基础上,编写软件代码。
由于图像是24位图,没有调色板信息,所以软件只要按照BMP格式偏移54个字节后,读取的便是第一个图像字节数据。VGA显示部分,要对framereader组件初始化,然后存放在数组中的图像数据便会不停地被读取到Clocked Video Output模块,最后数据会被送到VGA编码芯片显示。软件代码设计如下:
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 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 | //filename: main.c //author: shugen.yin //date: 2016.12.29 //function: BMP decode and VGA show #include <stdio.h> #include <system.h> #include <string.h> #include <io.h> #include "unistd.h" #include "sd_spi.h" #include "ff.h" #include "altera_avalon_pio_regs.h" #define FRAME_ADDR (framebuf0 + 0x00000000) #define FRAME_WIDTH 640 #define FRAME_HEIGHT 480 #define FRAME_SIZE (FRAME_WIDTH*FRAME_HEIGHT) unsigned int framebuf0[FRAME_SIZE]; void FrameRd_init(){ IOWR(ALT_VIP_VFR_0_BASE, 3, 0); // Frame Select IOWR(ALT_VIP_VFR_0_BASE, 4, framebuf0); // Frame 0 Base Address IOWR(ALT_VIP_VFR_0_BASE, 5, FRAME_SIZE/8); // Frame 0 Words => 640*480 IOWR(ALT_VIP_VFR_0_BASE, 6, FRAME_SIZE); // Frame 0 Single Cycle Color Patterns IOWR(ALT_VIP_VFR_0_BASE, 7, 0); // Frame 0 Reserved Bit IOWR(ALT_VIP_VFR_0_BASE, 8, FRAME_WIDTH); // Frame 0 Width IOWR(ALT_VIP_VFR_0_BASE, 9, FRAME_HEIGHT); // Frame 0 Height IOWR(ALT_VIP_VFR_0_BASE, 10, 3); // Frame 0 Interlaced => 3 = 0011 bedeutet progressive output IOWR(ALT_VIP_VFR_0_BASE, 0, 1); // start Frame Reader } void frame_init(){ BYTE pic_buf[FRAME_SIZE*3+54]; UINT i; UINT j=0; f_mount(&fs, "" ,0); res=f_open(&fdst, "0:/friend.bmp" , FA_READ); if (res==FR_OK) { res = f_read(&fdst,pic_buf,FRAME_SIZE*3+54,&br); f_close(&fdst); } printf ( "file read success!\n" ); for (i=54;i<FRAME_SIZE*3+54;i=i+3) { j++; framebuf0[FRAME_SIZE-j] = pic_buf[i]+(pic_buf[i+1])*256+(pic_buf[i+2])*65536; } printf ( "image processed done!\n" ); } int main ( void ) { frame_init(); FrameRd_init(); while (1); return 0; } |
5. 编译运行
编译成功后,以Hardware方式运行,终端打印:file read success! image processed done!
6. 最终结果
图片正常显示,和电脑上打开的friend.bmp一致。
本文转自 shugenyin 51CTO博客,原文链接:http://blog.51cto.com/shugenyin/1887551
转载地址:http://anmjo.baihongyu.com/