學習內容
本文使用帶有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
#include
#include
#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的起始地址
unsignedintconst frame_buffer_addr = (XPAR_PS7_DDR_0_S_AXI_BASEADDR + 0x1000000);
unsignedint 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);
return0;
}
//從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開發視頻