今天一鼓作气,再研究了一下如何用LCD1602自定义汉字
1、用字模软件获取汉字所对应的数据(因为嫌麻烦所以直接用了网上一个帖子里有关“电”的数据,如下:04,1f,15,1f,15,15,1f,04,07)帖子链接:http://www.51hei.com/mcu/3696.html
2、主要知识点
(1)lcd1602的11个指令集与lcd1602的基本显示,前两篇文章已经详细说过,链接如下
http://www.cnblogs.com/aslmer/p/5801363.html
http://www.cnblogs.com/aslmer/p/5819422.html
(2)DDRAM 与 CGRAM 的区别,根据数据手册知道我们可以定义8个汉字,具体更多知识点请自己百度。
(3)主要的两个指令 Set CGRAM Address 、 Write data to RAM 。
3、在上篇文章的基础上修改代码如下:
难点就在状态机的控制,重点修改部分都用
红色标注
module lcd_1602_driver(
clk ,
rst_n ,
lcd_en ,
lcd_rw ,
lcd_rs ,
lcd_data
);
input clk ;
input rst_n ;
output lcd_en ;
output lcd_rw ;
output lcd_rs ;
output [7:0] lcd_data;
wire clk ;
wire rst_n ;
wire lcd_en ;
wire lcd_rw;
reg [7:0] lcd_data;
reg lcd_rs ;
reg [7:0] c_state ;
reg [7:0] n_state ;
wire [127:0] row_1;
wire write_flag;
//wire [127:0] row_2;
assign row_1 ="i am liu xiao yi" ;
//assign row_2 ="happy everyday !";
//----------------------------------------------------------------------
//initialize
//first step is waitng more than 20 ms.
parameter TIME_20MS = 1000_000 ; //20000000/20=1000_000
//parameter TIME_15MS = 9'h100 ; //just for test
parameter TIME_500HZ= 100_000 ; //
//parameter TIME_500HZ= 4'hf; //just for test
//use gray code 这里本来用的是格雷码,但是由于增添了两个状态,就随机写了f1,f2这两个数字。
parameter IDLE= 8'h00 ;
parameter SET_FUNCTION= 8'h01 ;
parameter DISP_OFF= 8'h03 ;
parameter DISP_CLEAR= 8'h02 ;
parameter ENTRY_MODE= 8'h06 ;
parameter DISP_ON = 8'h07 ;
parameter ROW1_ADDR= 8'h05 ;
//----------------------修改1,增添这两个状态
parameter CGRAM_ADDR = 8'hf1;
parameter CGRAM_DATA = 8'hf2;
//-----------------------
parameter ROW1_0= 8'h04 ;
parameter ROW1_1= 8'h0C ;
parameter ROW1_2= 8'h0D ;
parameter ROW1_3= 8'h0F ;
parameter ROW1_4= 8'h0E ;
parameter ROW1_5= 8'h0A ;
parameter ROW1_6= 8'h0B ;
parameter ROW1_7= 8'h09 ;
parameter ROW1_8= 8'h08 ;
parameter ROW1_9= 8'h18 ;
parameter ROW1_A= 8'h19 ;
parameter ROW1_B= 8'h1B ;
parameter ROW1_C= 8'h1A ;
parameter ROW1_D= 8'h1E ;
parameter ROW1_E= 8'h1F ;
parameter ROW1_F= 8'h1D ;
parameter ROW2_ADDR= 8'h1C ;
parameter ROW2_0= 8'h14 ;
parameter ROW2_1= 8'h15 ;
parameter ROW2_2= 8'h17 ;
parameter ROW2_3= 8'h16 ;
parameter ROW2_4= 8'h12 ;
parameter ROW2_5= 8'h13 ;
parameter ROW2_6= 8'h11 ;
parameter ROW2_7= 8'h10 ;
parameter ROW2_8= 8'h30 ;
parameter ROW2_9= 8'h31 ;
parameter ROW2_A= 8'h33 ;
parameter ROW2_B= 8'h32 ;
parameter ROW2_C= 8'h36 ;
parameter ROW2_D= 8'h37 ;
parameter ROW2_E= 8'h35 ;
parameter ROW2_F= 8'h34 ;
reg [19:0] cnt_20ms ;
always @(posedge clk or negedge rst_n)begin
if(rst_n==1'b0)begin
cnt_20ms<=0;
end
else if(cnt_20ms == TIME_20MS -1)begin
cnt_20ms<=cnt_20ms;
end
else
cnt_20ms<=cnt_20ms + 1 ;
end
wire delay_done = (cnt_20ms==TIME_20MS-1)? 1'b1 : 1'b0 ;
//----------------------------------------------------------------------
//500ns lcd1602工作在500HZ,因此此处要分频
reg [19:0] cnt_500hz;
always @(posedge clk or negedge rst_n)begin
if(rst_n==1'b0)begin
cnt_500hz <= 0;
end
else if(delay_done==1)begin
if(cnt_500hz== TIME_500HZ - 1)
cnt_500hz<=0;
else
cnt_500hz<=cnt_500hz + 1 ;
end
else
cnt_500hz<=0;
end
assign lcd_en = (cnt_500hz>(TIME_500HZ-1)/2)? 1'b0 : 1'b1; //下降沿
as