集成电路技术分享

 找回密码
 我要注册

QQ登录

只需一步,快速开始

搜索
查看: 4008|回复: 8

求助各位高手,这是我写的Verilog 1602液晶驱动,显示时有问题??

[复制链接]
yyh1910 发表于 2010-11-8 13:02:05 | 显示全部楼层 |阅读模式
module disp1602(clk,en,rs,rw,lcd_data,rst);
  input clk,rst;       //20MHz输入时钟
  output en,rs,rw;    //使能信号,数据/指令选择端(H/L),读写选择端
  output [7:0] lcd_data;
  
  reg lcd_clk;      //1602时钟信号 500Hz
  reg [14:0] c0;    //将 clk(20MHz) 分频到 500Hz: 2ms  
  reg [3:0] state;//定义 状态

  reg  [7:0] lcd_data;
  reg  [127:0] data_first_buf,data_second_buf;     //液晶显示的数据缓存
  reg  rs,lcd_en_sel;
  reg  [4:0] 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   day  up  "; //液晶显示的第二行的数据  
/***********************************/


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[127:120];
                 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[127:120];
                 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
 楼主| yyh1910 发表于 2010-11-8 13:02:33 | 显示全部楼层
显示时只是闪一下就没了,复位按一下,字符再闪一下,这是什么原因??
weibode01 发表于 2010-11-8 13:06:15 | 显示全部楼层
没有板子在手上,想用你的程序调一下也不行。。
 楼主| yyh1910 发表于 2010-11-8 15:16:08 | 显示全部楼层
回复 3# weibode01


    谢谢
 楼主| yyh1910 发表于 2010-11-8 17:00:03 | 显示全部楼层
/***********  状态机变化部分   ********/
/*    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[127:120];
                 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[127:120];
                 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   



我在写字符这里改了一下,不让他原地跳转,而是让他不断地写入字符,这样显示就正常了。
但我还是很想知道,为什么原来的代码不行,问题出在哪?
weibode01 发表于 2010-11-14 09:31:46 | 显示全部楼层
哈哈,我也想用板子去控制1602,可是都没钱买。。。穷孩子啊
驾神马看浮云 发表于 2011-2-4 20:45:21 | 显示全部楼层
加油!!!
FPGA_aihaozhe 发表于 2011-2-5 02:28:42 | 显示全部楼层
学习!!!!!!!!!!!
fsouth 发表于 2014-3-26 13:07:39 | 显示全部楼层
为什么我把你的程序下到我板子上   用你改过的程序  还是屏幕闪一下呢???
您需要登录后才可以回帖 登录 | 我要注册

本版积分规则

关闭

站长推荐上一条 /1 下一条

QQ|小黑屋|手机版|Archiver|fpga论坛|fpga设计论坛 ( 京ICP备20003123号-1 )

GMT+8, 2025-5-8 03:30 , Processed in 0.070188 second(s), 23 queries .

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表