本文是zynq 7000 的HDMI 显示实验 一文的继续,在上文中显示的内容包含在代码中,而本文直接显示SD卡里的BMP图片文件。
你必须先完成了zynq 7000 的HDMI 显示实验 ,才能本实验。
代码下载:
链接:https://pan.baidu.com/s/11-RLOYtl1AyxcQ_XGbw2YQ
提取码:zvnc
hdmiSDsrc.zip 是本文代码 17k, satan.zip是样本图片的压缩,其他是上文的内容
本实验的硬件设计基本与zynq 7000 的HDMI 显示实验 相同,所以不必重新建立新的工程,打开其 Vivado 工程,另存为一个新的工程并明命名为“ sd_hdmi_out” ,如下图所示,完成之后打开工程文件夹,删除.sdk 文件夹,这是上一个实验的程序,本实验不需要。
之后软件会自动打开这个工程,点击“ Open Block Design”,打开设计文件。因为本实验要读取 SD 卡的数据,所以要使能 SD0。 双击 ZYNQ7 Processing System打开设置页面,使能 SD0, 如下如图所示(这个要根据你SD卡硬件情况设置):
之后点击“ OK”并保存设置。接着重新生成顶层 HDL。点击 Generate Bitstream 生成新的 BIT 流文件。
生成完成后导出硬件(File->Export->Export Hardware),导出时勾选 Include bitstream。
硬件部分就完成了。File ->Launch SDK 我们就进入软件设计部分。
在打开的 SDK 软件中新建一个应用工程并命名为“ hdmi_sd”,工程模板选择空白。在本实验中,我们需要读取 SD 卡中的文件,所以添加文件系统以支持对于文件的操作, 点击 Modify this BSP’s Settings 进入设置页面, 如下图所示:
一般建立新工程后会是这个界面,如果不出现,记得点bsp 目录下的system.mss。
勾选下方的 xilffs,软件会自动添加相关文件到工程中,如下图所示:
之后可以看到相关文件已加入工程。
之 后 打 开下载链接的文件并复制,或者微相 资 料 例 程 目 录 SDK_Demo\ 18_sd_hdmi_out\sd_hdmi_out\sd_hdmi_out.sdk, 复制其中的 src 文件夹,保存到新建工程的相同位置,提示相同文件跳过不要替换。之后在 SDK 软件下右键点击工程,点击 Refresh 重新编译即可。
打开 display_demo.c 主程序文件, 我们可以看到本实验在之前实验的基础上增加了读取图片文件的函数 bmp_read。 在函数中使用 f_open 文件操作函数打开图片文件,然后读取前 54 字节的图像头文件,获取图像像素等属性信息,之后按照从下往上,从左往右的顺序读取像素数据。这样我们就获得了图片的全部像素数据,相当于之前实验用到的几个图片数据的头文件。在成功获取到图片的数据之后,我们就可以按照之前实验的步骤, 将数据写入 VDMA 的缓存中,再通过 HDMI 接口显示到屏幕上。
对比上个实验的代码,就是bmp_read 代替了DemoPrintTest。现在从图片文件读取显示数据,而后者是从头文件预赋值的变量,共同点都是送入显示区DDR。
#include
#include
#include
#include
#include "xil_types.h"
#include "xil_cache.h"
#include "xparameters.h"
#include "display_demo.h"
#include "display_ctrl/display_ctrl.h"
#include "display_ctrl/vga_modes.h"
#include "ff.h"
/*
* XPAR redefines
*/
#define DYNCLK_BASEADDR XPAR_AXI_DYNCLK_0_BASEADDR
#define VGA_VDMA_ID XPAR_AXIVDMA_0_DEVICE_ID
#define DISP_VTC_ID XPAR_VTC_0_DEVICE_ID
/* ------------------------------------------------------------ */
/* Global Variables */
/* ------------------------------------------------------------ */
/*
* Display Driver struct
*/
DisplayCtrl dispCtrl;
XAxiVdma vdma;
static FIL fil; /* File object */
static FATFS fatfs;
/*
* Frame buffers for video data
*/
u8 frameBuf[DISPLAY_NUM_FRAMES][DEMO_MAX_FRAME];
u8 *pFrames[DISPLAY_NUM_FRAMES]; // array of pointers to the frame buffers
/* ------------------------------------------------------------ */
/* Procedure Definitions */
/* ------------------------------------------------------------ */
unsigned char read_line_buf[1920 * 4];
void bmp_read(char * bmp,u8 *frame,u32 stride)
{
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++)
{
frame[x * BYTES_PIXEL + iPixelAddr + 0] = read_line_buf[x * 3 + 0];
frame[x * BYTES_PIXEL + iPixelAddr + 1] = read_line_buf[x * 3 + 1];
frame[x * BYTES_PIXEL + iPixelAddr + 2] = read_line_buf[x * 3 + 2];
}
iPixelAddr -= stride;
}
f_close(&fil);
}
int main(void)
{
int i;
int Status;
XAxiVdma_Config *vdmaConfig;
FRESULT rc;
/*
* Initialize an array of pointers to the 3 frame buffers
*/
for (i = 0; i < DISPLAY_NUM_FRAMES; i++)
{
pFrames[i] = frameBuf[i];
}
/*
* Initialize VDMA driver, get the hardware VDMA configurations
*/
vdmaConfig = XAxiVdma_LookupConfig(VGA_VDMA_ID);
if (vdmaConfig == NULL)
{
xil_printf("No video DMA found for ID %d\r\n", VGA_VDMA_ID);
}
/*
* Use hardware VDMA configurations to initialize the driver
*/
Status = XAxiVdma_CfgInitialize(&vdma, vdmaConfig, vdmaConfig->BaseAddress);
if (Status != XST_SUCCESS)
{
xil_printf("VDMA Configuration Initialization failed %d\r\n", Status);
}
/*
* Initialize the Display controller and start it
*/
VideoMode VMODE = VMODE_1920x1080;
Status = DisplayInitialize(&dispCtrl, &vdma, DISP_VTC_ID, DYNCLK_BASEADDR, pFrames, DEMO_STRIDE, VMODE);
if (Status != XST_SUCCESS)
{
xil_printf("Display Ctrl initialization failed during demo initialization%d\r\n", Status);
}
Status = DisplayStart(&dispCtrl);
if (Status != XST_SUCCESS)
{
xil_printf("Couldn't start display during demo initialization%d\r\n", Status);
}
rc = f_mount(&fatfs, "0:/", 0);
if (rc != FR_OK)
{
return 0 ;
}
bmp_read("shatan.bmp",dispCtrl.framePtr[dispCtrl.curFrame], DEMO_STRIDE);
Xil_DCacheFlushRange((unsigned int) dispCtrl.framePtr[dispCtrl.curFrame], DEMO_MAX_FRAME);
return 0;
}
main 函数:
先初始化pFrames(frame buffers 的指针)
get the hardware VDMA configurations :vdmaConfig
初始化驱动
显示启动。
安装并打开文件"shatan.bmp"
最后通过函数bmp_read把显示数据复制到显示缓存,图像就显示了
程序结束
程序编译完成之后,将例程文件夹下的示例图片拷贝到 SD 卡中,就可在开发板上下载验证了。
连接好开发板的串口线和下载线,使用 HDMI 线连接 HDMI 接口和显示器。将拷贝好示例图片的 SD 卡插入卡槽。点击菜单栏 Run->Run Configuration 进入烧录设置页面,按照下图所示设置相关设置。
设置完成后点击“ Run” 烧录程序,即可看到屏幕上如下图所示显示示例图片。
这里说明下图形文件要求,文件名是:shatan.bmp,这是程序里打开的文件名,如果改名,就要修改软件里的文件名,放在根目录下。文件是一个1900x1600 的24bits 图形文件。
如果要打开其他分辨率的文件,VideoMode VMODE = VMODE_1920x1080; 这个要改。我没尝试。
如果要打开不是 24位 bmp 图片,那就要了解文件结构,再修改软件bmp_read的代码了,这个有点难度,建议不要这样,可以改图片为24位。
介绍到此。