LCD1602液晶 - 天盘

tphust 2021-08-08 原文


LCD1602液晶

     这两天都在学习怎样用verilog语言写LCD1602液晶的程序,其实,我对1602液晶还是蛮熟悉的,毕竟,在学单片机的时候,也用C51写过它的驱动程序,还是蛮简单的,但是由于FPGA是并行的,所以,写的驱动程序和单片机的不太一样,今天有幸在网上看到了Crazy Bingo用状态机写的1602液晶的驱动程序,突然觉得verilog语言中的状态机这么强大,竟然能像这样用状态机来写LCD1602液晶的驱动程序;自己写的代码太烂,没敢贴出来,所以,参考了他写的代码,然后修改了一下!

//程序实现的功能:在LCD1602液晶上显示字符;
module lcd_1602
        (
          sysclk,
          rst_n,
          lcd_en,
          lcd_rs,
          lcd_rw,
          lcd_data
           
        );

input   sysclk;         //系统时钟 50MHZ
input   rst_n;          //复位信号,低电平有效;

output       lcd_en;    //读写使能信号,高电平有效;
output       lcd_rs;    //数据命令选择端(H/L);
output       lcd_rw;    //读写选择端(H/L);
output[7:0]  lcd_data;  //8位数据口;

wire        sysclk;
wire        rst_n;
wire        lcd_en;
reg         lcd_rs;
wire        lcd_rw;
reg[7:0]    lcd_data;
  
parameter  [127:0]row1="hello     world!";      //因为lcd1602每一行可显示16个字符,一个字符占8位;
parameter  [127:0]row2="I   like   FPGA!";      //所以每一行一共有16*8=128位;

reg [15:0]   time_cnt;
always @(posedge sysclk or negedge rst_n) 
 begin
       if(!rst_n)
          time_cnt<=16\'h0;
       else 
          time_cnt<=time_cnt+16\'b1;  
 end  

assign  lcd_rw=1\'b0;
assign  lcd_en=time_cnt[15]; 

wire  state_flag ;     //状态标志位 ,因为FPGA的运算速度比LCD1602要快的多,  
                      //所以必须要等到LCD1602稳定后才往里面写数据;
assign  state_flag=(time_cnt==16\'h7fff)?1\'b1:1\'b0 ;    //lcd_en最小值500ns ,所以lcd_en的频率应维持在2MHZ以内; 

parameter  IDLE=8\'h00;
//lcd1602 initial;
parameter  INI_SET=8\'h01;      //显示工作模式设置;
    
parameter  INI_CLR=8\'h02;      //清屏显示;

parameter  CURSOR_SET1=8\'h03;  // 光标设置1;

parameter  CURSOR_SET2=8\'h04;  //光标设置2;     
//display line 1;
parameter  LINE1_ADDER=8\'h05;

parameter  LINE1_0=8\'h06;

parameter  LINE1_1=8\'h07;

parameter  LINE1_2=8\'h08;

parameter  LINE1_3=8\'h09;

parameter  LINE1_4=8\'h0A;

parameter  LINE1_5=8\'h0B;

parameter  LINE1_6=8\'h0C;

parameter  LINE1_7=8\'h0D;

parameter  LINE1_8=8\'h0E;

parameter  LINE1_9=8\'h0F;

parameter  LINE1_A=8\'h10;

parameter  LINE1_B=8\'h11;

parameter  LINE1_C=8\'h12;

parameter  LINE1_D=8\'h13;

parameter  LINE1_E=8\'h14;

parameter  LINE1_F=8\'h15;
// display line 2;
parameter  LINE2_ADDER=8\'h16;

parameter  LINE2_0=8\'h17;

parameter  LINE2_1=8\'h18;

parameter  LINE2_2=8\'h19;

parameter  LINE2_3=8\'h1A;

parameter  LINE2_4=8\'h1B;

parameter  LINE2_5=8\'h1C;

parameter  LINE2_6=8\'h1D;

parameter  LINE2_7=8\'h1E;

parameter  LINE2_8=8\'h1F;

parameter  LINE2_9=8\'h20;

parameter  LINE2_A=8\'h21;

parameter  LINE2_B=8\'h22;

parameter  LINE2_C=8\'h23;

parameter  LINE2_D=8\'h24;

parameter  LINE2_E=8\'h25;

parameter  LINE2_F=8\'h26;
//------------------------------------------------//
reg[7:0] state;
reg[7:0] next_state;
always @ (posedge sysclk or negedge rst_n)
  begin
        if(!rst_n)
          state<=IDLE;
        else if(state_flag)
          state<=next_state;  
  end   
     
always @ (*)
  begin
       case(state)
         //display line1;
         IDLE        :   next_state=INI_SET;
         
         INI_SET     :   next_state=INI_CLR;
         
         INI_CLR     :   next_state=CURSOR_SET1;
         
         CURSOR_SET1 :   next_state=CURSOR_SET2;
         
         CURSOR_SET2 :   next_state=LINE1_ADDER;
         
         LINE1_ADDER :   next_state=LINE1_0;
         
         LINE1_0     :   next_state=LINE1_1;
         
         LINE1_1     :   next_state=LINE1_2;
         
         LINE1_2     :   next_state=LINE1_3;
         
         LINE1_3     :   next_state=LINE1_4;
         
         LINE1_4     :   next_state=LINE1_5; 
         
         LINE1_5     :   next_state=LINE1_6;
         
         LINE1_6     :   next_state=LINE1_7;
         
         LINE1_7     :   next_state=LINE1_8;
         
         LINE1_8     :   next_state=LINE1_9;
         
         LINE1_9     :   next_state=LINE1_A;
         
         LINE1_A     :   next_state=LINE1_B; 
         
         LINE1_B     :   next_state=LINE1_C;
         
         LINE1_C     :   next_state=LINE1_D;
         
         LINE1_D     :   next_state=LINE1_E;
         
         LINE1_E     :   next_state=LINE1_F; 
         
         LINE1_F     :   next_state=LINE2_ADDER; 
         //display line2;
         LINE2_ADDER :   next_state=LINE2_0;
         
         LINE2_0     :   next_state=LINE2_1;
         
         LINE2_1     :   next_state=LINE2_2;
         
         LINE2_2     :   next_state=LINE2_3;
         
         LINE2_3     :   next_state=LINE2_4;
         
         LINE2_4     :   next_state=LINE2_5; 
         
         LINE2_5     :   next_state=LINE2_6;
         
         LINE2_6     :   next_state=LINE2_7;
         
         LINE2_7     :   next_state=LINE2_8;
         
         LINE2_8     :   next_state=LINE2_9;
         
         LINE2_9     :   next_state=LINE2_A;
         
         LINE2_A     :   next_state=LINE2_B;
          
         LINE2_B     :   next_state=LINE2_C;
         
         LINE2_C     :   next_state=LINE2_D;
         
         LINE2_D     :   next_state=LINE2_E;
         
         LINE2_E     :   next_state=LINE2_F; 
         
         LINE2_F     :   next_state=LINE1_ADDER;
         
         default     :   next_state=IDLE; 
       endcase 
  end  

always @ (posedge sysclk or negedge rst_n)   
  begin
        if(!rst_n)
          begin 
           lcd_rs<=1\'h0;
           lcd_data<=8\'hxx;
          end 
        else if(state_flag)
          begin
            case (next_state)
               IDLE        :   lcd_rs<=1\'h0;
               
               INI_SET     :   lcd_rs<=1\'h0;
                              
               INI_CLR     :   lcd_rs<=1\'h0;
               
               CURSOR_SET1 :   lcd_rs<=1\'h0;
               
               CURSOR_SET2 :   lcd_rs<=1\'h0;
        //     line1       
               LINE1_ADDER :   lcd_rs<=1\'h0; 
               
               LINE1_0     :   lcd_rs<=1\'h1;
               
               LINE1_1     :   lcd_rs<=1\'h1;
               
               LINE1_2     :   lcd_rs<=1\'h1; 
               
               LINE1_3     :   lcd_rs<=1\'h1;
               
               LINE1_4     :   lcd_rs<=1\'h1;
               
               LINE1_5     :   lcd_rs<=1\'h1;
               
               LINE1_6     :   lcd_rs<=1\'h1; 
               
               LINE1_7     :   lcd_rs<=1\'h1;
               
               LINE1_8     :   lcd_rs<=1\'h1;
               
               LINE1_9     :   lcd_rs<=1\'h1;
               
               LINE1_A     :   lcd_rs<=1\'h1; 
               
               LINE1_B     :   lcd_rs<=1\'h1;
               
               LINE1_C     :   lcd_rs<=1\'h1;
               
               LINE1_D     :   lcd_rs<=1\'h1;
               
               LINE1_E     :   lcd_rs<=1\'h1; 
               
               LINE1_F     :   lcd_rs<=1\'h1;
        //     line2 
               LINE2_ADDER :   lcd_rs<=1\'h0; 
               
               LINE2_0     :   lcd_rs<=1\'h1;
               
               LINE2_1     :   lcd_rs<=1\'h1;
               
               LINE2_2     :   lcd_rs<=1\'h1; 
               
               LINE2_3     :   lcd_rs<=1\'h1;
               
               LINE2_4     :   lcd_rs<=1\'h1;
               
               LINE2_5     :   lcd_rs<=1\'h1;
               
               LINE2_6     :   lcd_rs<=1\'h1; 
               
               LINE2_7     :   lcd_rs<=1\'h1;
               
               LINE2_8     :   lcd_rs<=1\'h1;
               
               LINE2_9     :   lcd_rs<=1\'h1;
               
               LINE2_A     :   lcd_rs<=1\'h1; 
               
               LINE2_B     :   lcd_rs<=1\'h1;
               
               LINE2_C     :   lcd_rs<=1\'h1;
               
               LINE2_D     :   lcd_rs<=1\'h1;
               
               LINE2_E     :   lcd_rs<=1\'h1; 
               
               LINE2_F     :   lcd_rs<=1\'h1;     
             endcase 
             
             
             case(next_state) 
                IDLE        :  lcd_data<=8\'hxx;
                
                INI_SET     :  lcd_data<=8\'h38;   //设置16*2显示,5*7点阵,8位数据接口;
                
                INI_CLR     :  lcd_data<=8\'h01;   //清屏显示;
                
                CURSOR_SET1 :  lcd_data<=8\'h06;   //写一个字符后地址指针加一; 
                   
                CURSOR_SET2 :  lcd_data<=8\'h0c;   //设置开显示,不显示光标;
               //line1 
                LINE1_ADDER :  lcd_data<=8\'h80;   //LCD1602第一行 首地址; 
                
                LINE1_0     :  lcd_data<=row1[127:120];
                
                LINE1_1     :  lcd_data<=row1[119:112];
                
                LINE1_2     :  lcd_data<=row1[111:104];
                
                LINE1_3     :  lcd_data<=row1[103:96];  
                
                LINE1_4     :  lcd_data<=row1[95:88];
                
                LINE1_5     :  lcd_data<=row1[87:80];
                
                LINE1_6     :  lcd_data<=row1[79:72];
                
                LINE1_7     :  lcd_data<=row1[71:64]; 
                 
                LINE1_8     :  lcd_data<=row1[63:56];
                
                LINE1_9     :  lcd_data<=row1[55:48];
                
                LINE1_A     :  lcd_data<=row1[47:40];
                
                LINE1_B     :  lcd_data<=row1[39:32];  
                
                LINE1_C     :  lcd_data<=row1[31:24];
                
                LINE1_D     :  lcd_data<=row1[23:16];
                
                LINE1_E     :  lcd_data<=row1[15:8];
                
                LINE1_F     :  lcd_data<=row1[7:0];  
              //line2
                LINE2_ADDER :  lcd_data<=8\'hC0;   //LCD1602第二行首地址(8\'h80+8\'h40=8\'hC0)
                
                LINE2_0     :  lcd_data<=row2[127:120];
                
                LINE2_1     :  lcd_data<=row2[119:112];
                
                LINE2_2     :  lcd_data<=row2[111:104];
                
                LINE2_3     :  lcd_data<=row2[103:96];  
                
                LINE2_4     :  lcd_data<=row2[95:88];
                
                LINE2_5     :  lcd_data<=row2[87:80];
                
                LINE2_6     :  lcd_data<=row2[79:72];
                
                LINE2_7     :  lcd_data<=row2[71:64];  
                
                LINE2_8     :  lcd_data<=row2[63:56];
                
                LINE2_9     :  lcd_data<=row2[55:48];
                
                LINE2_A     :  lcd_data<=row2[47:40];
                
                LINE2_B     :  lcd_data<=row2[39:32];  
                
                LINE2_C     :  lcd_data<=row2[31:24];
                
                LINE2_D     :  lcd_data<=row2[23:16];
                
                LINE2_E     :  lcd_data<=row2[15:8];
                
                LINE2_F     :  lcd_data<=row2[7:0];
                
               endcase     
                   
                
          end    
             
  end 
 endmodule 

 

 

发表于
2012-07-08 17:03 
天盘 
阅读(327
评论(1
编辑 
收藏 
举报

 

版权声明:本文为tphust原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/tphust/archive/2012/07/08/2581664.html

LCD1602液晶 - 天盘的更多相关文章

  1. 如何在论文中画出漂亮的插图? – GarfieldEr007

    如何在论文中画出漂亮的插图? 2016-04-13 21:05  GarfieldEr007  阅读(5396 […]...

  2. 微信开放平台开发(2) 网站应用微信登录 – 大西瓜3721

    微信开放平台开发(2) 网站应用微信登录 在这篇微信公众平台开发教程中,我们将介绍如何使用微信开放平台接口实现 […]...

  3. SpringBoot + Spring Security 学习笔记(五)实现短信验证码+登录功能

    在 Spring Security 中基于表单的认证模式,默认就是密码帐号登录认证,那么对于短信验证码+登录的 […]...

  4. (原创)巩固理解基于DS18B20的1-wire协议(MCU,经验) – Booting

    (原创)巩固理解基于DS18B20的1-wire协议(MCU,经验) 1.Abstract     如前篇随笔 […]...

  5. 简单的系统封装过程 – knight1394

    简单的系统封装过程       在工作当中,经常要对不同型号的主机重新安装操作系统,网上下载的装机ghost版 […]...

  6. Protégé术语解释 – 蓝色守望

    Protégé术语解释 3种OWL语言        OWL可以分为三种子语言:OWL-Lite,OWL-DL […]...

  7. jmeter查看结果树_各种方式 – 肥涵

    jmeter查看结果树_各种方式 1、察看结果树之CSS_Selector tester   1-将查看方式修 […]...

  8. javaWeb开发小工具–MyCommonUtils – 小李探花IU

    javaWeb开发小工具–MyCommonUtils MyCommonUtils 参考一些资料,写 […]...

随机推荐

  1. 企业内部控制本质是什么

     企业内部控制本质是什么       如今,内部控制越来越受到企业重视,越来越多的企业在做企业内部控制,有的企 […]...

  2. 常见简体繁体转换

    使用转换js: transform.js : https://blog-static.cnblogs.com/ […]...

  3. 元素绝对定位以后设置了高宽,a标签不能点击的原因总结

    元素绝对定位以后设置了高宽,a标签不能点击的原因: 1、元素内并无内容 2、背景是透明的,无任何背景图或者颜色 […]...

  4. idea导入jdk源码查看(xjl456852原创)

    idea导入jdk源码查看(xjl456852原创) idea添加了jdk环境后,却无法查看jdk源码,只能通 […]...

  5. 阿里架构师带你深入浅出jvm

    本文跟大家聊聊JVM的内部结构,从组件中的多线程处理,JVM系统线程,局部变量数组等方面进行解析   JVM […]...

  6. SpringBoot整合Shiro+MD5+Salt+Redis实现认证和动态权限管理|前后端分离(下)—-筑基后期

    写在前面 在上一篇文章《SpringBoot整合Shiro+MD5+Salt+Redis实现认证和动态权限管理 […]...

  7. FreeAnchor:抛弃单一的IoU匹配,更自由的anchor匹配方法 | NIPS 2019

    论文抛弃以往根据IoU硬性指定anchor和GT匹配关系的方法,提出FreeAnchor方法来进行更自由的匹配 […]...

  8. LSTM算法原理理解

    神经网络   模拟人类大脑神经网络结构,每个神经元和其他的神经元相互连接,当它兴奋的时候会向相连的神经元发送化 […]...

展开目录

目录导航