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; }
四、实验现象
相关文章推荐
- WCF基础系列1 创建一个简单的WCF应用
- 详细介绍附代码:使用jquery,和php文件构建一个简单的在线聊天室,通过ip显示googlemap
- 从头开始构建一个web即时通讯系统 - 基础 - web即时通讯系统的四种实现
- [Android5 系列—] 1. 构建一个简单的用户界面
- VS Extension+NVelocity系列(一)——构建一个简单的NVelocity解析环境
- [Android5 系列—] 1. 构建一个简单的用户界面
- WCF+WF双剑合璧构建微软的SOA系列(一):从一个简单的Demo开始
- 【虫师--系列】JMeter基础之一 一个简单的性能测试
- Java与Struts结合写一个简单基础的分页显示
- WCF+WF双剑合璧构建微软的SOA系列(一):从一个简单的Demo开始
- SpringBoot入门系列:eclipse如何构建一个最简单的springBoot项目。
- 用C#构建一个简单的采集系统之二—采集任务实时显示
- 一步一个脚印学习WCF之二构建一个简单的WCF应用程序前必须掌握的WCF基础术语---契约(Contract)
- WCF+WF双剑合璧构建微软的SOA系列(一):从一个简单的Demo开始
- 一步一个脚印学习WCF之二构建一个简单的WCF应用程序前必须掌握的WCF基础术语---契约的名称与命名空间
- 使用Cocos2d的从零基础开始你的游戏生涯(系列之一 基础简单Objective-C入门)
- 【XIlinx-ZYNQ】 TPG+VTC+AXI4_to_Stream_out构建简单显示电路
- 一步一个脚印学习WCF之二构建一个简单的WCF应用程序前必须掌握的WCF基础术语---地址(Addresses)
- 一起谈.NET技术,WCF+WF双剑合璧构建微软的SOA系列(一):从一个简单的Demo开始
- 快速构建一个简单的个人框架系列