ZYNQ-使用HDMI显示器进行SD卡图片读取显示

本文介绍如何在ZYNQ平台上,利用VDMA、videooutIP等组件,从SD卡读取BMP图片并通过HDMI显示器显示。首先配置好开发环境和硬件平台,然后通过SDK编写程序,读取SD卡中的图片数据,并通过VDMA传输到视频输出接口,最终在显示器上呈现图片。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

学习内容

本文使用带有HDMI接口的显示器,构建图像视频显示的测试工程,利用VDMA进行传输图像视频数据,通过文件系统将SD卡中的照片读取出来然后在显示器显示。

开发环境

vivado 18.3&SDK,PYNQ-Z2开发板。

准备工作

所用到的IP:VDMA、video out IP、Video Timing Controller、动态时钟配置 IP和DVI IP。
详细介绍参考前文:

  1. ZYNQ-AXI_VDMA IP简介
  2. ZYNQ-Video out IP和Video Timing Controller IP简介
  3. ZYNQ-使用HDMI显示器进行VDMA彩条显示测试
  4. ZYNQ-使用SD卡读写文本数据

系统框图

通过控制器(MCU)把图片数据从sd卡中读出,缓存到VDMA。然后通过AXI-stream to video out IP和VTC IP将视频数据转换为普通的视频接口的时序信号,然后通过GP0控制视频时序输出,,由显示器显示输出图片。
在这里插入图片描述

硬件平台搭建

前文在进行zynq7 ip核配置时,勾选了SD卡的资源,所以这里可以直接进行使用前文的构建完成的硬件平台。

ZYNQ-使用HDMI显示器进行VDMA彩条显示测试

SDK软件部分

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "xil_types.h"
#include "xil_cache.h"
#include "xparameters.h"
#include "xaxivdma.h"
#include "xaxivdma_i.h"
#include "display_ctrl_hdmi/display_ctrl.h"
#include "vdma_api/vdma_api.h"
#include "ff.h"

//宏定义
#define BYTES_PIXEL        3                          //像素字节数,RGB888占3个字节
#define DYNCLK_BASEADDR    XPAR_AXI_DYNCLK_0_BASEADDR //动态时钟基地址
#define VDMA_ID            XPAR_AXIVDMA_0_DEVICE_ID   //VDMA器件ID
#define DISP_VTC_ID        XPAR_VTC_0_DEVICE_ID       //VTC器件ID

//函数声明
void load_sd_bmp(u8 *frame);

//全局变量
XAxiVdma     vdma;
DisplayCtrl  dispCtrl;
VideoMode    vd_mode;
//frame buffer的起始地址
unsigned int const frame_buffer_addr = (XPAR_PS7_DDR_0_S_AXI_BASEADDR + 0x1000000);
unsigned int lcd_id=0;        //LCD ID

int main(void)
{
	xil_printf("HDMI Display 1920*1080 \r\n");

	//设置video参数,分辨率:1920*1080
	vd_mode = VMODE_1920x1080;
	//配置VDMA
	run_vdma_frame_buffer(&vdma, VDMA_ID, vd_mode.width, vd_mode.height,frame_buffer_addr,0, 0,ONLY_READ);
    //初始化Display controller
	DisplayInitialize(&dispCtrl, DISP_VTC_ID, DYNCLK_BASEADDR);
    //设置VideoMode
	DisplaySetMode(&dispCtrl, &vd_mode);
	DisplayStart(&dispCtrl);

	//读取SD卡图片并显示
	load_sd_bmp((u8*)frame_buffer_addr);

    return 0;
}

//从SD卡中读取BMP图片
void load_sd_bmp(u8 *frame)
{
	static 	FATFS fatfs;
	FIL 	fil;
	u8		bmp_head[54];
	UINT 	*bmp_width,*bmp_height,*bmp_size;
	UINT 	br;
	int 	i;

	//挂载文件系统
	f_mount(&fatfs,"",1);
	//打开文件
	f_open(&fil,"huawei.bmp",FA_READ);
	//移动文件读写指针到文件开头
	f_lseek(&fil,0);
	//读取BMP文件头
	f_read(&fil,bmp_head,54,&br);
	xil_printf("huawei.bmp head: \n\r");
	for(i=0;i<54;i++)
		xil_printf(" %x",bmp_head[i]);

	//打印BMP图片分辨率和大小
	bmp_width  = (UINT *)(bmp_head + 0x12);
	bmp_height = (UINT *)(bmp_head + 0x16);
	bmp_size   = (UINT *)(bmp_head + 0x22);
	xil_printf("\n width = %d, height = %d, size = %d bytes \n\r",
			*bmp_width,*bmp_height,*bmp_size);
	//读出图片,写入DDR
	for(i=*bmp_height-1;i>=0;i--){
		f_read(&fil,frame+i*(*bmp_width)*3,(*bmp_width)*3,&br);
	}

	//关闭文件
	f_close(&fil);

	Xil_DCacheFlush();     //刷新Cache,数据更新至DDR3中
	xil_printf("show bmp\n\r");
	while(1){}
}

运行效果

在这里插入图片描述

Reference

  1. 正点原子ZYNQ开发视频
### Zynq 平台 SD BMP 文件读写操作 #### 实现概述 为了实现在Zynq平台上的SD对BMP文件的读写功能,需了解几个关键方面:首先是硬件配置部分,即如何初始化并配置SD控制器;其次是软件层面,涉及FAT文件系统的处理以及具体的图像数据解析。 #### 硬件配置与初始化 ZYNQ中的SD控制器遵循SD2.0协议标准[^3]。这意味着该设备能够兼容多种存储介质,并提供高速的数据传输能力。对于开发者而言,首要任务是在启动阶段正确地初始化这个外设模块。通常情况下,这一步骤会通过调用Xilinx提供的库函数完成,比如`XSdPs_CfgInitialize()`用于设定工作模式(如SPI或四线SD)、时钟频率等参数。 #### FAT 文件系统支持 当涉及到具体的应用场景——像访问位于SD内的特定类型的文件(这里是BMP),则离不开有效的文件管理机制。由于大多数商用级microSD都预格式化成了FAT32格式,因此应用程序应该集成相应的驱动来识别这种结构下的目录项和簇链表。值得注意的是,在某些版本的FatFs组件里,默认可能不开启长文件名的支持特性(`use_lfn`),而将其置为1可以允许程序正常处理较长命名的资源[^2]。 #### BMP 图像加载流程 针对BMP位图的具体读入过程如下: - 打开目标路径下指定名称的二进制流; - 解析BITMAPFILEHEADER头部信息以获取后续偏移量; - 继续解码紧跟其后的INFOHEADER字段从而得知宽度、高度及颜色深度属性; - 根据上述元数据分配适当大小的目标缓冲区; - 将实际像素数组复制到内存空间内供进一步分析或显示。 下面给出一段简化版C语言伪代码作为参考实现方式之一: ```c #include "ff.h" // ...其他必要的头文件... void LoadBmpFromSd(const char* pathToFille, unsigned char **imageData){ FIL fil; FRESULT fr; //尝试打开文件 fr = f_open(&fil, pathToFile, FA_READ); if(fr != FR_OK) { printf("Failed to open file [%s]\n",pathToFile ); return ; } BITMAPFILEHEADER bfh; BITMAPINFOHEADER bih; UINT br; //读取文件头 f_read(&fil,&bfh,sizeof(BITMAPFILEHEADER),&br); //跳过无关紧要的部分直到到达DIB header位置 f_lseek(&fil,bfh.bfOffBits-sizeof(BITMAPINFOHEADER)); //读取DIB header f_read(&fil,&bih,sizeof(BITMAPINFOHEADER),&br); int width=bih.biWidth; int height=abs(bih.biHeight); //注意biHeight可能是负数表示自底向上编码 *imageData=(unsigned char*)malloc(width*height*bih.biBitCount/8); //定位至图像数据起始处再执行批量搬运动作 f_lseek(&fil,bfh.bfOffBits); f_read(&fil,*imageData,width*height*bih.biBitCount/8 , &br ); f_close(&fil); } ```
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

FPGA and ICer

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值