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. Davinci 可视化系统部署安装及简单使用 – CurdBoys

    Davinci 可视化系统部署安装及简单使用 介绍目前很热门的可视化系统部署及安装(内有详细的操作演示视频) […]...

  2. ICE集群环境搭建 – blogs_zixin

    ICE集群环境搭建 本文将介绍ice搭建高可用集群环境的详细操作步骤,实现 register 的主从备份、双服 […]...

  3. 编程语言种类以及特点 – 星际海盗

    语言种类 一:汇编语言 脚本语言:  是一种解释型的语言,是为了缩短传统的编写-编译-链接-运行(edit-c […]...

  4. 新手学习FFmpeg – 调用API完成录屏并进行H.264编码

    新手学习FFmpeg – 调用API完成录屏并进行H.264编码 Screen Record H. […]...

  5. Linux常用基础操作命令大全(超实用精心整理) – qxandxt

    Linux常用基础操作命令大全(超实用精心整理) 相信大家都对黑客那种只用命令行对电脑操作的风格惊呆了,其实你 […]...

  6. [转]Node.js框架对比:Express/Koa/Hapi – freeliver54

    [转]Node.js框架对比:Express/Koa/Hapi 本文转自:https://www.cnblog […]...

  7. MyBatis 源码分析 – 插件机制

    1.简介 一般情况下,开源框架都会提供插件或其他形式的拓展点,供开发者自行拓展。这样的好处是显而易见的,一是增 […]...

  8. Microsoft Windows 2000 应用程序兼容性 2 – csdnexpert

    组件检查 我们发现导致无法在 Windows 2000 上安装应用程序的另一个原因是组件检查功能。显然,我们操 […]...

随机推荐

  1. 分布式事物的设计与实践

    分布式事物设计与实践 数据一致性定义 任何人 任何时间 任何地点 任何接入方式 任何服务 数据都是一致的 数据 […]...

  2. Error during the installation of SQL Server 2008 R2

    在windows 2008 r2 en中安装sql server 2008 r2 cn出错 error: Ev […]...

  3. 终极大招完美结合Excel与Python!(零基础就能学)

    ​   Excel和Jupyter Notebok都是我每天必用的工具,而且两个工具经常协同工作,一直以来工作 […]...

  4. 集合的相关信息

    体系结构 单列集合 Collection接口 |-List接口:可以存储重复元素、有索引、存取有序 |-Arr […]...

  5. 分享工作中一次优化程序的过程

      程序应用场景: 年初从总公司交接了一个评分系统,系统大概情况是80w考生,每个考生105条作答数据,作答数 […]...

  6. 梦想篇—-初级:与电子电路相关的基础知识

    404...

  7. 从零搭建一个IdentityServer——项目搭建

      本篇文章是基于ASP.NET CORE 5.0以及IdentityServer4的IdentityServ […]...

  8. 服务器性能都包括哪些指标?

    Apache性能监控支持以下指标: Apache吞吐率 Apache并发连接数 Apache并发连接数详细统计 […]...

展开目录

目录导航