差别
这里会显示出您选择的修订版和当前版本之间的差别。
两侧同时换到之前的修订记录 前一修订版 后一修订版 | 前一修订版 | ||
lcd显示模块 [2017/09/08 08:35] anran [硬件说明] |
lcd显示模块 [2020/01/18 21:48] (当前版本) gongyu |
||
---|---|---|---|
行 1: | 行 1: | ||
- | ======基于STEP FPGA的SPI RGB液晶屏显示驱动====== | + | ### 基于STEP FPGA的SPI RGB液晶屏显示驱动 |
本节将和大家一起使用FPGA驱动底板上的1.8寸RGB液晶屏实现图片显示功能。 | 本节将和大家一起使用FPGA驱动底板上的1.8寸RGB液晶屏实现图片显示功能。 | ||
- | + | --- | |
- | ====硬件说明==== | + | #### 硬件说明 |
- | ------- | + | 我们的[[STEP-BaseBoard]]底板上集成了1.8寸彩色液晶屏TFT_LCD模块,大家可以驱动LCD显示文字、图片或动态的波形。 |
- | 待更新 | + | |
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | VGA(video graphics array)即视频图形阵列,是IBM在1987年随PS/2一起推出的使用模拟信号的一种视频传输标准。VGA接口分公口和母口,如下图: | + | |
\\ | \\ | ||
- | {{ :vga接口.jpg?400 |}} | + | 首先了解一下液晶屏模块,相关资料下载:[[https://pan.baidu.com/s/1bp6AYsR]] |
+ | {{ :1.8寸lcd模块图.png?800 |}} | ||
\\ | \\ | ||
- | VGA接口引脚定义如下: | + | 框图如下: |
+ | {{ :1.8寸lcd模块规格书.png?800 |}} | ||
\\ | \\ | ||
- | {{ :vga接口定义.jpg?800 |}} | + | 原理图如下: |
+ | {{ :1.8寸lcd模块原理图.png?800 |}} | ||
\\ | \\ | ||
- | 一个标准的VGA接口应该有以下端口: | + | 原理图中的器件U1为液晶屏,液晶屏为1.8寸,128*RGB*160像素,串行总线(SPI),液晶屏集成了ST7735S的驱动器,处理器与ST7735S通信完成液晶屏的显示控制 |
+ | {{ :1.8寸lcd规格书.png?800 |}} | ||
\\ | \\ | ||
- | * 红绿蓝三色信号(R\G\B) | ||
- | * 行场同步信号(HS\VS) | ||
- | * 以及很多的地屏蔽; | ||
- | 三色信号都是模拟信号,行场同步信号都是数字信号; | ||
- | \\ | ||
- | 对于VGA的接口模拟电压,为0~0.714V,0代表无色,0.714代表满色,FPGA输出3.3V,所以还必须要经过DAC的转换。现今有两种比较成熟的方法:电阻分压方式和DAC转换方式。 | ||
- | \\ | ||
- | 我们的底板上就是采用的电阻分压的方式,因VGA显示器端有75欧的下拉电阻,为了得到0.714V的电压我们给RGB信号线上串入270欧的电阻,3.3V*75/(270+75)=0.717V。如下 | ||
- | \\ | ||
- | {{ :vga接口电路.png?800 |}} | ||
- | \\ | ||
- | VGA驱动显示器用的是扫描的方式,逐行扫描the HS (Horizontal Synchronization)逐行扫描是扫描从屏幕的左上角一点开始,由左向右逐点扫描,每扫描完一行,电子束回到屏幕的左边下一行的起始位置,在这期间CRT(阴极射线显像管)对电子束进行消隐,每行结束时,用行同步信号进行同步;当扫描完所有行之后形成一帧,用场同步信号进行同步,并使扫描回到屏幕左上方,同时进行场消隐,开始下一帧。VGA一直在扫描,每一场的扫描包括了若干行扫描,依次循环; | ||
- | \\ | ||
- | VGA显示时序如下: | ||
- | {{ :vga时序.png?800 |}} | ||
- | \\ | ||
- | VGA显示区域和消隐区域: | ||
- | {{ :vga显示区域.png?800 |}} | ||
- | \\ | ||
- | 常见的VGA显示模式: | ||
- | {{ :常见的vga显示模式.png?800 |}} | ||
- | ====Verilog代码==== | + | ST7735S为132RGBx162像素点262K控制器/驱动器,芯片可以直接跟外部处理器连接,支持串行SPI通信和8/9/16/18位并行通信(本液晶屏集成ST7735S时没有留并行接口,所以只能使用串行通信),详细参数请参考数据手册:{{:st7735s_datasheet.pdf|}} |
- | ------ | + | |
- | <code verilog> | + | |
- | // -------------------------------------------------------------------- | + | |
- | // >>>>>>>>>>>>>>>>>>>>>>>>> COPYRIGHT NOTICE <<<<<<<<<<<<<<<<<<<<<<<<< | + | |
- | // -------------------------------------------------------------------- | + | |
- | // Module: Param_define | + | |
- | // | + | |
- | // Author: Step | + | |
- | // | + | |
- | // Description: Param_define | + | |
- | // | + | |
- | // Web: www.stepfpga.com | + | |
- | // | + | |
- | // -------------------------------------------------------------------- | + | |
- | // Code Revision History : | + | |
- | // -------------------------------------------------------------------- | + | |
- | // Version: |Mod. Date: |Changes Made: | + | |
- | // V1.1 |2016/10/30 |Initial ver | + | |
- | // -------------------------------------------------------------------- | + | |
- | `timescale 1ns / 1ns | + | |
- | //VGA显示器驱动只需要5个信号即可(行同步、场同步、红色、绿色、蓝色信号) | + | --- |
- | //红绿蓝三色信号为模拟信号,输入电压范围为0.0V~0.7V | + | #### Verilog代码 |
- | //VGA时序中行同步和场同步都分为四个阶段(同步脉冲、后廊、有效线数、前廊) | + | |
- | //VGA显示有很多模式,每种模式都是有固定的时钟和时序参数,需要根据要求控制 | + | |
- | + | ||
- | `ifdef VGA_800X600_60Hz //不同VGA显示模式相应的参数 | + | |
- | //--------------------------------------------------------------------------- | + | |
- | //-- Horizonal timing information | + | |
- | `define HSYNC_A 16'd128 // 128 | + | |
- | `define HSYNC_B 16'd216 // 128 + 88 | + | |
- | `define HSYNC_C 16'd1016 // 128 + 88 + 800 | + | |
- | `define HSYNC_D 16'd1056 // 128 + 88 + 800 + 40 //行同步脉冲+后廊+有效线数+前廊 | + | |
- | //-- Vertical timing information | + | |
- | `define VSYNC_O 16'd4 // 4 | + | |
- | `define VSYNC_P 16'd27 // 4 + 23 | + | |
- | `define VSYNC_Q 16'd627 // 4 + 23 + 600 | + | |
- | `define VSYNC_R 16'd628 // 4 + 23 + 600 + 1 //场同步脉冲+后廊+有效线数+前廊 | + | |
- | //--------------------------------------------------------------------------- | + | |
- | `endif | + | |
- | + | ||
- | `ifdef VGA_640X480_85Hz //不同VGA显示模式相应的参数 | + | |
- | //--------------------------------------------------------------------------- | + | |
- | //-- Horizonal timing information | + | |
- | `define HSYNC_A 16'd48 // 48 | + | |
- | `define HSYNC_B 16'd160 // 48 + 112 | + | |
- | `define HSYNC_C 16'd800 // 48 + 112 + 640 | + | |
- | `define HSYNC_D 16'd832 // 48 + 112 + 640 + 32 //行同步脉冲+后廊+有效线数+前廊 | + | |
- | //-- Vertical timing information | + | |
- | `define VSYNC_O 16'd3 // 3 | + | |
- | `define VSYNC_P 16'd28 // 3 + 25 | + | |
- | `define VSYNC_Q 16'd508 // 3 + 25 + 480 | + | |
- | `define VSYNC_R 16'd509 // 3 + 25 + 480 + 1 //场同步脉冲+后廊+有效线数+前廊 | + | |
- | //--------------------------------------------------------------------------- | + | |
- | `endif | + | |
- | </code> | + | |
<code verilog> | <code verilog> | ||
行 105: | 行 30: | ||
// >>>>>>>>>>>>>>>>>>>>>>>>> COPYRIGHT NOTICE <<<<<<<<<<<<<<<<<<<<<<<<< | // >>>>>>>>>>>>>>>>>>>>>>>>> COPYRIGHT NOTICE <<<<<<<<<<<<<<<<<<<<<<<<< | ||
// -------------------------------------------------------------------- | // -------------------------------------------------------------------- | ||
- | // Module: Vga_Module | + | // Module: LCD_RGB |
// | // | ||
// Author: Step | // Author: Step | ||
// | // | ||
- | // Description: Vga_Module | + | // Description: Drive TFT_RGB_LCD_1.8 to display |
// | // | ||
// Web: www.stepfpga.com | // Web: www.stepfpga.com | ||
行 119: | 行 44: | ||
// V1.1 |2016/10/30 |Initial ver | // V1.1 |2016/10/30 |Initial ver | ||
// -------------------------------------------------------------------- | // -------------------------------------------------------------------- | ||
- | `define VGA_800X600_60Hz //定义使用的VGA显示模式 | + | module LCD_RGB # |
- | + | ||
- | `ifdef VGA_800X600_60Hz //根据VGA显示模式的定义调用相应的参数 | + | |
- | `include "Param_define.v" //调用Param_define.v文件中的全局定义 | + | |
- | `endif | + | |
- | + | ||
- | module Vga_Module | + | |
( | ( | ||
- | input clk_in, //40MHz系统时钟 | + | parameter LCD_W = 8'd132, //液晶屏像素宽度 |
- | input rst_n_in, //系统复位,低有效 | + | parameter LCD_H = 8'd162 //液晶屏像素高度 |
- | output reg sync_v, //VGA场同步sync_v | + | ) |
- | output reg sync_h, //VGA行同步sync_h | + | ( |
- | output reg [2:0] vga_data //VGA数据MSB~LSB = {R,G,B} | + | input clk_in, //12MHz系统时钟 |
+ | input rst_n_in, //系统复位,低有效 | ||
+ | |||
+ | output reg ram_lcd_clk_en, //RAM时钟使能 | ||
+ | output reg [7:0] ram_lcd_addr, //RAM地址信号 | ||
+ | input [131:0] ram_lcd_data, //RAM数据信号 | ||
+ | |||
+ | output reg lcd_rst_n_out, //LCD液晶屏复位 | ||
+ | output reg lcd_bl_out, //LCD背光控制 | ||
+ | output reg lcd_dc_out, //LCD数据指令控制 | ||
+ | output reg lcd_clk_out, //LCD时钟信号 | ||
+ | output reg lcd_data_out //LCD数据信号 | ||
); | ); | ||
- | |||
- | reg [15:0] x_cnt; | ||
- | reg [15:0] y_cnt; | ||
- | reg vga_valid; | ||
- | //对时钟计数标识VGA一次行扫描需要的时间 | + | localparam INIT_DEPTH = 16'd73; //LCD初始化的命令及数据的数量 |
- | always @ (posedge clk_in or negedge rst_n_in) | + | |
- | if(!rst_n_in) x_cnt <= 16'd0; //复位时初始值 | + | localparam RED = 16'hf800; //红色 |
- | else if(x_cnt >= `HSYNC_D) x_cnt <= 16'd0; //一次行扫描需要1056个时钟(128+88+800+40) | + | localparam GREEN = 16'h07e0; //绿色 |
- | else x_cnt <= x_cnt + 1'b1; | + | localparam BLUE = 16'h001f; //蓝色 |
- | + | localparam BLACK = 16'h0000; //黑色 | |
- | //对行扫描计数标识VGA一次场扫描需要的时间 | + | localparam WHITE = 16'hffff; //白色 |
- | always @ (posedge clk_in or negedge rst_n_in) | + | localparam YELLOW = 16'hffe0; //黄色 |
- | if(!rst_n_in) y_cnt <= 16'd0; //复位时初始值 | + | |
- | else if(x_cnt == `HSYNC_D) begin //每次行扫描时 | + | localparam IDLE = 3'd0; |
- | if(y_cnt >= `VSYNC_R) y_cnt <= 16'd0; //每次场扫描包含628次行扫描 | + | localparam MAIN = 3'd1; |
- | else y_cnt <= y_cnt + 1'b1; | + | localparam INIT = 3'd2; |
- | end else y_cnt <= y_cnt; //在每次行扫描过程中场扫描计数器保持不变 | + | localparam SCAN = 3'd3; |
- | + | localparam WRITE = 3'd4; | |
- | //按照显示模式的参数产生行同步扫描的脉冲 | + | localparam DELAY = 3'd5; |
- | always @ (posedge clk_in or negedge rst_n_in) | + | |
- | if(!rst_n_in) sync_h <= 1'b1; | + | localparam LOW = 1'b0; |
- | else if(x_cnt < `HSYNC_A) sync_h <= 1'b0; | + | localparam HIGH = 1'b1; |
- | else sync_h <= 1'b1; | + | |
- | + | //assign lcd_bl_out = HIGH; // backlight active high level | |
- | //按照显示模式的参数产生场同步扫描的脉冲 | + | |
- | always @ (posedge clk_in or negedge rst_n_in) | + | wire [15:0] color_t = YELLOW; //顶层色为黄色 |
- | if(!rst_n_in) sync_v <= 1'b1; | + | wire [15:0] color_b = BLACK; //背景色为黑色 |
- | else if(y_cnt < `VSYNC_O) sync_v <= 1'b0; | + | |
- | else sync_v <= 1'b1; | + | reg [7:0] x_cnt; |
- | + | reg [7:0] y_cnt; | |
- | //根据行场同步信号的有效线数确定有效显示区域 | + | reg [131:0] ram_data_r; |
- | always @ (posedge clk_in or negedge rst_n_in) | + | |
- | if(!rst_n_in) | + | reg [8:0] data_reg; // |
- | vga_valid <= 1'b0; | + | reg [8:0] reg_setxy [10:0]; |
- | else if((x_cnt > `HSYNC_B) && (x_cnt <`HSYNC_C) && (y_cnt > `VSYNC_P) && (y_cnt < `VSYNC_Q)) | + | reg [8:0] reg_init [72:0]; |
- | vga_valid <= 1'b1; //有效显示区域中vga_valid标志为1 | + | reg [2:0] cnt_main; |
- | else | + | reg [2:0] cnt_init; |
- | vga_valid <= 1'b0; | + | reg [2:0] cnt_scan; |
- | + | reg [5:0] cnt_write; | |
- | //在VGA有效显示区域不同的段显示不同的颜色 | + | reg [15:0] cnt_delay; |
- | always @ (posedge clk_in or negedge rst_n_in) | + | reg [15:0] num_delay; |
- | begin | + | reg [15:0] cnt; |
- | if(!rst_n_in) vga_data = 3'b111; | + | reg high_word; |
- | else if(vga_valid)begin //在有效显示区域内 | + | reg [2:0] state = IDLE; |
- | if((x_cnt > `HSYNC_B) && (x_cnt <= `HSYNC_B + 10'd100)) | + | reg [2:0] state_back = IDLE; |
- | vga_data = 3'b100; //红色 | + | always@(posedge clk_in or negedge rst_n_in) begin |
- | else if((x_cnt > `HSYNC_B + 10'd100) && (x_cnt <= `HSYNC_B + 10'd200)) | + | if(!rst_n_in) begin |
- | vga_data = 3'b010; //绿色 | + | x_cnt <= 8'd0; |
- | else if((x_cnt > `HSYNC_B + 10'd200) && (x_cnt <= `HSYNC_B + 10'd300)) | + | y_cnt <= 8'd0; |
- | vga_data = 3'b001; //蓝色 | + | ram_lcd_clk_en <= 1'b0; |
- | else if((x_cnt > `HSYNC_B + 10'd300) && (x_cnt <= `HSYNC_B + 10'd400)) | + | ram_lcd_addr <= 8'd0; |
- | vga_data = 3'b110; //黄色 | + | cnt_main <= 3'd0; |
- | else if((x_cnt > `HSYNC_B + 10'd400) && (x_cnt <= `HSYNC_B + 10'd500)) | + | cnt_init <= 3'd0; |
- | vga_data = 3'b101; //紫色 | + | cnt_scan <= 3'd0; |
- | else if((x_cnt > `HSYNC_B + 10'd500) && (x_cnt <= `HSYNC_B + 10'd600)) | + | cnt_write <= 6'd0; |
- | vga_data = 3'b011; //青色 | + | cnt_delay <= 16'd0; |
- | else if((x_cnt > `HSYNC_B + 10'd600) && (x_cnt <= `HSYNC_B + 10'd700)) | + | num_delay <= 16'd50; |
- | vga_data = 3'b111; //白色 | + | cnt <= 16'd0; |
- | else if((x_cnt > `HSYNC_B + 10'd700) && (x_cnt <= `HSYNC_B + 10'd800)) | + | high_word <= 1'b1; |
- | vga_data = 3'b000; //黑色 | + | lcd_bl_out <= LOW; |
- | else | + | state <= IDLE; |
- | vga_data = 3'b111; //白色 | + | state_back <= IDLE; |
- | end else | + | end else begin |
- | vga_data = 3'b111; //白色 | + | case(state) |
- | end | + | IDLE:begin |
+ | x_cnt <= 8'd0; | ||
+ | y_cnt <= 8'd0; | ||
+ | ram_lcd_clk_en <= 1'b0; | ||
+ | ram_lcd_addr <= 8'd0; | ||
+ | cnt_main <= 3'd0; | ||
+ | cnt_init <= 3'd0; | ||
+ | cnt_scan <= 3'd0; | ||
+ | cnt_write <= 6'd0; | ||
+ | cnt_delay <= 16'd0; | ||
+ | num_delay <= 16'd50; | ||
+ | cnt <= 16'd0; | ||
+ | high_word <= 1'b1; | ||
+ | state <= MAIN; | ||
+ | state_back <= MAIN; | ||
+ | end | ||
+ | MAIN:begin | ||
+ | case(cnt_main) //MAIN状态 | ||
+ | 3'd0: begin state <= INIT; cnt_main <= cnt_main + 1'b1; end | ||
+ | 3'd1: begin state <= SCAN; cnt_main <= cnt_main + 1'b1; end | ||
+ | 3'd2: begin cnt_main <= 1'b1; end | ||
+ | default: state <= IDLE; | ||
+ | endcase | ||
+ | end | ||
+ | INIT:begin //初始化状态 | ||
+ | case(cnt_init) | ||
+ | 3'd0: begin lcd_rst_n_out <= 1'b0; cnt_init <= cnt_init + 1'b1; end //复位有效 | ||
+ | 3'd1: begin num_delay <= 16'd3000; state <= DELAY; state_back <= INIT; cnt_init <= cnt_init + 1'b1; end //延时 | ||
+ | 3'd2: begin lcd_rst_n_out <= 1'b1; cnt_init <= cnt_init + 1'b1; end //复位恢复 | ||
+ | 3'd3: begin num_delay <= 16'd3000; state <= DELAY; state_back <= INIT; cnt_init <= cnt_init + 1'b1; end //延时 | ||
+ | 3'd4: begin | ||
+ | if(cnt>=INIT_DEPTH) begin //当73条指令及数据发出后,配置完成 | ||
+ | cnt <= 16'd0; | ||
+ | cnt_init <= cnt_init + 1'b1; | ||
+ | end else begin | ||
+ | data_reg <= reg_init[cnt]; | ||
+ | if(cnt==16'd0) num_delay <= 16'd50000; //第一条指令需要较长延时 | ||
+ | else num_delay <= 16'd50; | ||
+ | cnt <= cnt + 16'd1; | ||
+ | state <= WRITE; | ||
+ | state_back <= INIT; | ||
+ | end | ||
+ | end | ||
+ | 3'd5: begin cnt_init <= 1'b0; state <= MAIN; end //初始化完成,返回MAIN状态 | ||
+ | default: state <= IDLE; | ||
+ | endcase | ||
+ | end | ||
+ | SCAN:begin //刷屏状态,从RAM中读取数据刷屏 | ||
+ | case(cnt_scan) | ||
+ | 3'd0: begin //确定刷屏的区域坐标,这里为全屏 | ||
+ | if(cnt >= 11) begin // | ||
+ | cnt <= 16'd0; | ||
+ | cnt_scan <= cnt_scan + 1'b1; | ||
+ | end else begin | ||
+ | data_reg <= reg_setxy[cnt]; | ||
+ | cnt <= cnt + 16'd1; | ||
+ | num_delay <= 16'd50; | ||
+ | state <= WRITE; | ||
+ | state_back <= SCAN; | ||
+ | end | ||
+ | end | ||
+ | 3'd1: begin ram_lcd_clk_en <= HIGH; ram_lcd_addr <= y_cnt; cnt_scan <= cnt_scan + 1'b1; end //RAM时钟使能 | ||
+ | 3'd2: begin cnt_scan <= cnt_scan + 1'b1; end //延时一个时钟 | ||
+ | 3'd3: begin ram_lcd_clk_en <= LOW; ram_data_r <= ram_lcd_data; cnt_scan <= cnt_scan + 1'b1; end //读取RAM数据,同时关闭RAM时钟使能 | ||
+ | 3'd4: begin //每个像素点需要16bit的数据,SPI每次传8bit,两次分别传送高8位和低8位 | ||
+ | if(x_cnt>=LCD_W) begin //当一个数据(一行屏幕)写完后, | ||
+ | x_cnt <= 8'd0; | ||
+ | if(y_cnt>=LCD_H) begin y_cnt <= 8'd0; cnt_scan <= cnt_scan + 1'b1; end //如果是最后一行就跳出循环 | ||
+ | else begin y_cnt <= y_cnt + 1'b1; cnt_scan <= 3'd1; end //否则跳转至RAM时钟使能,循环刷屏 | ||
+ | end else begin | ||
+ | if(high_word) data_reg <= {1'b1,(ram_data_r[x_cnt]? color_t[15:8]:color_b[15:8])}; //根据相应bit的状态判定显示顶层色或背景色,根据high_word的状态判定写高8位或低8位 | ||
+ | else begin data_reg <= {1'b1,(ram_data_r[x_cnt]? color_t[7:0]:color_b[7:0])}; x_cnt <= x_cnt + 1'b1; end //根据相应bit的状态判定显示顶层色或背景色,根据high_word的状态判定写高8位或低8位,同时指向下一个bit | ||
+ | high_word <= ~high_word; //high_word的状态翻转 | ||
+ | num_delay <= 16'd50; //设定延时时间 | ||
+ | state <= WRITE; //跳转至WRITE状态 | ||
+ | state_back <= SCAN; //执行完WRITE及DELAY操作后返回SCAN状态 | ||
+ | end | ||
+ | end | ||
+ | 3'd5: begin cnt_scan <= 1'b0; lcd_bl_out <= HIGH; state <= MAIN; end | ||
+ | default: state <= IDLE; | ||
+ | endcase | ||
+ | end | ||
+ | WRITE:begin //WRITE状态,将数据按照SPI时序发送给屏幕 | ||
+ | if(cnt_write >= 6'd17) cnt_write <= 1'b0; | ||
+ | else cnt_write <= cnt_write + 1'b1; | ||
+ | case(cnt_write) | ||
+ | 6'd0: begin lcd_dc_out <= data_reg[8]; end //9位数据最高位为命令数据控制位 | ||
+ | 6'd1: begin lcd_clk_out <= LOW; lcd_data_out <= data_reg[7]; end //先发高位数据 | ||
+ | 6'd2: begin lcd_clk_out <= HIGH; end | ||
+ | 6'd3: begin lcd_clk_out <= LOW; lcd_data_out <= data_reg[6]; end | ||
+ | 6'd4: begin lcd_clk_out <= HIGH; end | ||
+ | 6'd5: begin lcd_clk_out <= LOW; lcd_data_out <= data_reg[5]; end | ||
+ | 6'd6: begin lcd_clk_out <= HIGH; end | ||
+ | 6'd7: begin lcd_clk_out <= LOW; lcd_data_out <= data_reg[4]; end | ||
+ | 6'd8: begin lcd_clk_out <= HIGH; end | ||
+ | 6'd9: begin lcd_clk_out <= LOW; lcd_data_out <= data_reg[3]; end | ||
+ | 6'd10: begin lcd_clk_out <= HIGH; end | ||
+ | 6'd11: begin lcd_clk_out <= LOW; lcd_data_out <= data_reg[2]; end | ||
+ | 6'd12: begin lcd_clk_out <= HIGH; end | ||
+ | 6'd13: begin lcd_clk_out <= LOW; lcd_data_out <= data_reg[1]; end | ||
+ | 6'd14: begin lcd_clk_out <= HIGH; end | ||
+ | 6'd15: begin lcd_clk_out <= LOW; lcd_data_out <= data_reg[0]; end //后发低位数据 | ||
+ | 6'd16: begin lcd_clk_out <= HIGH; end | ||
+ | 6'd17: begin lcd_clk_out <= LOW; state <= DELAY; end // | ||
+ | default: state <= IDLE; | ||
+ | endcase | ||
+ | end | ||
+ | DELAY:begin //延时状态 | ||
+ | if(cnt_delay >= num_delay) begin | ||
+ | cnt_delay <= 16'd0; | ||
+ | state <= state_back; | ||
+ | end else cnt_delay <= cnt_delay + 1'b1; | ||
+ | end | ||
+ | default:state <= IDLE; | ||
+ | endcase | ||
+ | end | ||
+ | end | ||
+ | |||
+ | // data for setxy | ||
+ | initial //设定显示区域指令及数据 | ||
+ | begin | ||
+ | reg_setxy[0] = {1'b0,8'h2a}; | ||
+ | reg_setxy[1] = {1'b1,8'h00}; | ||
+ | reg_setxy[2] = {1'b1,8'h00}; | ||
+ | reg_setxy[3] = {1'b1,8'h00}; | ||
+ | reg_setxy[4] = {1'b1,LCD_W-1}; | ||
+ | reg_setxy[5] = {1'b0,8'h2b}; | ||
+ | reg_setxy[6] = {1'b1,8'h00}; | ||
+ | reg_setxy[7] = {1'b1,8'h00}; | ||
+ | reg_setxy[8] = {1'b1,8'h00}; | ||
+ | reg_setxy[9] = {1'b1,LCD_H-1}; | ||
+ | reg_setxy[10] = {1'b0,8'h2c}; | ||
+ | end | ||
+ | |||
+ | // data for init | ||
+ | initial //LCD初始化的命令及数据 | ||
+ | begin | ||
+ | reg_init[0] = {1'b0,8'h11}; | ||
+ | reg_init[1] = {1'b0,8'hb1}; | ||
+ | reg_init[2] = {1'b1,8'h05}; | ||
+ | reg_init[3] = {1'b1,8'h3c}; | ||
+ | reg_init[4] = {1'b1,8'h3c}; | ||
+ | reg_init[5] = {1'b0,8'hb2}; | ||
+ | reg_init[6] = {1'b1,8'h05}; | ||
+ | reg_init[7] = {1'b1,8'h3c}; | ||
+ | reg_init[8] = {1'b1,8'h3c}; | ||
+ | reg_init[9] = {1'b0,8'hb3}; | ||
+ | reg_init[10] = {1'b1,8'h05}; | ||
+ | reg_init[11] = {1'b1,8'h3c}; | ||
+ | reg_init[12] = {1'b1,8'h3c}; | ||
+ | reg_init[13] = {1'b1,8'h05}; | ||
+ | reg_init[14] = {1'b1,8'h3c}; | ||
+ | reg_init[15] = {1'b1,8'h3c}; | ||
+ | reg_init[16] = {1'b0,8'hb4}; | ||
+ | reg_init[17] = {1'b1,8'h03}; | ||
+ | reg_init[18] = {1'b0,8'hc0}; | ||
+ | reg_init[19] = {1'b1,8'h28}; | ||
+ | reg_init[20] = {1'b1,8'h08}; | ||
+ | reg_init[21] = {1'b1,8'h04}; | ||
+ | reg_init[22] = {1'b0,8'hc1}; | ||
+ | reg_init[23] = {1'b1,8'hc0}; | ||
+ | reg_init[24] = {1'b0,8'hc2}; | ||
+ | reg_init[25] = {1'b1,8'h0d}; | ||
+ | reg_init[26] = {1'b1,8'h00}; | ||
+ | reg_init[27] = {1'b0,8'hc3}; | ||
+ | reg_init[28] = {1'b1,8'h8d}; | ||
+ | reg_init[29] = {1'b1,8'h2a}; | ||
+ | reg_init[30] = {1'b0,8'hc4}; | ||
+ | reg_init[31] = {1'b1,8'h8d}; | ||
+ | reg_init[32] = {1'b1,8'hee}; | ||
+ | reg_init[32] = {1'b0,8'hc5}; | ||
+ | reg_init[33] = {1'b1,8'h1a}; | ||
+ | reg_init[34] = {1'b0,8'h36}; | ||
+ | reg_init[35] = {1'b1,8'hc0}; | ||
+ | reg_init[36] = {1'b0,8'he0}; | ||
+ | reg_init[37] = {1'b1,8'h04}; | ||
+ | reg_init[38] = {1'b1,8'h22}; | ||
+ | reg_init[39] = {1'b1,8'h07}; | ||
+ | reg_init[40] = {1'b1,8'h0a}; | ||
+ | reg_init[41] = {1'b1,8'h2e}; | ||
+ | reg_init[42] = {1'b1,8'h30}; | ||
+ | reg_init[43] = {1'b1,8'h25}; | ||
+ | reg_init[44] = {1'b1,8'h2a}; | ||
+ | reg_init[45] = {1'b1,8'h28}; | ||
+ | reg_init[46] = {1'b1,8'h26}; | ||
+ | reg_init[47] = {1'b1,8'h2e}; | ||
+ | reg_init[48] = {1'b1,8'h3a}; | ||
+ | reg_init[49] = {1'b1,8'h00}; | ||
+ | reg_init[50] = {1'b1,8'h01}; | ||
+ | reg_init[51] = {1'b1,8'h03}; | ||
+ | reg_init[52] = {1'b1,8'h13}; | ||
+ | reg_init[53] = {1'b0,8'he1}; | ||
+ | reg_init[54] = {1'b1,8'h04}; | ||
+ | reg_init[55] = {1'b1,8'h16}; | ||
+ | reg_init[56] = {1'b1,8'h06}; | ||
+ | reg_init[57] = {1'b1,8'h0d}; | ||
+ | reg_init[58] = {1'b1,8'h2d}; | ||
+ | reg_init[59] = {1'b1,8'h26}; | ||
+ | reg_init[60] = {1'b1,8'h23}; | ||
+ | reg_init[61] = {1'b1,8'h27}; | ||
+ | reg_init[62] = {1'b1,8'h27}; | ||
+ | reg_init[63] = {1'b1,8'h25}; | ||
+ | reg_init[64] = {1'b1,8'h2d}; | ||
+ | reg_init[65] = {1'b1,8'h3b}; | ||
+ | reg_init[66] = {1'b1,8'h00}; | ||
+ | reg_init[67] = {1'b1,8'h01}; | ||
+ | reg_init[68] = {1'b1,8'h04}; | ||
+ | reg_init[69] = {1'b1,8'h13}; | ||
+ | reg_init[70] = {1'b0,8'h3a}; | ||
+ | reg_init[71] = {1'b1,8'h05}; | ||
+ | reg_init[72] = {1'b0,8'h29}; | ||
+ | |||
+ | end | ||
endmodule | endmodule | ||
</code> | </code> | ||
- | ====小结==== | + | |
- | ------ | + | --- |
- | 本节主要为大家讲解了VGA显示的原理、时序及软件设计,需要大家掌握的同时自己创建工程,通过整个设计流程,生成FPGA配置文件加载测试。 | + | #### 小结 |
+ | 本节主要为大家讲解了1.8寸RGB液晶屏图片显示的框架,需要大家掌握的同时自己创建工程,通过整个设计流程,生成FPGA配置文件加载测试。 | ||
\\ | \\ | ||
如果你对Diamond软件的使用不了解,请参考这里:[[lattice_diamond的使用|Diamond的使用]]。 | 如果你对Diamond软件的使用不了解,请参考这里:[[lattice_diamond的使用|Diamond的使用]]。 | ||
- | ====相关资料==== | + | --- |
- | ------ | + | #### 相关资料 |
- | \\ | + | 使用[[STEP-MXO2第二代]]的1.8寸RGB液晶屏显示驱动程序: 后续会有下载连接 待更新 |
- | 使用[[STEP-MXO2第二代]]的VGA显示驱动程序: 后续会有下载连接 待更新 | + | |
\\ | \\ | ||
- | 使用[[STEP-MAX10]]的VGA显示驱动程序: 后续会有下载连接 待更新 | + | 使用[[STEP-MAX10]]的1.8寸RGB液晶屏显示驱动程序: 后续会有下载连接 待更新 |
\\ | \\ |