硬件說明
我們的STEP-BaseBoard底板上集成了1.8寸彩色液晶屏TFT_LCD模塊,大家可以驅(qū)動LCD顯示文字、圖片或動態(tài)的波形。首先了解一下液晶屏模塊,相關(guān)資料下載:https://pan.baidu.com/s/1bp6AYsR
框圖如下:
原理圖如下:
原理圖中的器件U1為液晶屏,液晶屏為1.8寸,128RGB160像素,串行總線(SPI),液晶屏集成了ST7735S的驅(qū)動器,處理器與ST7735S通信完成液晶屏的顯示控制
ST7735S為132RGBx162像素點262K控制器/驅(qū)動器,芯片可以直接跟外部處理器連接,支持串行SPI通信和8/9/16/18位并行通信(本液晶屏集成ST7735S時沒有留并行接口,所以只能使用串行通信),詳細(xì)參數(shù)請參考數(shù)據(jù)手冊:st7735s_datasheet.pdf
Verilog代碼
//-------------------------------------------------------------------- //>>>>>>>>>>>>>>>>>>>>>>>>>COPYRIGHTNOTICE<<<<<<<<<<<<<<<<<<<<<<<<< //-------------------------------------------------------------------- //Module:LCD_RGB // //Author:Step // //Description:DriveTFT_RGB_LCD_1.8todisplay // //-------------------------------------------------------------------- //CodeRevisionHistory: //-------------------------------------------------------------------- //Version:|Mod.Date:|ChangesMade: //V1.1|2016/10/30|Initialver //-------------------------------------------------------------------- moduleLCD_RGB#( parameterLCD_W=8'd132, //液晶屏像素寬度 parameterLCD_H=8'd162 //液晶屏像素高度)( input clk_in, //12MHz系統(tǒng)時鐘 input rst_n_in, //系統(tǒng)復(fù)位,低有效 output reg ram_lcd_clk_en, //RAM時鐘使能 output reg [7:0] ram_lcd_addr, //RAM地址信號 input [131:0] ram_lcd_data, //RAM數(shù)據(jù)信號 output reg lcd_rst_n_out, //LCD液晶屏復(fù)位 output reg lcd_bl_out, //LCD背光控制 output reg lcd_dc_out, //LCD數(shù)據(jù)指令控制 output reg lcd_clk_out, //LCD時鐘信號 output reg lcd_data_out //LCD數(shù)據(jù)信號 ); localparam INIT_DEPTH=16'd73;//LCD初始化的命令及數(shù)據(jù)的數(shù)量 localparam RED = 16'hf800; //紅色 localparam GREEN = 16'h07e0; //綠色 localparam BLUE = 16'h001f; //藍(lán)色 localparam BLACK = 16'h0000; //黑色 localparam WHITE = 16'hffff; //白色 localparam YELLOW = 16'hffe0; //黃色 localparam IDLE = 3'd0; localparam MAIN = 3'd1; localparam INIT = 3'd2; localparam SCAN = 3'd3; localparam WRITE = 3'd4; localparam DELAY = 3'd5; localparam LOW = 1'b0; localparam HIGH = 1'b1; //assign lcd_bl_out=HIGH; //backlightactivehighlevel wire [15:0] color_t = YELLOW; //頂層色為黃色 wire [15:0] color_b = BLACK; //背景色為黑色 reg [7:0] x_cnt; reg [7:0] y_cnt; reg [131:0] ram_data_r; reg [8:0] data_reg; // reg [8:0] reg_setxy [10:0]; reg [8:0] reg_init [72:0]; reg [2:0] cnt_main; reg [2:0] cnt_init; reg [2:0] cnt_scan; reg [5:0] cnt_write; reg [15:0] cnt_delay; reg [15:0] num_delay; reg [15:0] cnt; reg high_word; reg [2:0] state=IDLE; reg [2:0] state_back=IDLE; always@(posedgeclk_inornegedgerst_n_in)begin if(!rst_n_in)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; lcd_bl_out<=LOW; state<=IDLE; state_back<=IDLE; endelsebegin case(state) 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狀態(tài) 3'd0: beginstate<=INIT;cnt_main<=cnt_main+1'b1;end 3'd1: beginstate<=SCAN;cnt_main<=cnt_main+1'b1;end 3'd2: begincnt_main<=1'b1; end default:state<=IDLE; endcase end INIT:begin //初始化狀態(tài) case(cnt_init) 3'd0: beginlcd_rst_n_out<=1'b0; cnt_init<=cnt_init+1'b1; end //復(fù)位有效 3'd1: beginnum_delay<=16'd3000; state<=DELAY; state_back<=INIT; cnt_init<=cnt_init+1'b1;end //延時 3'd2: beginlcd_rst_n_out<=1'b1; cnt_init<=cnt_init+1'b1; end //復(fù)位恢復(fù) 3'd3: beginnum_delay<=16'd3000; state<=DELAY; state_back<=INIT; cnt_init<=cnt_init+1'b1; end //延時 3'd4: begin if(cnt>=INIT_DEPTH)begin //當(dāng)73條指令及數(shù)據(jù)發(fā)出后,配置完成 cnt<=16'd0; cnt_init<=cnt_init+1'b1; endelsebegin data_reg<=reg_init[cnt]; if(cnt==16'd0)num_delay<=16'd50000;//第一條指令需要較長延時 elsenum_delay<=16'd50; cnt<=cnt+16'd1; state<=WRITE; state_back<=INIT; end end 3'd5: begincnt_init<=1'b0; state<=MAIN;end //初始化完成,返回MAIN狀態(tài) default:state<=IDLE; endcase end SCAN:begin //刷屏狀態(tài),從RAM中讀取數(shù)據(jù)刷屏 case(cnt_scan) 3'd0: begin//確定刷屏的區(qū)域坐標(biāo),這里為全屏 if(cnt>=11)begin // cnt<=16'd0; cnt_scan<=cnt_scan+1'b1; endelsebegin data_reg<=reg_setxy[cnt]; cnt<=cnt+16'd1; num_delay<=16'd50; state<=WRITE; state_back<=SCAN; end end 3'd1: beginram_lcd_clk_en<=HIGH; ram_lcd_addr<=y_cnt; cnt_scan<=cnt_scan+1'b1; end //RAM時鐘使能 3'd2: begincnt_scan<=cnt_scan+1'b1; end //延時一個時鐘 3'd3: beginram_lcd_clk_en<=LOW; ram_data_r<=ram_lcd_data; cnt_scan<=cnt_scan+1'b1; end //讀取RAM數(shù)據(jù),同時關(guān)閉RAM時鐘使能 3'd4: begin //每個像素點需要16bit的數(shù)據(jù),SPI每次傳8bit,兩次分別傳送高8位和低8位 if(x_cnt>=LCD_W)begin //當(dāng)一個數(shù)據(jù)(一行屏幕)寫完后, x_cnt<=8'd0; if(y_cnt>=LCD_H)beginy_cnt<=8'd0; cnt_scan<=cnt_scan+1'b1; end //如果是最后一行就跳出循環(huán) elsebeginy_cnt<=y_cnt+1'b1; cnt_scan<=3'd1; end //否則跳轉(zhuǎn)至RAM時鐘使能,循環(huán)刷屏 endelsebegin if(high_word)data_reg<={1'b1,(ram_data_r[x_cnt]?color_t[15:8]:color_b[15:8])}; //根據(jù)相應(yīng)bit的狀態(tài)判定顯示頂層色或背景色,根據(jù)high_word的狀態(tài)判定寫高8位或低8位 elsebegindata_reg<={1'b1,(ram_data_r[x_cnt]?color_t[7:0]:color_b[7:0])}; x_cnt<=x_cnt+1'b1; end //根據(jù)相應(yīng)bit的狀態(tài)判定顯示頂層色或背景色,根據(jù)high_word的狀態(tài)判定寫高8位或低8位,同時指向下一個bit high_word<=~high_word; //high_word的狀態(tài)翻轉(zhuǎn) num_delay<=16'd50; //設(shè)定延時時間 state<=WRITE; //跳轉(zhuǎn)至WRITE狀態(tài) state_back<=SCAN; //執(zhí)行完WRITE及DELAY操作后返回SCAN狀態(tài) end end 3'd5: begincnt_scan<=1'b0; lcd_bl_out<=HIGH; state<=MAIN; end default:state<=IDLE; endcase end WRITE:begin //WRITE狀態(tài),將數(shù)據(jù)按照SPI時序發(fā)送給屏幕 if(cnt_write>=6'd17)cnt_write<=1'b0; elsecnt_write<=cnt_write+1'b1; case(cnt_write) 6'd0: beginlcd_dc_out<=data_reg[8]; end //9位數(shù)據(jù)最高位為命令數(shù)據(jù)控制位 6'd1: beginlcd_clk_out<=LOW; lcd_data_out<=data_reg[7]; end //先發(fā)高位數(shù)據(jù) 6'd2: beginlcd_clk_out<=HIGH; end 6'd3: beginlcd_clk_out<=LOW; lcd_data_out<=data_reg[6]; end 6'd4: beginlcd_clk_out<=HIGH; end 6'd5: beginlcd_clk_out<=LOW; lcd_data_out<=data_reg[5]; end 6'd6: beginlcd_clk_out<=HIGH; end 6'd7: beginlcd_clk_out<=LOW; lcd_data_out<=data_reg[4]; end 6'd8: beginlcd_clk_out<=HIGH;e nd 6'd9: beginlcd_clk_out<=LOW; lcd_data_out<=data_reg[3]; end 6'd10: beginlcd_clk_out<=HIGH; end 6'd11: beginlcd_clk_out<=LOW; lcd_data_out<=data_reg[2]; end 6'd12: beginlcd_clk_out<=HIGH; end 6'd13: beginlcd_clk_out<=LOW; lcd_data_out<=data_reg[1]; end 6'd14: beginlcd_clk_out<=HIGH; end 6'd15: beginlcd_clk_out<=LOW; lcd_data_out<=data_reg[0]; end //后發(fā)低位數(shù)據(jù) 6'd16: beginlcd_clk_out<=HIGH; end 6'd17: beginlcd_clk_out<=LOW; state<=DELAY; end // default:state<=IDLE; endcase end DELAY:begin //延時狀態(tài) if(cnt_delay>=num_delay)begin cnt_delay<=16'd0; state<=state_back; endelsecnt_delay<=cnt_delay+1'b1; end default:state<=IDLE; endcase end end //dataforsetxy initial //設(shè)定顯示區(qū)域指令及數(shù)據(jù) 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 //dataforinit initial //LCD初始化的命令及數(shù)據(jù) 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
小結(jié)
本節(jié)主要為大家講解了1.8寸RGB液晶屏圖片顯示的框架,需要大家掌握的同時自己創(chuàng)建工程,通過整個設(shè)計流程,生成FPGA配置文件加載測試。