学习内容
本文使用带有HDMI接口的显示器,构建图像视频显示的测试工程,利用VDMA进行传输图像视频数据,通过文件系统将SD卡中的照片读取出来然后在显示器显示。
开发环境
vivado 18.3&SDK,PYNQ-Z2开发板。
准备工作
所用到的IP:VDMA、video out IP、Video Timing Controller、动态时钟配置 IP和DVI IP。
详细介绍参考前文:
- ZYNQ-AXI_VDMA IP简介
- ZYNQ-Video out IP和Video Timing Controller IP简介
- ZYNQ-使用HDMI显示器进行VDMA彩条显示测试
- ZYNQ-使用SD卡读写文本数据
系统框图
通过控制器(MCU)把图片数据从sd卡中读出,缓存到VDMA。然后通过AXI-stream to video out IP和VTC IP将视频数据转换为普通的视频接口的时序信号,然后通过GP0控制视频时序输出,,由显示器显示输出图片。
硬件平台搭建
前文在进行zynq7 ip核配置时,勾选了SD卡的资源,所以这里可以直接进行使用前文的构建完成的硬件平台。
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
- 正点原子ZYNQ开发视频