本节作为前一节的补充,将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