关于LCD1602的简单显示,大神门指点一下哈
/*以下是一个我从百度里找来的一个LCD1602的程序,我把它下载到我的板子里,发现第一行没显示,第二行是点阵,并没字符显示,这是我的硬件问题还是程序问题?
我是新手,还不明白LCD1602显示字符的原理,看它的资料也不太懂,想从它的显示实现代码里学起,大神们指点一下哈,谢谢哈~~~*/
// LCD_Top.v
//连接Clock_Gen模块和LCD_Driver模块
module LCD_Top(clk_48M,rst,LCD_EN,RS,RW,DB8);
input clk_48M,rst;
output LCD_EN,RS,RW;
output [7:0] DB8;
wire clk_LCD; //用于将Clock_Gen模块clk_LCD输出连接至LCD_Driver模块的clk_LCD输入
Clock_Gen U1(.clk_48M(clk_48M),
.rst(rst),
.clk_LCD(clk_LCD));
LCD_Driver U2(.clk_LCD(clk_LCD),
.rst(rst),
.LCD_EN(LCD_EN),
.RS(RS),
.RW(RW),
.DB8(DB8));
endmodule
// Clock_Gen.v
/****************为LCD_Drvier模块产生500Hz的时钟信号**************/
module Clock_Gen(clk_48M,rst,clk_LCD);
input clk_48M,rst; //rst为全局复位信号(高电平有效)
output clk_LCD;
wire clk_counter;
reg [11:0] cnt; //对时钟进行计数分频
wire clk_equ;
reg [9:0] count;
reg clk_BUF;
parameter counter= 50; //多少分频
/********************************************************************************
** 模块名称:分频器
** 功能描述:通过计数器实现分频功能.
********************************************************************************/
always@(posedge clk_48M)
begin
if(!rst) //低电平复位
cnt <= 12'd0;
else
if(clk_equ)
cnt <= 12'd0;
else
cnt <= cnt+1'b1;
end
assign clk_equ = (cnt==counter);
assign clk_counter = clk_equ;
always @(posedge clk_counter or negedge rst)
begin //利用计数器分频产生500Hz时钟
if(!rst)
begin
clk_BUF <= 1'b0;
count <= 10'b0;
end
else
begin
if(count == 10'd1000)
begin
clk_BUF <= ~clk_BUF;
count <= 10'b0;
end
else
begin
clk_BUF <= clk_BUF; //clk_BUF为500Hz的时钟信号
count <= count + 1'b1;
end
end
end
assign clk_LCD = clk_BUF;
//clk_LCD为LCD_Drvier模块所需要的500Hz的时钟信号
endmodule
// LCD_Driver.v
//功能简述:在1602液晶模块上显示字符串,其中第一行显示“Welcom to hx"
// 在第二行显示“www.mcuhx.com"
//液晶模块为TC1602A,相关特性请参考其数据手册
module LCD_Driver(clk_LCD,rst,LCD_EN,RS,RW,DB8);
input clk_LCD,rst; //rst为全局复位信号(高电平有效)
output LCD_EN,RS,RW;
//LCD_EN为LCD模块的使能信号(下降沿触发)
//RS=0时为写指令;RS=1时为写数据
//RW=0时对LCD模块执行写操作;RW=1时对LCD模块执行读操作
output [7:0] DB8; //8位指令或数据总线
reg [7:0] DB8;
reg [111:0] Data_First_Buf,Data_Second_Buf; //液晶显示的数据缓存
reg RS,LCD_EN_Sel;
reg [3:0] disp_count;
reg [3:0] state;
parameter Clear_Lcd = 4'b0000, //清屏并光标复位
Set_Disp_Mode = 4'b0001, //设置显示模式:8位2行5x7点阵
Disp_On = 4'b0010, //显示器开、光标不显示、光标不允许闪烁
Shift_Down = 4'b0011, //文字不动,光标自动右移
Write_Addr = 4'b0100, //写入显示起始地址
Write_Data_First = 4'b0101, //写入第一行显示的数据
Write_Data_Second = 4'b0110, //写入第二行显示的数据
Idel = 4'b0111; //空闲状态
parameter Data_First = "welcome to hx", //液晶显示的第一行的数据
Data_Second = "www.mcuhx.com"; //液晶显示的第二行的数据
assign RW = 1'b0; //RW=0时对LCD模块执行写操作
assign LCD_EN = LCD_EN_Sel ? clk_LCD : 1'b0;
//通过LCD_EN_Sel信号来控制LCD_EN的开启与关闭
always @(posedge clk_LCD or negedge rst)
begin
if(!rst)
begin
state <= Clear_Lcd; //复位:清屏并光标复位
RS <= 1'b0; //复位:RS=0时为写指令;
DB8 <= 8'b0; //复位:使DB8总线输出全0
LCD_EN_Sel <= 1'b1; //复位:开启夜晶使能信号
//Data_First_Buf <= Data_First;
//Data_Second_Buf <= Data_Second;
disp_count <= 4'b0;
end
else
case(state) //初始化LCD模块
Clear_Lcd:
begin
state <= Set_Disp_Mode;
DB8 <= 8'b00000001; //清屏并光标复位
end
Set_Disp_Mode:
begin
state <= Disp_On;
DB8 <= 8'b00111000; //设置显示模式:8位2行5x8点阵
end
Disp_On:
begin
state <= Shift_Down;
DB8 <= 8'b00001100; //显示器开、光标不显示、光标不允许闪烁
end
Shift_Down:
begin
state <= Write_Addr;
DB8 <= 8'b00000110; //文字不动,光标自动右移
end
Write_Addr:
begin
state <= Write_Data_First;
DB8 <= 8'b10000001; //写入第一行显示起始地址:第一行第二个位置
Data_First_Buf <= Data_First; //将第一行显示的数据赋给Data_First_Buf?
end
Write_Data_First: //写第一行数据
begin
if(disp_count == 14) //disp_count等于14时表示第一行数据已写完
begin
DB8 <= 8'b11000001; //送入写第二行的指令
RS <= 1'b0;
disp_count <= 4'b0;
Data_Second_Buf <= Data_Second;
state <= Write_Data_Second; //写完第一行进入写第二行状态
end
else
begin
DB8 <= Data_First_Buf[111:104];
Data_First_Buf <= (Data_First_Buf << 8);
RS <= 1'b1; //RS=1表示写数据
disp_count <= disp_count + 1'b1;
state <= Write_Data_First;
end
end
Write_Data_Second: //写第二行数据
begin
if(disp_count == 14)
begin
LCD_EN_Sel <= 1'b0;
RS <= 1'b0;
disp_count <= 4'b0;
state <= Idel; //写完进入空闲状态
end
else
begin
DB8 <= Data_Second_Buf[111:104];
Data_Second_Buf <= (Data_Second_Buf << 8);
RS <= 1'b1;
disp_count <= disp_count + 1'b1;
state <= Write_Data_Second;
end
end
Idel:
begin
state <= Idel; //在Idel状态循环
end
default: state <= Clear_Lcd; //若state为其他值,则将state置为Clear_Lcd
endcase
end
endmodule
前排卖瓜子
你理解了程序再说吧,这样会很乱的
你把问题缩小点啊,这样看着好累。
不错
你的这个是什么硬件,FPGA?
一般单片机的话没有这么复杂,我做的仿真可以,硬件就不行了
跟我的问题差不多,不过我是用VHDL写的
建议楼至先看懂程序,再一点一点调试