天天看點

activiti高亮顯示圖檔_【正點原子FPGA連載】第二十章SD卡讀BMP圖檔HDMI顯示實驗領航者 ZYNQ 之嵌入式開發指南...

1)實驗平台:正點原子領航者ZYNQ開發闆

2)平台購買位址:https://item.taobao.com/item.htm?&id=606160108761

3)全套實驗源碼+手冊+視訊下載下傳位址:http://www.openedv.com/docs/boards/fpga/zdyz_linhanz.html

4)對正點原子FPGA感興趣的同學可以加群讨論:876744900

5)關注正點原子公衆号,擷取最新資料

http://weixin.qq.com/r/hEhUTLbEdesKrfIv9x2W (二維碼自動識别)

第二十章SD卡讀BMP圖檔HDMI顯示實驗

我們在“SD卡讀BMP圖檔LCD顯示實驗”中,成功地将SD卡中的BMP圖檔讀出,并将其顯示在了LCD屏上。本章我們将學習如何SD卡中的BMP圖檔顯示在HDMI顯示器上。

本章包括以下幾個部分:

2020.1簡介

20.2實驗任務

20.3硬體設計

20.4軟體設計

20.5下載下傳驗證

20.1簡介

在“SD卡讀BMP圖檔LCD顯示實驗”的簡介部分,我們詳細介紹了BMP圖檔的資料格式;另外在《領航者FPGA開發指南》中的“HDMI彩條顯示實驗”一章,我們介紹了HDMI接口。如果大家對這兩部分的内容不熟悉的話,可以參考相應的章節,此處就不再贅述了。

20.2實驗任務

本章的實驗任務是使用領航者ZYNQ開發闆讀取SD卡中存放的BMP格式圖檔,分辨率為1920*1080,并将其顯示在HDMI顯示器上。

20.3硬體設計

根據實驗任務我們可以畫出本次實驗的系統框圖,如下圖所示:

activiti高亮顯示圖檔_【正點原子FPGA連載】第二十章SD卡讀BMP圖檔HDMI顯示實驗領航者 ZYNQ 之嵌入式開發指南...

圖 20.3.1 系統框圖

圖 5.3.1與“SD卡讀BMP圖檔LCD顯示實驗”中的系統框圖基本相同,隻是将驅動LCD顯示的rgb2lcd子產品替換成了本次實驗中的DVI Transmitter,用于驅動HDMI接口;另外還删除了用于讀取LCD ID資訊的AXI GPIO子產品。是以本次實驗的硬體設計部分在“SD卡讀BMP圖檔LCD顯示實驗”的基礎上稍作修改即可。

首先要删除《SD卡讀BMP圖檔LCD顯示實驗》工程中的rgb to lcd和AXI GPIO兩個子產品,以及LCD相關的接口。如圖 20.3.2所示,我們要删除圖中橙色高亮的兩個子產品和3個接口:

activiti高亮顯示圖檔_【正點原子FPGA連載】第二十章SD卡讀BMP圖檔HDMI顯示實驗領航者 ZYNQ 之嵌入式開發指南...

圖 20.3.2 删除LCD相關子產品

接下來添加DVI Transmitter IP核。該IP核位于工程目錄下的ip_repo檔案夾中,名為“DVI_TX”。我們需要将其添加到工程的IP庫中,添加IP核的方法請大家參考“自定義IP核-呼吸燈實驗”。添加完成後,我們要在Block Design中連接配接DVI Transmitter子產品的接口信号,并引出外部端口,具體的連接配接方式如圖 20.3.3所示:

activiti高亮顯示圖檔_【正點原子FPGA連載】第二十章SD卡讀BMP圖檔HDMI顯示實驗領航者 ZYNQ 之嵌入式開發指南...

圖 20.3.3 添加并連接配接DVI_Transmitter IP核

至此本次實驗的硬體框圖已經搭建好了。需要說明的是,本次實驗的硬體框圖是基于《SD卡讀BMP圖檔LCD顯示實驗》搭建的,VDMA的AXI Stream格式資料流和Memory Map格式資料流的時鐘頻率設定的較低,為100Mhz,是以VDMA和DDR3的資料互動速率會受到限制,即支援的HDMI顯示分辨率無法達到很高,實測最大能達到的分辨率為1280x800。

對于LCD屏的顯示實驗來說,達到1280x800的分辨率已經夠用了,但是考慮到目前大多數的HDMI顯示器支援1080P(1920x1080)的分辨率,我們需要對底層搭建的硬體環境做修改,才能支援1080P分辨率。考慮到本手冊HDMI顯示相關的例程不需要1080P分辨率,且大多數HDMI顯示例程是基于LCD例程修改而來,如果每次都為了相容1080P分辨率而修改底層硬體環境比較麻煩,是以本手冊僅本章實驗的底層硬體環境支援1080P分辨率,其它HDMI實驗大家如果有1080P分辨率的顯示需求,可以按照本章實驗進行修改。

底層硬體修改的方法是将VDMA的AXI Stream格式資料流和Memory Map格式資料流的時鐘頻率改為150Mhz,而VDMA的配置端口不需要太高的頻率,可以仍然保持100Mhz。

首先輕按兩下打開“ZYNQ7 Processing System”框圖,點選“Clock Configuration”,在“PL Fabric Clocks”一欄下勾選FCLK_CLK1,時鐘頻率設定為150Mhz。設定完成後,點選“OK”按鈕,如下圖所示:

activiti高亮顯示圖檔_【正點原子FPGA連載】第二十章SD卡讀BMP圖檔HDMI顯示實驗領航者 ZYNQ 之嵌入式開發指南...

圖 20.3.4 添加“FCLK_CLK1”時鐘

修改完成後,可以發現“ZYNQ7 Processing System”框圖多了一個FCLK_CLK1端口。接下來删除FCLK_CLK0連線,首先選中FCLK_CLK0的連線使其高亮,然後按下鍵盤的“Delete”進行删除,如圖 20.3.5和圖 20.3.6所示:

activiti高亮顯示圖檔_【正點原子FPGA連載】第二十章SD卡讀BMP圖檔HDMI顯示實驗領航者 ZYNQ 之嵌入式開發指南...

圖 20.3.5 選中FCLK_CLK0連線

activiti高亮顯示圖檔_【正點原子FPGA連載】第二十章SD卡讀BMP圖檔HDMI顯示實驗領航者 ZYNQ 之嵌入式開發指南...

圖 20.3.6 删除FCLK_CLK0連線

然後删除框圖中的AXI Interconnect IP核(ps7_0_axi_periph)、AXI SmartConnect IP核(axi_smc)和Processor System Reset IP核(rst_ps7_0_100M),框圖删除後,如下圖所示。

activiti高亮顯示圖檔_【正點原子FPGA連載】第二十章SD卡讀BMP圖檔HDMI顯示實驗領航者 ZYNQ 之嵌入式開發指南...

圖 20.3.7 删除IP核

接下來連接配接FCLK_CLK1的時鐘,如下圖所示。

activiti高亮顯示圖檔_【正點原子FPGA連載】第二十章SD卡讀BMP圖檔HDMI顯示實驗領航者 ZYNQ 之嵌入式開發指南...

然後點選“Run Connnection Automation”,下面列出了會自動連接配接的子產品及其接口,勾選“All Automation”,然後點選“OK”按鈕。

此時系統會自動生成 AXI Interconnect 和 AXI Smartconnect。AXI Interconnect(ps7_0_axi_periph)用于橋接ZYNQ處理器M_AXI_GP0總線和外部低速外設的AXI_LITE總線;AXI Smartconnect(axi_smc)用于連接配接ZYNQ處理器的HP0接口和VDMA的M_AXI_MM2S總線。另外系統也自動生成了兩個 reset子產品(rst_ps7_0_100M和rst_ps7_0_150M),用于複位總線上的外設。

整體系統架構圖如下:

activiti高亮顯示圖檔_【正點原子FPGA連載】第二十章SD卡讀BMP圖檔HDMI顯示實驗領航者 ZYNQ 之嵌入式開發指南...

圖 20.3.8 整體系統架構連接配接圖

block design修改完成後儲存,然後重新Generate Output Products和“Create HDL Wrapper”。接下來我們還要修改限制檔案,為HDMI接口配置設定引腳。打開工程中名為“system_wrapper.xdc”的限制檔案,并将原先LCD相關的限制語句删除,替換成以下内容:

set_property -dict {PACKAGE_PIN G17 IOSTANDARD LVCMOS33} [get_ports tmds_oen_0]

set_property PACKAGE_PIN L16 [get_ports {TMDS_0_tmds_data_p[2]}]

set_property PACKAGE_PIN M14 [get_ports {TMDS_0_tmds_data_p[1]}]

set_property PACKAGE_PIN K19 [get_ports {TMDS_0_tmds_data_p[0]}]

set_property PACKAGE_PIN L14 [get_ports TMDS_0_tmds_clk_p]

儲存限制檔案,然後選擇“Generate Bitstream”重新生成BIT檔案。

20.4軟體設計

本次實驗的軟體工程與“SD卡讀BMP圖檔LCD顯示實驗”略有不同,如下圖所示:

activiti高亮顯示圖檔_【正點原子FPGA連載】第二十章SD卡讀BMP圖檔HDMI顯示實驗領航者 ZYNQ 之嵌入式開發指南...

圖 20.4.1 軟體工程

圖 20.4.1左側紅色方框中的檔案夾名為“display_ctrl_hdmi”,它在前面實驗中“display_ctrl”的基礎上删除了GPIO相關的函數及變量。在本次實驗中删除了AXI GPIO子產品,是以要删除這些函數和變量,否則會報錯。

本次實驗的代碼如下所示:

  1. 1 #include <stdio.h>
  2. 2 #include <stdlib.h>
  3. 3 #include <string.h>
  4. 4 #include "xil_types.h"
  5. 5 #include "xil_cache.h"
  6. 6 #include "xparameters.h"
  7. 7 #include "xaxivdma.h"
  8. 8 #include "xaxivdma_i.h"
  9. 9 #include "display_ctrl_hdmi/display_ctrl.h"
  10. 10 #include "vdma_api/vdma_api.h"
  11. 11 #include "ff.h"
  12. 12
  13. 13 //宏定義
  14. 14 #define BYTES_PIXEL 3 //像素位元組數,RGB888占3個位元組
  15. 15 #define DYNCLK_BASEADDR XPAR_AXI_DYNCLK_0_BASEADDR //動态時鐘基位址
  16. 16 #define VDMA_ID XPAR_AXIVDMA_0_DEVICE_ID //VDMA器件ID
  17. 17 #define DISP_VTC_ID XPAR_VTC_0_DEVICE_ID //VTC器件ID
  18. 18
  19. 19 //函數聲明
  20. 20 void load_sd_bmp(u8 *frame);
  21. 21
  22. 22 //全局變量
  23. 23 XAxiVdma vdma;
  24. 24 DisplayCtrl dispCtrl;
  25. 25 VideoMode vd_mode;
  26. 26 //frame buffer的起始位址
  27. 27 unsigned int const frame_buffer_addr = (XPAR_PS7_DDR_0_S_AXI_BASEADDR + 0x1000000);
  28. 28 unsigned int lcd_id=0; //LCD ID
  29. 29
  30. 30 int main(void)
  31. 31 {
  32. 32 xil_printf("HDMI Display 1920*1080 rn");
  33. 33
  34. 34 //設定video參數,分辨率:1920*1080
  35. 35 vd_mode = VMODE_1920x1080;
  36. 36
  37. 37 //配置VDMA
  38. 38 run_vdma_frame_buffer(&vdma, VDMA_ID, vd_mode.width, vd_mode.height,
  39. 39 frame_buffer_addr,0, 0,ONLY_READ);
  40. 40
  41. 41 //初始化Display controller
  42. 42 DisplayInitialize(&dispCtrl, DISP_VTC_ID, DYNCLK_BASEADDR);
  43. 43 //設定VideoMode
  44. 44 DisplaySetMode(&dispCtrl, &vd_mode);
  45. 45 DisplayStart(&dispCtrl);
  46. 46
  47. 47 //讀取SD卡圖檔并顯示
  48. 48 load_sd_bmp((u8*)frame_buffer_addr);
  49. 49
  50. 50 return 0;
  51. 51 }
  52. 52
  53. 53 //從SD卡中讀取BMP圖檔
  54. 54 void load_sd_bmp(u8 *frame)
  55. 55 {
  56. 56 static FATFS fatfs;
  57. 57 FIL fil;
  58. 58 u8 bmp_head[54];
  59. 59 UINT *bmp_width,*bmp_height,*bmp_size;
  60. 60 UINT br;
  61. 61 int i;
  62. 62
  63. 63 //挂載檔案系統
  64. 64 f_mount(&fatfs,"",1);
  65. 65
  66. 66 //打開檔案
  67. 67 f_open(&fil,"fengjing.bmp",FA_READ);
  68. 68
  69. 69 //移動檔案讀寫指針到檔案開頭
  70. 70 f_lseek(&fil,0);
  71. 71
  72. 72 //讀取BMP檔案頭
  73. 73 f_read(&fil,bmp_head,54,&br);
  74. 74 xil_printf("fengjing.bmp head: nr");
  75. 75 for(i=0;i<54;i++)
  76. 76 xil_printf(" %x",bmp_head);
  77. 77
  78. 78 //列印BMP圖檔分辨率和大小
  79. 79 bmp_width = (UINT *)(bmp_head + 0x12);
  80. 80 bmp_height = (UINT *)(bmp_head + 0x16);
  81. 81 bmp_size = (UINT *)(bmp_head + 0x22);
  82. 82 xil_printf("n width = %d, height = %d, size = %d bytes nr",
  83. 83 *bmp_width,*bmp_height,*bmp_size);
  84. 84
  85. 85 //讀出圖檔,寫入DDR
  86. 86 for(i=*bmp_height-1;i>=0;i--){
  87. 87 f_read(&fil,frame+i*(*bmp_width)*3,(*bmp_width)*3,&br);
  88. 88 }
  89. 89
  90. 90 //關閉檔案
  91. 91 f_close(&fil);
  92. 92
  93. 93 Xil_DCacheFlush(); //重新整理Cache,資料更新至DDR3中
  94. 94 xil_printf("show bmpnr");
  95. 95 }

可以看出,本次實驗的程式與“SD卡讀BMP圖檔LCD顯示實驗”非常相似,隻是删除了讀取LCD ID相關的内容。有關這部分代碼的詳細介紹請大家參考“SD卡讀BMP圖檔LCD顯示實驗”,此處不再贅述。需要注意的是,本次實驗在SD卡中放置的圖檔分辨率為1920*1080,是以在程式的第35行,視訊參數設定成VMODE_1920x1080。

20.5下載下傳驗證

首先我們将下載下傳器與領航者底闆上的JTAG接口連接配接,下載下傳器另外一端與電腦連接配接。然後使用Mini USB連接配接線将開發闆左側的USB_UART接口與電腦連接配接,用于序列槽通信。

我們在工程目錄下建立了一個名為“風景圖檔”的檔案夾,把其中名為“fengjing.bmp”的圖檔拷貝到SD卡的根目錄下,然後将SD卡插入領航者底闆背面的卡槽中。另外還需要使用HDMI連接配接線将HDMI顯示器連接配接到領航者底闆上的HDMI接口。最後連接配接開發闆的電源,并打開電源開關。

在SDK軟體下方的SDK Terminal視窗中點選右上角的加号來設定并連接配接序列槽。然後下載下傳本次實驗硬體設計過程中所生成的BIT檔案,來對PL進行配置。最後下載下傳軟體程式,下載下傳完成後,在下方的SDK Terminal中可以看到應用程式列印的資訊,如下圖所示:

activiti高亮顯示圖檔_【正點原子FPGA連載】第二十章SD卡讀BMP圖檔HDMI顯示實驗領航者 ZYNQ 之嵌入式開發指南...

圖 20.5.1 序列槽列印資訊

圖 20.5.1中列印出了BMP檔案的檔案頭和資訊頭等資訊,同時從資料中計算出BMP圖檔的寬度為1920,高度為1080,與我們存入SD卡中的BMP圖檔一緻。

同時HDMI顯示器上顯示存入SD卡中的示例圖檔,如圖 20.5.2所示,說明本次實驗在領航者ZYNQ開發闆上面下載下傳驗證成功。

activiti高亮顯示圖檔_【正點原子FPGA連載】第二十章SD卡讀BMP圖檔HDMI顯示實驗領航者 ZYNQ 之嵌入式開發指南...

圖 20.5.2 下載下傳驗證

繼續閱讀