MYIR-ZYNQ7000系列-zturn教程(25):读取SD卡里的图片使用hdmi显示

开发板环境:vivado 2017.4 ,开发板型号xc7z010clg400-1,这个工程主要读取SD卡里的图片使用hdmi来进行显示

链接:https://pan.baidu.com/s/1QkbI0J-A_DJdUKwZKBMDDg       提取码:wp8a 

这个工程是以前面一篇博客里的hdmi显示通路上面进行更改的,所以vivado工程不变只是更改了SDK代码。

上一篇的hdmi的SDK工程和主程序

SDK工程

主程序

/*
 * Copyright (c) 2009-2012 Xilinx, Inc.  All rights reserved.
 *
 * Xilinx, Inc.
 * XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" AS A
 * COURTESY TO YOU.  BY PROVIDING THIS DESIGN, CODE, OR INFORMATION AS
 * ONE POSSIBLE   IMPLEMENTATION OF THIS FEATURE, APPLICATION OR
 * STANDARD, XILINX IS MAKING NO REPRESENTATION THAT THIS IMPLEMENTATION
 * IS FREE FROM ANY CLAIMS OF INFRINGEMENT, AND YOU ARE RESPONSIBLE
 * FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE FOR YOUR IMPLEMENTATION.
 * XILINX EXPRESSLY DISCLAIMS ANY WARRANTY WHATSOEVER WITH RESPECT TO
 * THE ADEQUACY OF THE IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO
 * ANY WARRANTIES OR REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE
 * FROM CLAIMS OF INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY
 * AND FITNESS FOR A PARTICULAR PURPOSE.
 *
 */
 
/*
 * helloworld.c: simple test application
 *
 * This application configures UART 16550 to baud rate 9600.
 * PS7 UART (Zynq) is not initialized by this application, since
 * bootrom/bsp configures it to baud rate 115200
 *
 * ------------------------------------------------
 * | UART TYPE   BAUD RATE                        |
 * ------------------------------------------------
 *   uartns550   9600
 *   uartlite    Configurable only in HW design
 *   ps7_uart    115200 (configured by bootrom/bsp)
 */
 
#include <stdio.h>
#include "platform.h"
#include "xparameters.h"
#include "xil_io.h"
#include "sleep.h"
 
 
 
#define DDR_BASEADDR        0x00000000
 
#define VDMA_BASEADDR       XPAR_AXI_VDMA_0_BASEADDR
#define H_STRIDE            1920
#define H_ACTIVE            1920
#define V_ACTIVE            1080
 
 
#define VIDEO_LENGTH  (H_STRIDE*V_ACTIVE)
#define VIDEO_BASEADDR0 DDR_BASEADDR + 0x2000000
#define VIDEO_BASEADDR1 DDR_BASEADDR + 0x3000000
#define VIDEO_BASEADDR2 DDR_BASEADDR + 0x4000000
 
//函数声明
void Xil_DCacheFlush(void);
 
 
extern const unsigned char gImage_beijing[8294400];
 
void show_img(u32 x, u32 y, u32 disp_base_addr, const unsigned char * addr, u32 size_x, u32 size_y)
{
	//计算图片 左上角坐标
	u32 i=0;
	u32 j=0;
	u32 r,g,b;
	u32 start_addr=disp_base_addr;
	start_addr = disp_base_addr + 4*x + y*4*H_STRIDE;
	for(j=0;j<size_y;j++)
	{
		for(i=0;i<size_x;i++)
		{
			b = *(addr+(i+j*size_x)*4+1);
			g = *(addr+(i+j*size_x)*4+2);
			r = *(addr+(i+j*size_x)*4+3);
			Xil_Out32((start_addr+(i+j*H_STRIDE)*4),((r<<24)|(g<<16)|(b<<8)|0x0));
		}
	}
	Xil_DCacheFlush();
}
 
int main()
{
 
    sii9022_init();
 
	//各种显示 相关的参数
	Xil_Out32((VDMA_BASEADDR + 0x000), 0x00000003); 		// enable circular mode
	Xil_Out32((VDMA_BASEADDR + 0x05c), VIDEO_BASEADDR0); 	// start address
	Xil_Out32((VDMA_BASEADDR + 0x060), VIDEO_BASEADDR0); 	// start address
	Xil_Out32((VDMA_BASEADDR + 0x064), VIDEO_BASEADDR0); 	// start address
	Xil_Out32((VDMA_BASEADDR + 0x058), (H_STRIDE*4)); 		// h offset (1920 * 4) bytes
	Xil_Out32((VDMA_BASEADDR + 0x054), (H_ACTIVE*4)); 		// h size (1920 * 4) bytes
	Xil_Out32((VDMA_BASEADDR + 0x050), V_ACTIVE); 			// v size (1080)
 
 
	while(1)
	{
		show_img(0,0,VIDEO_BASEADDR0,&gImage_beijing[0],1920,1080);
	}
 
 
}

这个读取SD卡图片工程的SDK工程和主程序

SDK工程

主程序

/*
 * Copyright (c) 2009-2012 Xilinx, Inc.  All rights reserved.
 *
 * Xilinx, Inc.
 * XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" AS A
 * COURTESY TO YOU.  BY PROVIDING THIS DESIGN, CODE, OR INFORMATION AS
 * ONE POSSIBLE   IMPLEMENTATION OF THIS FEATURE, APPLICATION OR
 * STANDARD, XILINX IS MAKING NO REPRESENTATION THAT THIS IMPLEMENTATION
 * IS FREE FROM ANY CLAIMS OF INFRINGEMENT, AND YOU ARE RESPONSIBLE
 * FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE FOR YOUR IMPLEMENTATION.
 * XILINX EXPRESSLY DISCLAIMS ANY WARRANTY WHATSOEVER WITH RESPECT TO
 * THE ADEQUACY OF THE IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO
 * ANY WARRANTIES OR REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE
 * FROM CLAIMS OF INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY
 * AND FITNESS FOR A PARTICULAR PURPOSE.
 *
 */

/*
 * helloworld.c: simple test application
 *
 * This application configures UART 16550 to baud rate 9600.
 * PS7 UART (Zynq) is not initialized by this application, since
 * bootrom/bsp configures it to baud rate 115200
 *
 * ------------------------------------------------
 * | UART TYPE   BAUD RATE                        |
 * ------------------------------------------------
 *   uartns550   9600
 *   uartlite    Configurable only in HW design
 *   ps7_uart    115200 (configured by bootrom/bsp)
 */

#include <stdio.h>
#include "platform.h"
#include "xparameters.h"
#include "xil_io.h"
#include "ff.h"
#include "sleep.h"



#define DDR_BASEADDR        0x00000000

#define VDMA_BASEADDR       XPAR_AXI_VDMA_0_BASEADDR
#define H_STRIDE            1920
#define H_ACTIVE            1920
#define V_ACTIVE            1080


#define VIDEO_LENGTH  (H_STRIDE*V_ACTIVE)
#define VIDEO_BASEADDR0 DDR_BASEADDR + 0x2000000
#define VIDEO_BASEADDR1 DDR_BASEADDR + 0x3000000
#define VIDEO_BASEADDR2 DDR_BASEADDR + 0x4000000

#define BYTES_PIXEL 3
#define DEMO_STRIDE (1920 * BYTES_PIXEL)

unsigned char read_line_buf[1920 * 3];


u8 frameBuf[1920*1080*3];

static FIL fil;		/* File object */
static FATFS fatfs;


//函数声明
void Xil_DCacheFlush(void);


void bmp_read(char * bmp,u8 *frame,u32 stride)
{
	u32 i;
	u32 r,g,b;

	short y,x;
	short Ximage;
	short Yimage;
	u32 iPixelAddr = 0;
	FRESULT res;
	unsigned char TMPBUF[64];
	unsigned int br;         // File R/W count

	res = f_open(&fil, bmp, FA_OPEN_EXISTING | FA_READ);
	if(res != FR_OK)
	{
		return ;
	}
	res = f_read(&fil, TMPBUF, 54, &br);
	if(res != FR_OK)
	{
		return ;
	}
	Ximage=(unsigned short int)TMPBUF[19]*256+TMPBUF[18];
	Yimage=(unsigned short int)TMPBUF[23]*256+TMPBUF[22];
	iPixelAddr = (Yimage-1)*stride ;

	for(y = 0; y < Yimage ; y++)
	{
		f_read(&fil, read_line_buf, Ximage * 3, &br);
		for(x = 0; x < Ximage; x++)
		{
			b = frame[x * BYTES_PIXEL + iPixelAddr + 0] = read_line_buf[x * 3 + 0];

			g = frame[x * BYTES_PIXEL + iPixelAddr + 1] = read_line_buf[x * 3 + 1];

			r = frame[x * BYTES_PIXEL + iPixelAddr + 2] = read_line_buf[x * 3 + 2];

			Xil_Out32((VIDEO_BASEADDR0 + (((1920-1-x)+(1080-1-y)*H_STRIDE)*4)) ,((r<<24)|(g<<16)|(b<<8)|0x0));

		}
		iPixelAddr -= stride;
	}

	f_close(&fil);
}

int main()
{
   u32 i;
	FRESULT rc;

    sii9022_init();

	//各种显示 相关的参数
	Xil_Out32((VDMA_BASEADDR + 0x000), 0x00000003); 		// enable circular mode
	Xil_Out32((VDMA_BASEADDR + 0x05c), VIDEO_BASEADDR0); 	// start address
	Xil_Out32((VDMA_BASEADDR + 0x060), VIDEO_BASEADDR0); 	// start address
	Xil_Out32((VDMA_BASEADDR + 0x064), VIDEO_BASEADDR0); 	// start address
	Xil_Out32((VDMA_BASEADDR + 0x058), (H_STRIDE*4)); 		// h offset (1920 * 4) bytes
	Xil_Out32((VDMA_BASEADDR + 0x054), (H_ACTIVE*4)); 		// h size (1920 * 4) bytes
	Xil_Out32((VDMA_BASEADDR + 0x050), V_ACTIVE); 			// v size (1080)


	rc = f_mount(&fatfs, "0:/", 0);
	if (rc != FR_OK)
	{
		return 0 ;
	}

	while(1)
	{
		bmp_read("1.bmp",frameBuf, DEMO_STRIDE);

	}
}

从两个程序比较可以看到这里添加了一个SD卡的读写程序和一些SD卡的文件系统之类的,主要是下面这段读写SD卡的程序

void bmp_read(char * bmp,u8 *frame,u32 stride)
{
	u32 i;
	u32 r,g,b;

	short y,x;
	short Ximage;
	short Yimage;
	u32 iPixelAddr = 0;
	FRESULT res;
	unsigned char TMPBUF[64];
	unsigned int br;         // File R/W count

	res = f_open(&fil, bmp, FA_OPEN_EXISTING | FA_READ);
	if(res != FR_OK)
	{
		return ;
	}
	res = f_read(&fil, TMPBUF, 54, &br);
	if(res != FR_OK)
	{
		return ;
	}
	Ximage=(unsigned short int)TMPBUF[19]*256+TMPBUF[18];
	Yimage=(unsigned short int)TMPBUF[23]*256+TMPBUF[22];
	iPixelAddr = (Yimage-1)*stride ;

	for(y = 0; y < Yimage ; y++)
	{
		f_read(&fil, read_line_buf, Ximage * 3, &br);
		for(x = 0; x < Ximage; x++)
		{
			b = frame[x * BYTES_PIXEL + iPixelAddr + 0] = read_line_buf[x * 3 + 0];

			g = frame[x * BYTES_PIXEL + iPixelAddr + 1] = read_line_buf[x * 3 + 1];

			r = frame[x * BYTES_PIXEL + iPixelAddr + 2] = read_line_buf[x * 3 + 2];

			Xil_Out32((VIDEO_BASEADDR0 + (((1920-1-x)+(1080-1-y)*H_STRIDE)*4)) ,((r<<24)|(g<<16)|(b<<8)|0x0));

		}
		iPixelAddr -= stride;
	}

	f_close(&fil);
}

读写SD卡程序中这两个主对读取bmp图片的行场大小,也就是图片大小

    Ximage=(unsigned short int)TMPBUF[19]*256+TMPBUF[18];
    Yimage=(unsigned short int)TMPBUF[23]*256+TMPBUF[22];

上图中可以看到TMPBUF[18] = 0x80 、TMPBUF[19] = 0x07 、TMPBUF[22] = 0x38 、TMPBUF[23] = 0x04

    Ximage=(unsigned short int)TMPBUF[19]*256+TMPBUF[18];

                 =(0x07)*256 + 0x80  (这里是十六进制)

                 = 7*256 + 128  (十进制)

                 =  1920

Yimage=(unsigned short int)TMPBUF[23]*256+TMPBUF[22];

                 =(0x04)*256 + 0x38  (这里是十六进制)

                 = 4*256 + 56  (十进制)

                 =  1080

直接打开一个bmp图片属性可以看到基本是24位的

 但我的这个hdmi显示工程vdma读取ddr是每次读取32位的,所以要将SD卡程序读取的24位图片数据拼

接为32位,我这就是对低8位添0

下面这三句主要是每次读取3个8位也就是读取一个24位

            b = frame[x * BYTES_PIXEL + iPixelAddr + 0] = read_line_buf[x * 3 + 0];

            g = frame[x * BYTES_PIXEL + iPixelAddr + 1] = read_line_buf[x * 3 + 1];

            r = frame[x * BYTES_PIXEL + iPixelAddr + 2] = read_line_buf[x * 3 + 2];

下面这句就是将低8位直接补0凑成一个32位数据

            ((r<<24)|(g<<16)|(b<<8)|0x0));

下面就是往VDMA所读取的DDR地址空间写入读取的SD卡图片数据

Xil_Out32((VIDEO_BASEADDR0 + ((x+y*H_STRIDE)*4)) ,((r<<24)|(g<<16)|(b<<8)|0x0));

下面是显示效果

可以看到图片是倒着显示的,说明这个SD卡图片应该是倒着写入进去的,只要将图片再倒着写入DDR就可以显示正常图片了

Xil_Out32((VIDEO_BASEADDR0 + (((1920-1-x)+(1080-1-y)*H_STRIDE)*4)) ,((r<<24)|(g<<16)|(b<<8)|0x0));

也就是像上面这样用直接用1920和1080去减掉不断增加的行场坐标就相当于倒着写入到DDR,就可以正常显示图片了

显示效果

工程主要是将放到SD卡里的图片读取到DDR并且通过hdmi显示,所以先将工程生成的BOOT.bin拷贝到SD卡

再到SD卡里放一个1920*1080的1.bmp图片,这里要注意的是图片不能直接将网上下载的jpg图片直接更改扩展名为bmp,

这样更改的图片数据格式是无法更改过来的,要么直接下载一个bmp的1080p图片,要么下载一个1080p的jpg图片用

图片转换器转换为bmp格式的,直接更改扩展名为bmp的图片是无法读取的这里一定要注意。

最后比较SD卡里的图片和显示的图片是左右颠倒的虽然图片上下颠倒已经倒过来了,大家可以想一下如何将左右颠倒

给倒过来我这里暂时不进行说明,大家可以在纸上画一个上下颠倒的图片最后如何变为正常图片再对写入的DDR程序进

更改就行了。

  • 5
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值