基于Lemon ZYNQ的PS实验 二十二 5寸RGB屏实验: 用VDMA模块来缓存图像并在LCD上显示(二)显示TF卡上的BMP格式图片

本节作为前一节的补充,将TF卡上的图片通过VDMA的方式显示在RGB LCD屏幕上,作为VDMA的实战演练

因为本文内容和前一节有大量的重复雷同工作,所以本节只介绍关键的几个地方,需要看详细工程创建的请看 前一节的内容

  • 此章节内容适用于Lemon ZYNQ主板,如是其他板子请看对应板子目录
  • 本文在 vivado2018.3版本上演示
  • 备注Lemon ZYNQ 的PS输入时钟是50M,这里和其他常见的ZYNQ主板不同

本次实验需要外接本站的5寸IPS 屏幕模块,有关本次实验的 RGB屏的原理图手册以及其他例程资料可以参看下面汇总贴:5寸IPS 800X480 RGB接口LCD屏幕模块

一、VIVADO工程的修改(只增加SD使能功能,前一节已经操作)

vivado 在blockdesign里 使能SD功能,(之前工程其实已经做了这一步)

二、SDK部分的修改

1)接下来SDK部分我们作如下修改, 因为我们要加载TF卡,而TF卡的格式是FAT32的,所以这里我们需要加载FatFs库,xilinx已经帮我们集成了这部分库的功能,我们只需要使能功能就好,操作如下

2)添加 XILFFS 库

3)接下来需要使能 文件名称的功能 默认是关闭的

4)代码的编写

复制以下代码到main.c中

#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 "sleep.h"
#include "ff.h"

#define WIDTH 800
#define HEIGHT 480

#define VDMA_BASEADDR XPAR_AXI_VDMA_0_BASEADDR

#define VIDEO_BASEADDR0 0x01000000
#define VIDEO_BASEADDR1 VIDEO_BASEADDR0+WIDTH*HEIGHT*3


void load_sd_bmp(u8 *frame,unsigned char mode)
{
static FATFS fatfs;
FIL fil;
u8 bmp_head[54];
UINT *bmp_width,*bmp_height;
UINT br;
int i;

f_mount(&fatfs,"",1);

if(mode==0)f_open(&fil,"A.bmp",FA_READ);
else f_open(&fil,"B.bmp",FA_READ);

f_lseek(&fil,0);
f_read(&fil,bmp_head,54,&br);

bmp_width = (UINT *)(bmp_head + 0x12);
bmp_height = (UINT *)(bmp_head + 0x16);

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();
}

void VDMA_init(){
Xil_Out32((VDMA_BASEADDR + 0x000), 0x00000001);
Xil_Out32((VDMA_BASEADDR + 0x05c), VIDEO_BASEADDR0);
Xil_Out32((VDMA_BASEADDR + 0x060), VIDEO_BASEADDR1);
Xil_Out32((VDMA_BASEADDR + 0x058), (WIDTH*3));
Xil_Out32((VDMA_BASEADDR + 0x054), (WIDTH*3));
Xil_Out32((VDMA_BASEADDR + 0x050), HEIGHT);
Xil_Out32((VDMA_BASEADDR + 0x028), 0X00000000);
}

int main(void) {

load_sd_bmp((u8*)VIDEO_BASEADDR0,0);
load_sd_bmp((u8*)VIDEO_BASEADDR1,1);
VDMA_init();

while(1){
Xil_Out32((VDMA_BASEADDR + 0x028), 0x00000000);
sleep(1);
Xil_Out32((VDMA_BASEADDR + 0x028), 0x00000001);
sleep(1);
}
}

代码非常好理解,load_sd_bmp 实现的功能是挂载TF卡,并且根据mode的值来读取TF卡中对应名称的图片,并将图片的内容存入对应的DDR地址内。(mode 是我自己加入的,通过mode的值的大小分别载入两张不同的图片,最终在主函数里实现两张图片显示的动态切换)

VIDEO_BASEADDR0,和VIDEO_BASEADDR1分别对应两帧的缓存地址(只要两个帧之间的地址相差的位置可以调整,只要不要彼此相互有交集产生内存相互影响就可以了)

#define VIDEO_BASEADDR0 0x01000000
#define VIDEO_BASEADDR1 VIDEO_BASEADDR0+WIDTH*HEIGHT*3

本文中我们的VDMA 并没有用库函数来进行配置,而是用更简洁的Xil_Out32方式来进行初始化和控制,我们在BLOCK DESIGN 中定义了VDMA的缓存有3个,这里我们只用两个缓存来进行演示。

主程序里 加载两张照片分别到VIDEO_BASEADDR0内存区域,和VIDEO_BASEADDR1内存区域,并完成VDMA初始化

		load_sd_bmp((u8*)VIDEO_BASEADDR0,0);
		load_sd_bmp((u8*)VIDEO_BASEADDR1,1);
		VDMA_init();

主循环很容易理解,前面我们已经对缓存帧0和缓存帧1分别填了不同的图像(这些地址在之前已存入TF图片信息),这里我们通过配置028h的4-0bit来让vdma停留在我们指定的缓存帧上(前文中已将vdma 配置在非循环状态下,Park Mode)

while(1){
Xil_Out32((VDMA_BASEADDR + 0x028), 0x00000000);
sleep(1);
Xil_Out32((VDMA_BASEADDR + 0x028), 0x00000001);
sleep(1);
}

结合while(1)以及sleep,最终我们实现了让屏幕在缓存帧1和缓存帧0中以1秒为间隔来回切换最终在LCD上显示了。

备注 本节中,我们的 VDMA仍然让他工作在指定帧显示的模式下。

三、上机调试

1)之后在电脑上插入FAT32格式的TF卡,并将下列文件下载并解压并存入TF卡的根目录(切记 TF卡必须为fat32格式) HDMI 测试图片 image下载

其中A,B是800X480的两张测试图

2)将TF卡从电脑正常退出,并插入到我们主板的 TF卡卡槽中

3) 回到SDK界面,对程序进行正常编译,并debug,没问题的话,应该可以看到两张800X480的图片在循环播放的。

写在实验后:

1)如果要更换其他屏幕不同分辨率的屏幕的话,只需要对VTC的分辨率,以及Clock时钟,以及main函数分辨率对应位置进行修改即可。

2)配置VDMA的方法除了可以用直接读写寄存器的方式外,也可以调用SDK VDMADEMO中的库函数来做,这里不再

  • 本文的完整工程下载:22_VDMA_5INCH_LCD_TF_IMAGE
  • VIVADO的版本:2018.3
  • 工程创建目录:E:\Lemon_ZYNQ\SDK\21_VDMA_5INCH_LCD_COLOR_BAR

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注