求助各位高手,这是我写的Verilog 1602液晶驱动,显示时有问题??
module disp1602(clk,en,rs,rw,lcd_data,rst);input clk,rst; //20MHz输入时钟
output en,rs,rw; //使能信号,数据/指令选择端(H/L),读写选择端
output lcd_data;
reg lcd_clk; //1602时钟信号 500Hz
reg c0; //将 clk(20MHz) 分频到 500Hz: 2ms
reg state;//定义 状态
reg lcd_data;
reg data_first_buf,data_second_buf; //液晶显示的数据缓存
regrs,lcd_en_sel;
reg disp_count;
/******* 定义各状态名及编码******/
parameter Clear_Lcd = 4'b0000, //清屏和光标恢复
Set_Disp_Mode = 4'b0001, //设置显示模式:8位2行5x7点阵
Disp_On = 4'b0010, //显示器开、光标不显示、光标不允许闪烁
Auto_ad_address = 4'b0011,
Write_Addr = 4'b0100, //写入显示起始地址
Write_Data_First= 4'b0101, //写入第一行显示的数据
Write_Data_Second = 4'b0110, //写入第二行显示的数据
SJMP= 4'B0111; //原地跳转
parameter Data_First =" good good study ",//液晶显示的第一行的数据
Data_Second = "day dayup"; //液晶显示的第二行的数据
/***********************************/
assign rw=1'b0; //选择 写 选通
assign en=lcd_en_sel?lcd_clk:1'b0;//通过lcd_en_sel来控制 en 的选通
/***********状态机变化部分 ********/
/* 1602液晶功能设置,数据写入 */
/**************************************/
always @(posedge lcd_clk or negedge rst)
begin
if(!rst)
begin
state<=Clear_Lcd;
lcd_data<=8'b0000_0000;
rs <=1'b0;
lcd_en_sel<=1;
disp_count<=4'b0000;
end
else
case(state)
Clear_Lcd:
begin
state<=Set_Disp_Mode;
lcd_data=8'b0000_0001; //清屏指令
end
Set_Disp_Mode:
begin
state<=Disp_On;
lcd_data=8'b0011_1000;//1602显示设置
end
Disp_On:
begin
state<=Auto_ad_address;
lcd_data=8'b0000_1110;//开 显示和光标
end
Auto_ad_address:
begin
state<=Write_Addr;
lcd_data=8'b0000_0110;//写1个字符,地址指针和光标都加 1
end
Write_Addr:
begin
state<=Write_Data_First;
lcd_data=8'b1000_0000;//设置数据指针的首地址
data_first_buf<=Data_First;//将第一行14个字符(112位)赋给 data_first_buf
// data_second_buf=Data_Second;//将第二行14个字符(112位)赋给 data_second_buf
end
Write_Data_First:
begin
if(disp_count==16)
begin
rs=0;
lcd_data=8'b1100_0000;
disp_count=0;
data_second_buf<=Data_Second;//将第二行14个字符(112位)赋给 data_second_buf
state<=Write_Data_Second;
end
else
begin
rs=1;
lcd_data=data_first_buf;
data_first_buf=(data_first_buf<<8);
disp_count=disp_count+1;
state<=Write_Data_First;
end
end
Write_Data_Second:
begin
if(disp_count<16)
begin
rs=1;
lcd_data=data_second_buf;
data_second_buf=(data_second_buf<<8);
disp_count=disp_count+1;
state<=Write_Data_Second;
end
else state=SJMP;
end
SJMP:
state<=SJMP;
default:state<=SJMP;
endcase
end
/****clk分频为 500Hz****/
always @(posedge clk)
if(c0<25000)
c0=c0+1;
else
begin
c0=0;lcd_clk=~lcd_clk;
end
endmodule 显示时只是闪一下就没了,复位按一下,字符再闪一下,这是什么原因?? 没有板子在手上,想用你的程序调一下也不行。。 回复 3# weibode01
谢谢 /***********状态机变化部分 ********/
/* 1602液晶功能设置,数据写入 */
/**************************************/
always @(posedge lcd_clk or negedge rst)
begin
if(!rst)
begin
state<=Clear_Lcd;
lcd_data<=8'b0000_0000;
rs <=1'b0;
lcd_en_sel<=1;
disp_count<=4'b0000;
end
else
case(state)
Clear_Lcd:
begin
state<=Set_Disp_Mode;
lcd_data=8'b0000_0001; //清屏指令
end
Set_Disp_Mode:
begin
state<=Disp_On;
lcd_data=8'b0011_1000;//1602显示设置
end
Disp_On:
begin
state<=Auto_ad_address;
lcd_data=8'b0000_1110;//开 显示和光标
end
Auto_ad_address:
begin
state<=Write_Addr;
lcd_data=8'b0000_0110;//写1个字符,地址指针和光标都加 1
end
Write_Addr:
begin
state<=Write_Data_First;
lcd_data=8'b1000_0000;//设置数据指针的首地址
data_first_buf<=Data_First;//将第一行14个字符(112位)赋给 data_first_buf
// data_second_buf=Data_Second;//将第二行14个字符(112位)赋给 data_second_buf
end
Write_Data_First:
begin
if(disp_count==16)
begin
rs=0;
lcd_data=8'b1100_0000;
disp_count=0;
data_second_buf<=Data_Second;//将第二行14个字符(112位)赋给 data_second_buf
state<=Write_Data_Second;
end
else
begin
rs=1;
lcd_data=data_first_buf;
data_first_buf=(data_first_buf<<8);
disp_count=disp_count+1;
state<=Write_Data_First;
end
end
Write_Data_Second:
begin
if(disp_count<16)
begin
rs=1;
lcd_data=data_second_buf;
data_second_buf=(data_second_buf<<8);
disp_count=disp_count+1;
state<=Write_Data_Second;
end
else begin disp_count=0;state=Write_Data_First;end
end
// SJMP:
// state<=SJMP;
// default:state<=SJMP;
endcase
end
我在写字符这里改了一下,不让他原地跳转,而是让他不断地写入字符,这样显示就正常了。
但我还是很想知道,为什么原来的代码不行,问题出在哪? 哈哈,我也想用板子去控制1602,可是都没钱买。。。穷孩子啊 加油!!! 学习!!!!!!!!!!! 为什么我把你的程序下到我板子上 用你改过的程序还是屏幕闪一下呢???
页:
[1]