您的位置:首页 > 其它

ZYNQ基础系列(四)VTC+VDMA+Vid_Out核 开始构建一个简单的显示通路

2018-01-15 16:49 651 查看

ZYNQ7010把SD卡的图片显示到HDMI

ZYNQ基础系列(三)中有相关IP核的初步介绍,在已有的基础上可以搭建一个基础的显示通路了

实验目的:在Mi701N开发板的基础上,驱动800*600的显示屏输出图片(图片文件[.bin文件]存放SD卡中)

一、PL部分实现

大体框图:



AXI接口连接模块和复位模块是通过自动生成的

rgb2dvi模块:用于IO口输出HDMI信号 [在ZYNQ基础系列(二)],也可以不加该模块直接以VGA形式输出,或者加一个驱动HDMI芯片的IP核输出

PS模块:注意根据板子具体情况设置PS时钟和PL时钟以及DDR型号

CLOCK模块:PS倍频到100M的时钟输出(图中红色线)作为CLOCK模块的输入,由于分辨率是800*600的,所以时钟clock1输出40M,clock2是clock1的5倍,200M,(两个输出时钟,图中青色线),该模块的lock信号作为显示通路的复位信号

VTC、VDMA和Vid_Out核的配置,和上一文中的一样

二、制作图片文件

Image2Lcd工具



按照如上设置,将.bin图片文件,导出

三、SDK部分实现

初始化:首先PS通过AXI总线配置PL的工作模式

工作:从SD卡中读取图片文件,然后PS将图片数据写入DDR,PL不断从DDR中读取数据,然后通过视频通路,显示在屏幕上

设置开启xilinx自带的文件系统的库:



如图将xilffs勾选(否则提示找不到 ff.h 文件):



勾选此库之后,就可以使用文件系统相关的函数了

等下的代码中,
SD_Init
SD_Transfer_read
分别是初始化SD卡和读取SD卡中的文件内容(.bin文件)

将读取的.bin数据存到DDR中:

等下的代码中,
show_img
函数,将完成数据存到DDR相应地址的操作

对PL中的VDMA的配置:

通过PS完成对VDMA的初始化,详先上一文

PS完整代码:

#include "xaxivdma.h"
#include "xaxivdma_i.h"
#include "sleep.h"

#include <string.h>
#include "xparameters.h"
#include "xil_printf.h"
#include "ff.h"
#include "xdevcfg.h"

#define DDR_BASEADDR        0x00000000
#define VDMA_BASEADDR       XPAR_AXI_VDMA_0_BASEADDR
#define H_STRIDE            800
#define H_ACTIVE            800
#define V_ACTIVE            600

#define VIDEO_BASEADDR0 DDR_BASEADDR + 0x1000000
#define VIDEO_BASEADDR1 DDR_BASEADDR + 0x2000000
#define VIDEO_BASEADDR2 DDR_BASEADDR + 0x3000000

void Xil_DCacheFlush(void);

unsigned char picture1[800*600*3]={0};
static FATFS fatfs;

void show_img(u32 x, u32 y, u32 disp_base_addr, unsigned char * addr, u32 size_x, u32 size_y)
{
u32 i=0;
u32 j=0;
u32 r,g,b;
u32 start_addr=disp_base_addr;
start_addr = disp_base_addr + 4*x + y*4*H_STRIDE;
for(j=0;j<size_y;j++)
{
for(i=0;i<size_x;i++)
{
b = *(addr+(i+j*size_x)*3+0);
g = *(addr+(i+j*size_x)*3+1);
r = *(addr+(i+j*size_x)*3+2);
Xil_Out32((start_addr+(i+j*H_STRIDE)*4),((r<<16)|(g<<8)|(b<<0)|0x0));
}
}
Xil_DCacheFlush();
}

int SD_Init()
{
FRESULT rc;
rc = f_mount(&fatfs,"",0);
if(rc)
{
xil_printf("ERROR : f_mount returned %d\r\n",rc);
return XST_FAILURE;
}
return XST_SUCCESS;
}
int SD_Transfer_read(char *FileName,u32 DestinationAddress,u32 ByteLength)
{
FIL fil;
FRESULT rc;
UINT br;
rc = f_open(&fil,FileName,FA_READ);
if(rc)
{
xil_printf("ERROR : f_open returned %d\r\n",rc);
return XST_FAILURE;
}
rc = f_lseek(&fil, 0);
if(rc)
{
xil_printf("ERROR : f_lseek returned %d\r\n",rc);
return XST_FAILURE;
}
rc = f_read(&fil, (void*)DestinationAddress,ByteLength,&br);
if(rc)
{
xil_printf("ERROR : f_read returned %d\r\n",rc);
return XST_FAILURE;
}
rc = f_close(&fil);
if(rc)
{
xil_printf(" ERROR : f_close returned %d\r\n", rc);
return XST_FAILURE;
}
return XST_SUCCESS;
}

int main(void)
{
u32 i;
xil_printf("Starting the first VDMA \n\r");

//VDMA configurateAXI VDMA0
/*****************往DDR写数据设置**********************/
//Xil_Out32((VDMA_BASEADDR + 0x030), 0x3);// enable circular mode
//Xil_Out32((VDMA_BASEADDR + 0x0AC), VIDEO_BASEADDR0);  // start address
//Xil_Out32((VDMA_BASEADDR + 0x0B0), VIDEO_BASEADDR1);  // start address
//Xil_Out32((VDMA_BASEADDR + 0x0B4), VIDEO_BASEADDR2);  // start address
//Xil_Out32((VDMA_BASEADDR + 0x0A8), (H_STRIDE*4));     // h offset (800 * 4) bytes
//Xil_Out32((VDMA_BASEADDR + 0x0A4), (H_ACTIVE*4));     // h size (600 * 4) bytes
//Xil_Out32((VDMA_BASEADDR + 0x0A0), V_ACTIVE);         // v size (600)
/*****************从DDR读数据设置**********************/
Xil_Out32((VDMA_BASEADDR + 0x000), 0x3);        // enable circular mode
Xil_Out32((VDMA_BASEADDR + 0x05c), VIDEO_BASEADDR0);    // start address
Xil_Out32((VDMA_BASEADDR + 0x060), VIDEO_BASEADDR1);    // start address
Xil_Out32((VDMA_BASEADDR + 0x064), VIDEO_BASEADDR2);    // start address
Xil_Out32((VDMA_BASEADDR + 0x058), (H_STRIDE*4));       // h offset (800 * 4) bytes
Xil_Out32((VDMA_BASEADDR + 0x054), (H_ACTIVE*4));       // h size (800 * 4) bytes
Xil_Out32((VDMA_BASEADDR + 0x050), V_ACTIVE);           // v size (600)

for(i=0;i<H_STRIDE*H_ACTIVE;i++)
{
Xil_Out32(VIDEO_BASEADDR0+i,0);
}

SD_Init();
SD_Transfer_read("test.bin",(u32)picture1,800*600*3+1);

while(1)
{
show_img(0,0,VIDEO_BASEADDR0,&picture1[0],800,600);
show_img(0,0,VIDEO_BASEADDR1,&picture1[0],800,600);
show_img(0,0,VIDEO_BASEADDR2,&picture1[0],800,600);
sleep(5);
}
return 0;
}


四、实验现象

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
相关文章推荐