先上接线图:
VL:对比度,正常接一个1K的电阻就好了,如果电阻过大会出现一个个黑方块,而你要显示的就看不清楚了,反之如果电阻过小,就会根本显示不出东西,亮亮的一片。也可以接1K的电位器实现改对比度的功能。
RS:数据指令选择端: 0 写指令 1 读指令
RW:读写选择端 0 写指令/数据 1 读状态/数据
EN:使能端:下降沿使得指令数据生效
这些都是控制端口,要留心注意他们的接线
D0-D7:这些是数据端口,用来传递数据的。
Bl- 、 Bl+ :这些是背光电源,如果你上电连LCD都不亮就要检查一下这里。
HD44780内置了 DDRAM、CGROM和 CGRAM。
在 LCD模块上也固化
了字模存储器,这就是 CGROM和 CGRAM。HD44780内置了 192个常用字符的字模,
存于字符产生器 CGROM(Character Generator ROM)中,另外还有 8 个允许用户
自定义的字符产生 RAM,称为 CGRAM(Character Generator RAM)。下图说明了
CGROM和 CGRAM与字符的对应关系。
指令集:
信号真值表:
RS | R/W | E | 功能 |
0 | 0 | 下降沿 | 写指令
0 | 1 | 高电平 | 读状态
1 | 0 | 下降沿 | 写数据
1 | 1 | 高电平 | 读数据
简单写一下常用的指令:
显示开关光标设置:0x0f;(打开光标显示闪烁)
清屏设置: 0x01;
功能设置:0x31:;
显示地址设置0x06;
设置流程大概就是先设置好初始配置,然后定义写入地址,送入写的数据
代码如下:
module lcd1602_driver(
clk,
rst_n,
RSel,
R_W,
En,
Lcd_data,
Lcd_Vcc,
Lcd_GND,
Lcd_A,
Lcd_K
);
input clk; //输入时钟
input rst_n;
output reg RSel; //数据指令选择
output R_W; //读写选择
output reg En; //使能
output reg[7:0]Lcd_data; //数据位
output Lcd_Vcc; //lcd 电源开关 +
output Lcd_GND; //lcd 电源开关 -
output Lcd_A; //lcd 背光 +
output Lcd_K; //lcd 背光 -
/*--------------初始化功能设置-------------*/
parameter Mode_Set =8'h31,//显示模式设置
Cursor_Dis_Set =8'h0c,//光标显示设置
Cursor_Move_Set =8'h80,//光标移动设置
Clear_Set =8'h01,//清屏
Init_ADDr_Set =8'h80;//起始位置
/*-------------背光设置--------------------*/
assign Lcd_Vcc=1'b1;//供电
assign Lcd_GND=1'b0;//
assign Lcd_A=1'b1;//背光常开
assign Lcd_K=1'b0;//
assign R_W=1'b0;//只写
/*---------任务列表------------*/
task Write_order;
input [7:0] order;//指令
begin
RSel<=1'b0;
En<=1'b1;
state<=state+1'b1;
Lcd_data<=order;
end
endtask
task En_Negedge;
begin
En<=1'b0;
state<=state+1'b1;
end
endtask
task Write_data;
input [7:0] order_1;//数据
begin
RSel<=1'b1;
En<=1'b1;
state<=state+1'b1;
Lcd_data<=order_1;
end
endtask
/*--------驱动时钟------------*/
wire lcd_clk=(cnt_clk==16'd24999);
reg [15:0]cnt_clk;
always@(posedge clk or negedge rst_n)begin
if(rst_n==1'b0)begin
cnt_clk<=1'b0;
end
else if(cnt_clk==16'd24999)begin//延时500us
cnt_clk<=1'b0;
end
else begin
cnt_clk<=cnt_clk+1'b1;
end
end
/*---------显示状态配置--------*/
reg [4:0] state;
always@(posedge clk or negedge rst_n)begin
if(rst_n==1'b0)begin
RSel<=1'b0;
En<=1'b0;
state<=5'd0;
Lcd_data<=1'b0;
end
else if(lcd_clk==1'b1)begin
case(state)
/*----------------初始化设置---------------------*/
5'd0:begin
Write_order(Mode_Set);
end
5'd1:begin
En_Negedge();
end
5'd2:begin
Write_order(Cursor_Dis_Set);//设置光标显示
end
5'd3:begin
En_Negedge();
end
5'd4:begin
Write_order(Cursor_Move_Set);//设置光标移动
end
5'd5:begin
En_Negedge();
end
5'd6:begin
Write_order(Clear_Set);//清屏
end
5'd7:begin
En_Negedge();
end
/*-----显示区--------*/
5'd8:begin
Write_order(Init_ADDr_Set);//设置写入地址
end
5'd9:begin
En_Negedge();
end
5'd10:begin
Write_data("F");
end
5'd11:begin
En_Negedge();
end
5'd12:begin
Write_data("P");
end
5'd13:begin
En_Negedge();
end
5'd14:begin
Write_data("G");
end
5'd15:begin
En_Negedge();
end
5'd16:begin
Write_data("A");
end
5'd17:begin
En_Negedge();
end
default:state<=5'bxxxx;
endcase
end
else begin
RSel<=RSel;
En<=En;
Lcd_data<=Lcd_data;
end
end
endmodule