Altera FPGA LCD1602液晶顯示屏封裝
阿新 • • 發佈:2019-01-09
//lcd顯示模組 module lcd_IP_model(clk,rst,data_buf,lcd_e,lcd_rw,lcd_rs,lcd_data); input clk; input rst; input [255:0]data_buf; //資料介面 output lcd_e; output lcd_rw; output lcd_rs; output [7:0]lcd_data; //--------------------------------------------------------------- //分頻得到clk_800Hz reg [16:0]cnt; reg clk_lcd; always @(posedge clk or negedge rst) if(!rst) cnt <= 1'b0; else begin cnt <= cnt + 1'b1; if( cnt == 17'd31249) begin cnt <= 1'b0; clk_lcd <= ~clk_lcd; end end //--------------------------------------------------------------- reg [2:0]func; //狀態機func reg [3:0]com_cnt; //com_buf_bit的計數模組 reg [5:0]data_cnt; //data_buf_bit計數模組 reg [87:0]com_buf_bit; //11條lcd螢幕指令 每條8bit,11條就需要 11x8=88bit reg [255:0]data_buf_bit;//lcd 每行16個字元,一共兩行,總共32個字元,一個字元需要8bit顯示,所以32x8=256bit 參考LCD1602液晶顯示控制部分 parameter set0=4'd1,set1=4'd2,dat1=4'd3,set2=4'd4,dat2=4'd5,done=4'd6; parameter com_buf={8'h02,8'h06,8'h0C,8'h38,8'h80,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00};//LCD1602指令,對螢幕初始化 //--------------------------------------------------------------- reg [7:0]lcd_data; reg lcd_rs; reg en; reg [255:0]data; //因為封裝成ip核所以採用一個暫存器把data_buf值存起來, //後面做對比用,如果data值變化,顯示內容也就變化 always @(posedge clk_lcd or negedge rst) begin if(!rst) com_buf_bit <= 8'h01; //清屏指令 else begin en <= 0; //寫指令 case(func) //液晶屏初始化 set0: begin com_buf_bit <= com_buf; data_buf_bit <= data_buf; data <= data_buf; //data_buf存到暫存器data裡面 com_cnt <= 1'b0; data_cnt <= 1'b0; func <= set1; end //--------------------------------------------------------------- set1: begin lcd_rs <= 0; //寫指令 lcd_data <= com_buf_bit[87:80]; com_buf_bit <= (com_buf_bit<<8); com_cnt <= com_cnt + 1'b1; if(com_cnt <= 10) //共11次,11條lcd指令 func <= set1; else begin func <= dat1; com_cnt <= 1'b0; end end //--------------------------------------------------------------- dat1: begin lcd_rs <= 1; //寫資料 lcd_data <= data_buf_bit[255:248]; data_buf_bit <= (data_buf_bit<<8); data_cnt <= data_cnt + 1'b1; if(data_cnt < 15) //共16次 液晶屏第一行顯示的內容 func <= dat1; else func <= set2; end //--------------------------------------------------------------- set2: begin lcd_rs <= 0; //寫指令 lcd_data <= 8'hC0; //表示第二行第一位 func <= dat2; end //--------------------------------------------------------------- dat2: begin lcd_rs <= 1; //寫資料 lcd_data <= data_buf_bit[255:248]; data_buf_bit <= (data_buf_bit<<8); data_cnt <= data_cnt + 1'b1; if(data_cnt < 31) //共32次 把第二行的內容顯示在螢幕上 func <= dat2; //不能把第一行字元顯示出來,所以採用分兩次寫資料 else begin func <= done; data_cnt <= 1'b0; end end //--------------------------------------------------------------- done: begin if(data_buf!==data ) //判斷有沒有新送進來的資料,對比法 func <= set0; //有就回液晶屏初始化 else begin func <= done; //沒有就結束 en <= 1; end end default:func <= set0; endcase end end //--------------------------------------------------------------- assign lcd_e = clk_lcd | en; assign lcd_rw = 0; endmodule