本文对手上的4寸 RGB888屏程序进行调试,为了快速验证屏幕是否工作,这里先用PS的硬件I2C功能对屏幕进行初始化(以后会用PL重写配置部分)
如题,本次用的屏幕是 RGB+I2C屏,也就是屏幕可以通过I2C来进行初始化,初始化完成后通过RGB信号(RGB888,HSYNC VSYNC PCLK DE)来对屏幕持续性的输出图像数据。
对于其他的RGB屏其实也都大同小异,可以参考本工程来进行修改,(大部分是 SPI+RGB, 因为排针接口有限,所以这里我把屏幕硬件上配置成了 I2C+RGB,I2C和触摸屏的I2C共用信号线)
屏幕为NT35510屏 (可以设置成80端口 或者MIPI 端口,这里仅演示用RGB端口去驱动)
创建Vivado工程
1)具体步骤 新建一个VIVADO 工程,打开软件 选中Create Project, 如下图所示
![](http://www.hellofpga.com/wp-content/uploads/2021/07/Create-Project.png)
2)点击NEXT ,在出现的第二个对话框“Project name”中输入工程名;在“Project location”中选择保存路径;勾选“Create project subdirectory”,最后点击“Next” 备注,所有的路径均不能出现中文名称
3)点击 RTL PROJECT 选项,点击NEXT
![](http://www.hellofpga.com/wp-content/uploads/2021/07/image.png)
4) 第四步Add Sources 选项直接留空,NEXT
5)第五步Add Constraints 选项直接留空,NEXT
6)选择芯片型号 我们板子上用的芯片是XC7Z010 ,并在列表栏中选择对应的封装型号,完整型号是XC7Z010CLG400-1 如下所示,选中后点NEXT
![](http://www.hellofpga.com/wp-content/uploads/2021/07/image-1.png)
7)确认所选信息 点击“Finish”,完成vivado的工程创建
![](http://www.hellofpga.com/wp-content/uploads/2021/07/image-4.png)
创建一个BLOCK设计
1)IP INTEGRATOR→Create Block Design,在弹出的对话框中输入设计名,最后点击“OK”,如下图所示
![](http://www.hellofpga.com/wp-content/uploads/2022/11/image-51.png)
2)在右侧的窗口里 ,点击加号,在选择框里搜索ZYNQ,并找到ZYNQ7 PROCESSING SYSTEM ,双击并打开
![](http://www.hellofpga.com/wp-content/uploads/2021/08/image-2.png)
3)软件自动生成了一个 zynq的block 如下图所示,接下来要做一些相应的设置,双击下图中的ZYNQ核
![](http://www.hellofpga.com/wp-content/uploads/2021/08/image-3.png)
4)依次在弹窗里找到DDR Configuration→DDR Controller Configuration→DDR3,在Memory Part下拉菜单中根据自己板子上的DDR来选择相应的DDR3,本实验所用到型号:MT41K128M16JT 125,数据位宽选择16bit 最后点击“OK”,如下图所示。
![](http://www.hellofpga.com/wp-content/uploads/2021/08/image-5.png)
5)在PS的MIO配置选项的GPIO栏里,增加两路EMIO(因为本次除了I2C去配置屏幕外,还需要两路IO分别去控制RST信号和BL背光信号)
![](http://www.hellofpga.com/wp-content/uploads/2022/11/image-52.png)
6)并且增加一路I2C资源,选EMIO方式(因为板子上所有的排针都是接在PL端的)
![](http://www.hellofpga.com/wp-content/uploads/2022/11/image-53.png)
7)点击“Run Block Automation”如下图所示。在弹出的选项中保持默认,点击“OK”,即可完成对ZYNQ7 Processing System的配置
![](http://www.hellofpga.com/wp-content/uploads/2022/10/image-43.png)
8)将刚才添加EMIO GPIO 引出 右键GPIO_0—->Make External
![](http://www.hellofpga.com/wp-content/uploads/2022/10/image-44.png)
9)用同样的方法将EMIO I2C引出,右键 IIC_0 点选Make External
![](http://www.hellofpga.com/wp-content/uploads/2022/11/image-54.png)
10)用线将M_AXI_GP0_ACLK与 FCLK_CLK0连接起来(如果嫌麻烦在配置页也可以将AXI功能关闭,这里没有用到AXI功能)
![](http://www.hellofpga.com/wp-content/uploads/2022/11/image-55.png)
11)source→Design Source ,右键我们创建的BLOCK工程,点击create HDL wrapper如下图所示。
![](http://www.hellofpga.com/wp-content/uploads/2021/08/image-12.png)
在弹出的对话框里保持默认
![](http://www.hellofpga.com/wp-content/uploads/2021/08/image-13.png)
软件自动为我们生成HDL文件
![](http://www.hellofpga.com/wp-content/uploads/2022/11/image-56.png)
创建工程PL的 RGB的VERILOG部分
RGB的工程其实之前有写过,Tiny ZYNQ板 工程五 基于ZYNQ PL资源的HDMI功能演示
这里我们把HDMI工程的 RGB部分搬过来并作简单修改。
1)首先我们先用锁相环创建一个33M的时钟(为什么是33M ,因为800X480的屏幕在60hz左右的时钟就是33M)
点击IP Catalog 打开模块选择器, 在里面的搜索栏输入 CLOCKING ,系统会自动跳出符合的 Clocking Wizard选项,双击它
![](http://www.hellofpga.com/wp-content/uploads/2021/07/image-3.png)
2)在弹出的窗口中我们将input Frequence 输入频率修改为板子上焊接的50M时钟, 右边改为单端输入
![](http://www.hellofpga.com/wp-content/uploads/2021/07/image-11-1024x660.png)
3)在output Clocks选项中 将clk_out1改成33m
![](http://www.hellofpga.com/wp-content/uploads/2022/11/image-57.png)
4)将界面托到最下面,因为我们这里的要求并不高,所以把时钟的复位reset,和locked选项去除,最后点击ok生成模块
![](http://www.hellofpga.com/wp-content/uploads/2021/07/image-15.png)
之后点选OK完成创建
增加我们的VERILOG代码内容
1)这里创建一个显示模块显示模块负责输出标准的RGB时序,这里对HDMI工程中的RGB部分作了修改,调整了480X800的时序,以及增加了多种显示效果切换的部分,让显示结果更为丰富,具体如下( color_bar.v)
module COLOR_BAR( input clk, //pixel clock input rst, //reset signal high active output hs, //horizontal synchronization output vs, //vertical synchronization output de, //video valid output[7:0] rgb_r, //video red data output[7:0] rgb_g, //video green data output[7:0] rgb_b //video blue data ); `define VIDEO_480_800 //800x480 33Mhz `ifdef VIDEO_480_800 parameter H_ACTIVE = 16'd480; parameter H_FP = 16'd1; parameter H_SYNC = 16'd3; parameter H_BP = 16'd160; parameter V_ACTIVE = 16'd800; parameter V_FP = 16'd40; parameter V_SYNC = 16'd128; parameter V_BP = 16'd88; parameter HS_POL = 1'b0; parameter VS_POL = 1'b0; `endif parameter H_TOTAL = H_ACTIVE + H_FP + H_SYNC + H_BP;//horizontal total time (pixels) parameter V_TOTAL = V_ACTIVE + V_FP + V_SYNC + V_BP;//vertical total time (lines) //define the RGB values for 8 colors parameter WHITE_R = 8'hff; parameter WHITE_G = 8'hff; parameter WHITE_B = 8'hff; parameter YELLOW_R = 8'hff; parameter YELLOW_G = 8'hff; parameter YELLOW_B = 8'h00; parameter CYAN_R = 8'h00; parameter CYAN_G = 8'hff; parameter CYAN_B = 8'hff; parameter GREEN_R = 8'h00; parameter GREEN_G = 8'hff; parameter GREEN_B = 8'h00; parameter MAGENTA_R = 8'hff; parameter MAGENTA_G = 8'h00; parameter MAGENTA_B = 8'hff; parameter RED_R = 8'hff; parameter RED_G = 8'h00; parameter RED_B = 8'h00; parameter BLUE_R = 8'h00; parameter BLUE_G = 8'h00; parameter BLUE_B = 8'hff; parameter BLACK_R = 8'h00; parameter BLACK_G = 8'h00; parameter BLACK_B = 8'h00; reg hs_reg; //horizontal sync register reg vs_reg; //vertical sync register reg hs_reg_d0; //delay 1 clock of 'hs_reg' reg vs_reg_d0; //delay 1 clock of 'vs_reg' reg[11:0] h_cnt; //horizontal counter reg[11:0] v_cnt; //vertical counter reg[11:0] active_x; //video x position reg[11:0] active_y; //video y position reg[7:0] rgb_r_reg; //video red data register reg[7:0] rgb_g_reg; //video green data register reg[7:0] rgb_b_reg; //video blue data register reg h_active; //horizontal video active reg v_active; //vertical video active wire video_active; //video active(horizontal active and vertical active) reg video_active_d0; //delay 1 clock of video_active assign hs = hs_reg_d0; assign vs = vs_reg_d0; assign video_active = h_active & v_active; assign de = video_active_d0; assign rgb_r = rgb_r_reg; assign rgb_g = rgb_g_reg; assign rgb_b = rgb_b_reg; always@(posedge clk or posedge rst) begin if(rst == 1'b1) begin hs_reg_d0 <= 1'b0; vs_reg_d0 <= 1'b0; video_active_d0 <= 1'b0; end else begin hs_reg_d0 <= hs_reg; vs_reg_d0 <= vs_reg; video_active_d0 <= video_active; end end always@(posedge clk or posedge rst) begin if(rst == 1'b1) h_cnt <= 12'd0; else if(h_cnt == H_TOTAL - 1)//horizontal counter maximum value h_cnt <= 12'd0; else h_cnt <= h_cnt + 12'd1; end always@(posedge clk or posedge rst) begin if(rst == 1'b1) active_x <= 12'd0; else if(h_cnt >= H_FP + H_SYNC + H_BP - 1)//horizontal video active active_x <= h_cnt - (H_FP[11:0] + H_SYNC[11:0] + H_BP[11:0] - 12'd1); else active_x <= active_x; end always@(posedge clk or posedge rst) begin if(rst == 1'b1) v_cnt <= 12'd0; else if(h_cnt == H_FP - 1)//horizontal sync time if(v_cnt == V_TOTAL - 1)//vertical counter maximum value v_cnt <= 12'd0; else v_cnt <= v_cnt + 12'd1; else v_cnt <= v_cnt; end always@(posedge clk or posedge rst) begin if(rst == 1'b1) hs_reg <= 1'b0; else if(h_cnt == H_FP - 1)//horizontal sync begin hs_reg <= HS_POL; else if(h_cnt == H_FP + H_SYNC - 1)//horizontal sync end hs_reg <= ~hs_reg; else hs_reg <= hs_reg; end always@(posedge clk or posedge rst) begin if(rst == 1'b1) h_active <= 1'b0; else if(h_cnt == H_FP + H_SYNC + H_BP - 1)//horizontal active begin h_active <= 1'b1; else if(h_cnt == H_TOTAL - 1)//horizontal active end h_active <= 1'b0; else h_active <= h_active; end always@(posedge clk or posedge rst) begin if(rst == 1'b1) vs_reg <= 1'd0; else if((v_cnt == V_FP - 1) && (h_cnt == H_FP - 1))//vertical sync begin vs_reg <= HS_POL; else if((v_cnt == V_FP + V_SYNC - 1) && (h_cnt == H_FP - 1))//vertical sync end vs_reg <= ~vs_reg; else vs_reg <= vs_reg; end always@(posedge clk or posedge rst) begin if(rst == 1'b1) v_active <= 1'd0; else if((v_cnt == V_FP + V_SYNC + V_BP - 1) && (h_cnt == H_FP - 1))//vertical active begin v_active <= 1'b1; else if((v_cnt == V_TOTAL - 1) && (h_cnt == H_FP - 1)) //vertical active end v_active <= 1'b0; else v_active <= v_active; end reg [3:0]mode=4'd0; parameter T1MS = 26'd60_000_000 ; reg [25:0]time_count;//时钟计数器 always@(posedge clk) if(time_count>=T1MS)begin time_count<=26'd0; if(mode<8)mode<=mode+1'b1; else mode<=4'd0; end else time_count<=time_count+1'b1; always@(posedge clk or posedge rst) begin if(rst == 1'b1) begin rgb_r_reg <= 8'h00; rgb_g_reg <= 8'h00; rgb_b_reg <= 8'h00; end else if(video_active)begin if(mode==0)begin if(active_x == 12'd0) begin rgb_r_reg <= WHITE_R; rgb_g_reg <= WHITE_G; rgb_b_reg <= WHITE_B; end else if(active_x == (H_ACTIVE/8) * 1) begin rgb_r_reg <= YELLOW_R; rgb_g_reg <= YELLOW_G; rgb_b_reg <= YELLOW_B; end else if(active_x == (H_ACTIVE/8) * 2) begin rgb_r_reg <= CYAN_R; rgb_g_reg <= CYAN_G; rgb_b_reg <= CYAN_B; end else if(active_x == (H_ACTIVE/8) * 3) begin rgb_r_reg <= GREEN_R; rgb_g_reg <= GREEN_G; rgb_b_reg <= GREEN_B; end else if(active_x == (H_ACTIVE/8) * 4) begin rgb_r_reg <= MAGENTA_R; rgb_g_reg <= MAGENTA_G; rgb_b_reg <= MAGENTA_B; end else if(active_x == (H_ACTIVE/8) * 5) begin rgb_r_reg <= RED_R; rgb_g_reg <= RED_G; rgb_b_reg <= RED_B; end else if(active_x == (H_ACTIVE/8) * 6) begin rgb_r_reg <= BLUE_R; rgb_g_reg <= BLUE_G; rgb_b_reg <= BLUE_B; end else if(active_x == (H_ACTIVE/8) * 7) begin rgb_r_reg <= BLACK_R; rgb_g_reg <= BLACK_G; rgb_b_reg <= BLACK_B; end else begin rgb_r_reg <= rgb_r_reg; rgb_g_reg <= rgb_g_reg; rgb_b_reg <= rgb_b_reg; end end else if(mode==1)begin rgb_r_reg <= active_x[7:0]; rgb_g_reg <= 8'h00; rgb_b_reg <= 8'h00; end else if(mode==2)begin rgb_r_reg <=8'h00 ; rgb_g_reg <= active_x[7:0]; rgb_b_reg <= 8'h00; end else if(mode==3)begin rgb_r_reg <=8'h00 ; rgb_g_reg <=8'h00; rgb_b_reg <= active_x[7:0]; end else if(mode==4)begin rgb_r_reg <=active_x[7:0]; rgb_g_reg <=active_x[7:0]; rgb_b_reg <=active_x[7:0]; end else if(mode==5)begin rgb_r_reg <=8'hff; rgb_g_reg <=8'hff; rgb_b_reg <=8'hff; end else if(mode==6)begin rgb_r_reg <=8'hff; rgb_g_reg <=8'h00; rgb_b_reg <=8'h00; end else if(mode==7)begin rgb_r_reg <=8'h00; rgb_g_reg <=8'hff; rgb_b_reg <=8'h00; end else if(mode==8)begin rgb_r_reg <=8'h00; rgb_g_reg <=8'h00; rgb_b_reg <=8'hff; end else begin rgb_r_reg <= 8'h00; rgb_g_reg <= 8'h00; rgb_b_reg <= 8'h00; end end end endmodule
其中 以下代码用来每两秒钟切换一次显示模式,而不同的mode 分别对应上面代码中不同颜色画面的显示。也就是系统每两秒切换一次模式 ,一共有8种模式
reg [3:0]mode=4'd0; parameter T1MS = 26'd66_000_000 ; reg [25:0]time_count; always@(posedge clk) if(time_count>=T1MS)begin time_count<=26'd0; if(mode<8)mode<=mode+1'b1; else mode<=4'd0; end else time_count<=time_count+1'b1;
2)创建一个顶层模块,分别调用时钟、ZYNQ核 以及彩条纹显示模块(top.v)
`timescale 1ns / 1ps module LCD_MODULE( input CLK, output [7:0]LCD_R, output [7:0]LCD_G, output [7:0]LCD_B, output LCD_HSYNC, output LCD_VSYNC, output LCD_PCLK, output LCD_DE, inout LCD_RST, inout LCD_I2C_SCL, inout LCD_I2C_SDA, inout BL ); wire clk_33m; clk_wiz_0 u2( .clk_in1(CLK), .clk_out1(clk_33m) ); assign LCD_PCLK=~clk_33m; COLOR_BAR u4( .clk(clk_33m), .rst(0), .hs(LCD_HSYNC), .vs(LCD_VSYNC), .de(LCD_DE), .rgb_r(LCD_R), .rgb_g(LCD_G), .rgb_b(LCD_B) ); ZYNQ_wrapper U_zynq( .GPIO_0_0_tri_io({LCD_RST,BL}), .IIC_0_0_scl_io(LCD_I2C_SCL), .IIC_0_0_sda_io(LCD_I2C_SDA) ); endmodule
最后再增加约束文件 (LCD_TEST.XDC)
set_property IOSTANDARD LVCMOS33 [get_ports {LCD_R[6]}] set_property IOSTANDARD LVCMOS33 [get_ports {LCD_B[5]}] set_property IOSTANDARD LVCMOS33 [get_ports LCD_VSYNC] set_property IOSTANDARD LVCMOS33 [get_ports {LCD_R[3]}] set_property IOSTANDARD LVCMOS33 [get_ports {LCD_G[3]}] set_property IOSTANDARD LVCMOS33 [get_ports {LCD_B[0]}] set_property IOSTANDARD LVCMOS33 [get_ports {LCD_R[0]}] set_property IOSTANDARD LVCMOS33 [get_ports {LCD_G[2]}] set_property IOSTANDARD LVCMOS33 [get_ports {LCD_B[4]}] set_property IOSTANDARD LVCMOS33 [get_ports LCD_HSYNC] set_property IOSTANDARD LVCMOS33 [get_ports {LCD_R[1]}] set_property IOSTANDARD LVCMOS33 [get_ports {LCD_R[4]}] set_property IOSTANDARD LVCMOS33 [get_ports {LCD_G[1]}] set_property IOSTANDARD LVCMOS33 [get_ports {LCD_B[3]}] set_property IOSTANDARD LVCMOS33 [get_ports CLK] set_property IOSTANDARD LVCMOS33 [get_ports {LCD_G[6]}] set_property IOSTANDARD LVCMOS33 [get_ports LCD_PCLK] set_property IOSTANDARD LVCMOS33 [get_ports LCD_DE] set_property IOSTANDARD LVCMOS33 [get_ports {LCD_G[0]}] set_property IOSTANDARD LVCMOS33 [get_ports {LCD_B[2]}] set_property IOSTANDARD LVCMOS33 [get_ports {LCD_R[5]}] set_property IOSTANDARD LVCMOS33 [get_ports {LCD_G[5]}] set_property IOSTANDARD LVCMOS33 [get_ports {LCD_R[2]}] set_property IOSTANDARD LVCMOS33 [get_ports {LCD_B[1]}] set_property IOSTANDARD LVCMOS33 [get_ports LCD_RST] set_property IOSTANDARD LVCMOS33 [get_ports {LCD_G[4]}] set_property IOSTANDARD LVCMOS33 [get_ports {LCD_B[6]}] set_property IOSTANDARD LVCMOS33 [get_ports {LCD_R[7]}] set_property IOSTANDARD LVCMOS33 [get_ports LCD_I2C_SDA] set_property IOSTANDARD LVCMOS33 [get_ports LCD_I2C_SCL] set_property IOSTANDARD LVCMOS33 [get_ports {LCD_B[7]}] set_property IOSTANDARD LVCMOS33 [get_ports {LCD_G[7]}] set_property IOSTANDARD LVCMOS33 [get_ports BL] set_property PACKAGE_PIN W13 [get_ports {LCD_B[0]}] set_property PACKAGE_PIN L16 [get_ports {LCD_B[4]}] set_property PACKAGE_PIN M18 [get_ports {LCD_G[2]}] set_property PACKAGE_PIN Y19 [get_ports {LCD_R[4]}] set_property PACKAGE_PIN V17 [get_ports {LCD_R[6]}] set_property PACKAGE_PIN W16 [get_ports {LCD_R[2]}] set_property PACKAGE_PIN Y18 [get_ports {LCD_R[0]}] set_property PACKAGE_PIN V16 [get_ports {LCD_G[6]}] set_property PACKAGE_PIN Y16 [get_ports {LCD_G[0]}] set_property PACKAGE_PIN W15 [get_ports {LCD_B[6]}] set_property PACKAGE_PIN P16 [get_ports {LCD_G[1]}] set_property PACKAGE_PIN M17 [get_ports {LCD_B[1]}] set_property PACKAGE_PIN U19 [get_ports BL] set_property PACKAGE_PIN T10 [get_ports {LCD_B[3]}] set_property PACKAGE_PIN N17 [get_ports {LCD_B[5]}] set_property PACKAGE_PIN N16 [get_ports {LCD_B[7]}] set_property PACKAGE_PIN V12 [get_ports LCD_DE] set_property PACKAGE_PIN P18 [get_ports {LCD_G[3]}] set_property PACKAGE_PIN Y17 [get_ports {LCD_G[4]}] set_property PACKAGE_PIN R16 [get_ports {LCD_G[5]}] set_property PACKAGE_PIN R17 [get_ports {LCD_G[7]}] set_property PACKAGE_PIN U12 [get_ports LCD_PCLK] set_property PACKAGE_PIN K18 [get_ports CLK] set_property PACKAGE_PIN V18 [get_ports {LCD_R[1]}] set_property PACKAGE_PIN T17 [get_ports {LCD_R[3]}] set_property PACKAGE_PIN T16 [get_ports {LCD_R[5]}] set_property PACKAGE_PIN U17 [get_ports {LCD_R[7]}] set_property PACKAGE_PIN U20 [get_ports LCD_RST] set_property PACKAGE_PIN W14 [get_ports LCD_VSYNC] set_property PACKAGE_PIN Y14 [get_ports {LCD_B[2]}] set_property PACKAGE_PIN V13 [get_ports LCD_HSYNC] set_property PACKAGE_PIN U15 [get_ports LCD_I2C_SCL] set_property PACKAGE_PIN T15 [get_ports LCD_I2C_SDA] set_property CLOCK_DEDICATED_ROUTE FALSE [get_nets u2/inst/clk_in1_clk_wiz_0] set_property CLOCK_DEDICATED_ROUTE FALSE [get_nets CLK_IBUF]
4.生成bit文件
按下绿色箭头对工程进行编译
![](http://www.hellofpga.com/wp-content/uploads/2021/08/image-19.png)
按下Generate Bitstream 完成综合以及生成bit文件
![](http://www.hellofpga.com/wp-content/uploads/2021/08/image-18.png)
5.SDK程序编写
1)File→Export→Export hardware…,在弹出的对话框中勾选“include bitstream”,点击“OK”确认,如下图所示。
![](http://www.hellofpga.com/wp-content/uploads/2021/08/image-20.png)
![](http://www.hellofpga.com/wp-content/uploads/2021/08/image-24.png)
2)File→Lauch SDK,在弹出的对话框中,保存默认,点击“OK”,如下图所示。
![](http://www.hellofpga.com/wp-content/uploads/2021/08/image-21.png)
系统将自动打开SDK开发环境
![](http://www.hellofpga.com/wp-content/uploads/2021/08/image-22.png)
3)新建一个工程 file→new→Application Project,来新建一个“Application Project”,如下图所示。
![](http://www.hellofpga.com/wp-content/uploads/2021/08/image-23.png)
4)在新建工程名中输入自己的工程名称,点击NEXT
![](http://www.hellofpga.com/wp-content/uploads/2022/11/image-58.png)
5)选择空工程,点击完成FINISH
![](http://www.hellofpga.com/wp-content/uploads/2021/08/image-26.png)
6) 在工程中添加main.c文件 src—>New—>Source File 如下图所示
![](http://www.hellofpga.com/wp-content/uploads/2022/10/image-48.png)
7)在弹出的窗口中填入main.c 并且保存
![](http://www.hellofpga.com/wp-content/uploads/2022/10/image-49.png)
8).打开刚才创建的main.c
然后 写入以下代码 有一个地方值得注意 EMIO的 IO口编号 是从54开始的,也就是我VIVADO 下创建的 EMIO端口,在PS端都是从54-55-56 依次排序的(小贴士 小于54的是MIO 也就是芯片PS的硬件IO口)
#include "xparameters.h" #include "xstatus.h" #include "xplatform_info.h" #include "xgpiops.h" #include "xiicps.h" #include <xil_printf.h> XGpioPs Gpio; /* The driver instance for GPIO Device. */ #define GPIO_DEVICE_ID XPAR_XGPIOPS_0_DEVICE_ID #define EMIO_LCD_RST 55 #define EMIO_LCD_BL 54 void Gpio_Init(void){ XGpioPs_Config *ConfigPtr; ConfigPtr = XGpioPs_LookupConfig(GPIO_DEVICE_ID); XGpioPs_CfgInitialize(&Gpio, ConfigPtr,ConfigPtr->BaseAddr); XGpioPs_SetDirectionPin(&Gpio, EMIO_LCD_RST, 1); XGpioPs_SetOutputEnablePin(&Gpio, EMIO_LCD_RST, 1); XGpioPs_WritePin(&Gpio, EMIO_LCD_RST, 1); XGpioPs_SetDirectionPin(&Gpio, EMIO_LCD_BL, 1); XGpioPs_SetOutputEnablePin(&Gpio, EMIO_LCD_BL, 1); XGpioPs_WritePin(&Gpio, EMIO_LCD_BL, 0); } void LCD_delay(unsigned int i){ volatile int Delay; volatile int k; for(k=0;k<i;k++) for (Delay = 0; Delay < 10000; Delay++); } #define IIC_DEVICE_ID XPAR_XIICPS_0_DEVICE_ID #define IIC_SCLK_RATE 50000 #define IIC_SLAVE_ADDR 0x4C //4D XIicPs Iic; unsigned char Send_date(unsigned int date1,unsigned char date2){ u8 state=0; u8 SendBuffer[4]; /**< Buffer for Transmitting Data */ SendBuffer[0]=(date1>>8)&0xff; SendBuffer[1]=date1&0xff; SendBuffer[2]=0x00; SendBuffer[3]=date2; state=XIicPs_MasterSendPolled(&Iic, SendBuffer,4, IIC_SLAVE_ADDR); return state; } void Send_comm(unsigned int date1){ u8 SendBuffer[2]; /**< Buffer for Transmitting Data */ SendBuffer[0]=(date1>>8)&0xff; SendBuffer[1]=date1&0xff; XIicPs_MasterSendPolled(&Iic, SendBuffer,2, IIC_SLAVE_ADDR); } void Lcd_Init(void){ XGpioPs_WritePin(&Gpio, EMIO_LCD_RST, 1); LCD_delay(1000); XGpioPs_WritePin(&Gpio, EMIO_LCD_RST, 0); LCD_delay(1000); XGpioPs_WritePin(&Gpio, EMIO_LCD_RST, 1); LCD_delay(100); Send_date(0xF000,0x55); Send_date(0xF001,0xAA); Send_date(0xF002,0x52); Send_date(0xF003,0x08); Send_date(0xF004,0x01);//Page 1 //*************AVDD Set AVDD 5.2V*************// Send_date(0xB000,0x0D); Send_date(0xB001,0x0D); Send_date(0xB002,0x0D); //************AVDD ratio****************// Send_date(0xB600,0x34); Send_date(0xB601,0x34); Send_date(0xB602,0x34); //************AVEE -5.2V****************// Send_date(0xB100,0x0D); Send_date(0xB101,0x0D); Send_date(0xB102,0x0D); //***********AVEE ratio*************// Send_date(0xB700,0x34); Send_date(0xB701,0x34); Send_date(0xB702,0x34); //***********VCL -2.5V*************// Send_date(0xB200,0x00); Send_date(0xB201,0x00); Send_date(0xB202,0x00); //**************VCL ratio*****************// Send_date(0xB800,0x24); Send_date(0xB801,0x24); Send_date(0xB802,0x24); //*************VGH 15V (Free pump)*********// Send_date(0xBF00,0x01); Send_date(0xB300,0x0F); Send_date(0xB301,0x0F); Send_date(0xB302,0x0F); //*************VGH ratio*****************// Send_date(0xB900,0x34); Send_date(0xB901,0x34); Send_date(0xB902,0x34); //***************VGL_REG -10V**************// Send_date(0xB500,0x08); Send_date(0xB501,0x08); Send_date(0xB502,0x08); Send_date(0xC200,0x03); //*****************VGLX ratio***************// Send_date(0xBA00,0x24); Send_date(0xBA01,0x24); Send_date(0xBA02,0x24); //*************VGMP/VGSP 4.5V/0V*************// Send_date(0xBC00,0x00); Send_date(0xBC01,0x78); Send_date(0xBC02,0x00); //************VGMN/VGSN -4.5V/0V****************// Send_date(0xBD00,0x00); Send_date(0xBD01,0x78); Send_date(0xBD02,0x00); //************VCOM -1.25V****************// Send_date(0xBE00,0x00); Send_date(0xBE01,0x64); //67-------------- //************Gamma Setting******************// Send_date(0xD100,0x00); Send_date(0xD101,0x33); Send_date(0xD102,0x00); Send_date(0xD103,0x34); Send_date(0xD104,0x00); Send_date(0xD105,0x3a); Send_date(0xD106,0x00); Send_date(0xD107,0x4A); Send_date(0xD108,0x00); Send_date(0xD109,0x5c); Send_date(0xD10A,0x00); Send_date(0xD10B,0x81); Send_date(0xD10C,0x00); Send_date(0xD10D,0xA6); Send_date(0xD10E,0x00); Send_date(0xD10F,0xE5); Send_date(0xD110,0x01); Send_date(0xD111,0x13); Send_date(0xD112,0x01); Send_date(0xD113,0x54); Send_date(0xD114,0x01); Send_date(0xD115,0x82); Send_date(0xD116,0x01); Send_date(0xD117,0xCA); Send_date(0xD118,0x02); Send_date(0xD119,0x00); Send_date(0xD11A,0x02); Send_date(0xD11B,0x01); Send_date(0xD11C,0x02); Send_date(0xD11D,0x34); Send_date(0xD11E,0x02); Send_date(0xD11F,0x67); Send_date(0xD120,0x02); Send_date(0xD121,0x84); Send_date(0xD122,0x02); Send_date(0xD123,0xA4); Send_date(0xD124,0x02); Send_date(0xD125,0xB7); Send_date(0xD126,0x02); Send_date(0xD127,0xCF); Send_date(0xD128,0x02); Send_date(0xD129,0xDE); Send_date(0xD12A,0x02); Send_date(0xD12B,0xF2); Send_date(0xD12C,0x02); Send_date(0xD12D,0xFE); Send_date(0xD12E,0x03); Send_date(0xD12F,0x10); Send_date(0xD130,0x03); Send_date(0xD131,0x33); Send_date(0xD132,0x03); Send_date(0xD133,0x6D); Send_date(0xD200,0x00); Send_date(0xD201,0x33); Send_date(0xD202,0x00); Send_date(0xD203,0x34); Send_date(0xD204,0x00); Send_date(0xD205,0x3A); Send_date(0xD206,0x00); Send_date(0xD207,0x4A); Send_date(0xD208,0x00); Send_date(0xD209,0x5C); Send_date(0xD20A,0x00); Send_date(0xD20B,0x81); Send_date(0xD20C,0x00); Send_date(0xD20D,0xA6); Send_date(0xD20E,0x00); Send_date(0xD20F,0xE5); Send_date(0xD210,0x01); Send_date(0xD211,0x13); Send_date(0xD212,0x01); Send_date(0xD213,0x54); Send_date(0xD214,0x01); Send_date(0xD215,0x82); Send_date(0xD216,0x01); Send_date(0xD217,0xCA); Send_date(0xD218,0x02); Send_date(0xD219,0x00); Send_date(0xD21A,0x02); Send_date(0xD21B,0x01); Send_date(0xD21C,0x02); Send_date(0xD21D,0x34); Send_date(0xD21E,0x02); Send_date(0xD21F,0x67); Send_date(0xD220,0x02); Send_date(0xD221,0x84); Send_date(0xD222,0x02); Send_date(0xD223,0xA4); Send_date(0xD224,0x02); Send_date(0xD225,0xB7); Send_date(0xD226,0x02); Send_date(0xD227,0xCF); Send_date(0xD228,0x02); Send_date(0xD229,0xDE); Send_date(0xD22A,0x02); Send_date(0xD22B,0xF2); Send_date(0xD22C,0x02); Send_date(0xD22D,0xFE); Send_date(0xD22E,0x03); Send_date(0xD22F,0x10); Send_date(0xD230,0x03); Send_date(0xD231,0x33); Send_date(0xD232,0x03); Send_date(0xD233,0x6D); Send_date(0xD300,0x00); Send_date(0xD301,0x33); Send_date(0xD302,0x00); Send_date(0xD303,0x34); Send_date(0xD304,0x00); Send_date(0xD305,0x3A); Send_date(0xD306,0x00); Send_date(0xD307,0x4A); Send_date(0xD308,0x00); Send_date(0xD309,0x5C); Send_date(0xD30A,0x00); Send_date(0xD30B,0x81); Send_date(0xD30C,0x00); Send_date(0xD30D,0xA6); Send_date(0xD30E,0x00); Send_date(0xD30F,0xE5); Send_date(0xD310,0x01); Send_date(0xD311,0x13); Send_date(0xD312,0x01); Send_date(0xD313,0x54); Send_date(0xD314,0x01); Send_date(0xD315,0x82); Send_date(0xD316,0x01); Send_date(0xD317,0xCA); Send_date(0xD318,0x02); Send_date(0xD319,0x00); Send_date(0xD31A,0x02); Send_date(0xD31B,0x01); Send_date(0xD31C,0x02); Send_date(0xD31D,0x34); Send_date(0xD31E,0x02); Send_date(0xD31F,0x67); Send_date(0xD320,0x02); Send_date(0xD321,0x84); Send_date(0xD322,0x02); Send_date(0xD323,0xA4); Send_date(0xD324,0x02); Send_date(0xD325,0xB7); Send_date(0xD326,0x02); Send_date(0xD327,0xCF); Send_date(0xD328,0x02); Send_date(0xD329,0xDE); Send_date(0xD32A,0x02); Send_date(0xD32B,0xF2); Send_date(0xD32C,0x02); Send_date(0xD32D,0xFE); Send_date(0xD32E,0x03); Send_date(0xD32F,0x10); Send_date(0xD330,0x03); Send_date(0xD331,0x33); Send_date(0xD332,0x03); Send_date(0xD333,0x6D); Send_date(0xD400,0x00); Send_date(0xD401,0x33); Send_date(0xD402,0x00); Send_date(0xD403,0x34); Send_date(0xD404,0x00); Send_date(0xD405,0x3A); Send_date(0xD406,0x00); Send_date(0xD407,0x4A); Send_date(0xD408,0x00); Send_date(0xD409,0x5C); Send_date(0xD40A,0x00); Send_date(0xD40B,0x81); Send_date(0xD40C,0x00); Send_date(0xD40D,0xA6); Send_date(0xD40E,0x00); Send_date(0xD40F,0xE5); Send_date(0xD410,0x01); Send_date(0xD411,0x13); Send_date(0xD412,0x01); Send_date(0xD413,0x54); Send_date(0xD414,0x01); Send_date(0xD415,0x82); Send_date(0xD416,0x01); Send_date(0xD417,0xCA); Send_date(0xD418,0x02); Send_date(0xD419,0x00); Send_date(0xD41A,0x02); Send_date(0xD41B,0x01); Send_date(0xD41C,0x02); Send_date(0xD41D,0x34); Send_date(0xD41E,0x02); Send_date(0xD41F,0x67); Send_date(0xD420,0x02); Send_date(0xD421,0x84); Send_date(0xD422,0x02); Send_date(0xD423,0xA4); Send_date(0xD424,0x02); Send_date(0xD425,0xB7); Send_date(0xD426,0x02); Send_date(0xD427,0xCF); Send_date(0xD428,0x02); Send_date(0xD429,0xDE); Send_date(0xD42A,0x02); Send_date(0xD42B,0xF2); Send_date(0xD42C,0x02); Send_date(0xD42D,0xFE); Send_date(0xD42E,0x03); Send_date(0xD42F,0x10); Send_date(0xD430,0x03); Send_date(0xD431,0x33); Send_date(0xD432,0x03); Send_date(0xD433,0x6D); Send_date(0xD500,0x00); Send_date(0xD501,0x33); Send_date(0xD502,0x00); Send_date(0xD503,0x33); Send_date(0xD504,0x00); Send_date(0xD505,0x3A); Send_date(0xD506,0x00); Send_date(0xD507,0x4A); Send_date(0xD508,0x00); Send_date(0xD509,0x5C); Send_date(0xD50A,0x00); Send_date(0xD50B,0x81); Send_date(0xD50C,0x00); Send_date(0xD50D,0xA6); Send_date(0xD50E,0x00); Send_date(0xD50F,0xE5); Send_date(0xD510,0x01); Send_date(0xD511,0x13); Send_date(0xD512,0x01); Send_date(0xD513,0x54); Send_date(0xD514,0x01); Send_date(0xD515,0x82); Send_date(0xD516,0x01); Send_date(0xD517,0xCA); Send_date(0xD518,0x02); Send_date(0xD519,0x00); Send_date(0xD51A,0x02); Send_date(0xD51B,0x01); Send_date(0xD51C,0x02); Send_date(0xD51D,0x34); Send_date(0xD51E,0x02); Send_date(0xD51F,0x67); Send_date(0xD520,0x02); Send_date(0xD521,0x84); Send_date(0xD522,0x02); Send_date(0xD523,0xA4); Send_date(0xD524,0x02); Send_date(0xD525,0xB7); Send_date(0xD526,0x02); Send_date(0xD527,0xCF); Send_date(0xD528,0x02); Send_date(0xD529,0xDE); Send_date(0xD52A,0x02); Send_date(0xD52B,0xF2); Send_date(0xD52C,0x02); Send_date(0xD52D,0xFE); Send_date(0xD52E,0x03); Send_date(0xD52F,0x10); Send_date(0xD530,0x03); Send_date(0xD531,0x33); Send_date(0xD532,0x03); Send_date(0xD533,0x6D); Send_date(0xD600,0x00); Send_date(0xD601,0x33); Send_date(0xD602,0x00); Send_date(0xD603,0x34); Send_date(0xD604,0x00); Send_date(0xD605,0x3A); Send_date(0xD606,0x00); Send_date(0xD607,0x4A); Send_date(0xD608,0x00); Send_date(0xD609,0x5C); Send_date(0xD60A,0x00); Send_date(0xD60B,0x81); Send_date(0xD60C,0x00); Send_date(0xD60D,0xA6); Send_date(0xD60E,0x00); Send_date(0xD60F,0xE5); Send_date(0xD610,0x01); Send_date(0xD611,0x13); Send_date(0xD612,0x01); Send_date(0xD613,0x54); Send_date(0xD614,0x01); Send_date(0xD615,0x82); Send_date(0xD616,0x01); Send_date(0xD617,0xCA); Send_date(0xD618,0x02); Send_date(0xD619,0x00); Send_date(0xD61A,0x02); Send_date(0xD61B,0x01); Send_date(0xD61C,0x02); Send_date(0xD61D,0x34); Send_date(0xD61E,0x02); Send_date(0xD61F,0x67); Send_date(0xD620,0x02); Send_date(0xD621,0x84); Send_date(0xD622,0x02); Send_date(0xD623,0xA4); Send_date(0xD624,0x02); Send_date(0xD625,0xB7); Send_date(0xD626,0x02); Send_date(0xD627,0xCF); Send_date(0xD628,0x02); Send_date(0xD629,0xDE); Send_date(0xD62A,0x02); Send_date(0xD62B,0xF2); Send_date(0xD62C,0x02); Send_date(0xD62D,0xFE); Send_date(0xD62E,0x03); Send_date(0xD62F,0x10); Send_date(0xD630,0x03); Send_date(0xD631,0x33); Send_date(0xD632,0x03); Send_date(0xD633,0x6D); //**************LV2 Page 0 enable*************// Send_date(0xF000,0x55); Send_date(0xF001,0xAA); Send_date(0xF002,0x52); Send_date(0xF003,0x08); Send_date(0xF004,0x00);//Page 0 //Send_date(0xB000,0x00);//add RGB mode2 //Send_date(0xB001,0x10); //Send_date(0xB002,0x10); //Send_date(0xB003,0x10); //Send_date(0xB004,0x10); Send_date(0xB300,0x00); //*************480x800*********************// Send_date(0xB500,0x50); //***************Display control**************// Send_date(0xB100,0xCC); Send_date(0xB101,0x00); //***************Source hold time*************// Send_date(0xB600,0x05); //**************Gate EQ control***************// Send_date(0xB700,0x70); Send_date(0xB701,0x70); //*************Source EQ control (Mode 2)******// Send_date(0xB800,0x01); Send_date(0xB801,0x03); Send_date(0xB802,0x03); Send_date(0xB803,0x03); //************Inversion mode (2-dot)***********// Send_date(0xBC00,0x02); Send_date(0xBC01,0x00); Send_date(0xBC02,0x00); //***************Frame rate***************// /* Send_date(0xBD00,0x01); Send_date(0xBD01,0x84); Send_date(0xBD02,0x1C); //0X1C Send_date(0xBD03,0x1C); Send_date(0xBD04,0x00);*/ //********Timing control 4H w/ 4-Delayms *******// Send_date(0xC900,0xD0); Send_date(0xC901,0x02); Send_date(0xC902,0x50); Send_date(0xC903,0x50); Send_date(0xC904,0x50); Send_date(0x3600,0x00);//00 // Send_date(0x3600,0xe0);//00 // // Send_date(0x2a00,0x00); // Send_date(0x2a01,0x00); // Send_date(0x2a02,0x03); // Send_date(0x2a03,0x1f); // // Send_date(0x2b00,0x00); // Send_date(0x2b01,0x00); // Send_date(0x2b02,0x01); // Send_date(0x2b03,0xdf); Send_date(0x3500,0x00); //Send_date(0x3A00,0x55); Send_date(0x3A00,0x07);//RGB888 Send_comm(0x1100); LCD_delay(120); Send_comm(0x2900); LCD_delay(10); Send_comm(0x2C00); XGpioPs_WritePin(&Gpio, EMIO_LCD_BL, 1); } void I2C_init(){ XIicPs_Config *Config; Config = XIicPs_LookupConfig(IIC_DEVICE_ID); XIicPs_CfgInitialize(&Iic, Config, Config->BaseAddress); XIicPs_SetSClk(&Iic, IIC_SCLK_RATE); } int main(void) { Gpio_Init(); I2C_init(); Lcd_Init(); while(1); return XST_SUCCESS; }
主程序种 只对GPIO I2C 的硬件资源进行初始化, 然后通过Lcd_Init();将屏幕的初始化指令通过I2C 对LCD进行配置, 完成后打开背光EMIO_LCD_BL
6.下载到板子上进行验证
选中工程中的硬件平台,并点击右键→Program FPGA,在弹出的对话框中选择默认,点击“program”,完成FPGA PL部分的Program工作
![](http://www.hellofpga.com/wp-content/uploads/2021/08/image-42.png)
2)选中我们生成的GPIO工程 展开绿色箭头(RUN)右边的图标,选择Run As→1 Launch on Hardware(System Debugger)
![](http://www.hellofpga.com/wp-content/uploads/2022/11/image-59.png)
可以看到板子上的屏幕开始显示图像,并且以2秒的时间间隔在变换着不同的颜色
![](http://www.hellofpga.com/wp-content/uploads/2022/11/image-60.png)
![](http://www.hellofpga.com/wp-content/uploads/2022/11/image-61.png)
备注 :为了方便调试可以按照下列描述进行勾选,这样每次debug的时候就自动重新对PL部分进行配置了(强烈推荐把每个工程都这样设置)
![](http://www.hellofpga.com/wp-content/uploads/2022/10/image-51.png)
![](http://www.hellofpga.com/wp-content/uploads/2022/10/image-39.png)
之后点 APPLY 然后 再选择Run As→1 Launch on Hardware(System Debugger)就可
另外 此次芯片用的是NT35510 ,内部是带GRAM的,默认是竖屏显示(通过配置 我们可以将屏幕设置成横屏 也就是从480X800改成800X480),只需要将MV 和 显示区域进行调整就可,大家可以自行尝试(实际横屏可以显示,但是横屏的时候画面切换会出现斜对角撕裂,所以这里就不推荐用横屏了,如需要横屏可以在ZYNQ将图像缓存到DDR上,做软件横屏,效果会比硬件配置成横屏更好,后面有时间会进行演示)
另外I2C配置部分也可以用VERILOG去编写,后面有时间会更新这块
板子上的触摸屏后续会例程上会增加
以下是本次项目的完整工程 仅供参考