查看: 1364|回复: 0

​【MAXII_EPM240T100_CPLD】实验七 LCD1602显示屏驱动

[复制链接]
  • TA的每日心情
    开心
    2019-11-19 11:07
  • 签到天数: 226 天

    连续签到: 1 天

    [LV.7]常住居民III

    发表于 2017-2-15 09:03:10 | 显示全部楼层 |阅读模式
    分享到:
    【MAXII_EPM240T100_CPLD】实验七 LCD1602显示屏驱动
    有实验六的基础,已知道板载连接LCD1602或LCD128X64显示屏的插座,就可以开展LCD屏的驱显。经过几番实验,最好总算成功了。看来这个芯片的资源有限,想制作一个稍大点的东西,内部的cels就不够了,最后折中显示固定码为好。因为1602 自带ASCII码,不需要自己编点阵码,这样就简单了一点。
    创建项目,名称为lcd162。过程免了,代码如下。
    module lcd162(clk,rst,LCD_E,LCD_RW,LCD_RS,LCD_D);
    input clk,rst;
    output LCD_E,LCD_RW,LCD_RS;
    output [7:0]LCD_D;
    reg LCD_E,LCD_RW,LCD_RS;
    reg [7:0]LCD_D;
    reg [9:0]state;
    reg [5:0]address;
    parameter IDLE=10'b0000000000;
    parameter CLEAR=10'b0000000001;//清屏
    parameter RETURNCURSOR=10'b0000000010;//归home位
    parameter SETMODE=10'b0000000111;//输入方式设置
    parameter SWITCHMODE=10'b0000001111;//显示状态设置
    parameter SHIFT=10'b0000011100;//光标画面滚动
    parameter SETFUNCTION=10'b0000111100;//工作方式设置1:8/0:4位数据接口
    parameter SETCGRAM=10'b0001000000;//设置CGRA
    parameter SETDDRAM1=10'b0010000001;//设置DDRAM
    parameter SETDDRAM2=10'b0010000010;//设置DDRAM
    parameter READFLAG=10'b0100000000;//读状态
    parameter WRITERAM1=10'b1000000001;//写RAM
    parameter WRITERAM2=10'b1000000010;//写RAM
    parameter READRAM=10'b1100000000;//读RAM
    parameter cur_inc      =1;
    parameter cur_dec      =0;
    parameter cur_shift    =1;
    parameter cur_noshift  =0;
    parameter open_display =1;
    parameter open_cur     =0;
    parameter blank_cur    =0;
    parameter shift_display=1;
    parameter shift_cur    =0;
    parameter right_shift  =1;
    parameter left_shift   =0;
    parameter LCD_Dwidth8  =1;
    parameter LCD_Dwidth4  =0;
    parameter twoline      =1;
    parameter oneline      =0;
    parameter font5x10     =1;
    parameter font5x7      =0;
    //
    function [7:0] ddram;//写入ASCII字符数据
    input [5:0] n;
    begin
    case(n)
      0:ddram=8'h57;//W
      1:ddram=8'h65;//e
      2:ddram=8'h6c;//l
      3:ddram=8'h63;//c
      4:ddram=8'h6f;//o
      5:ddram=8'h6d;//m
      6:ddram=8'h65;//e
      7:ddram=8'hA0;//space
      8:ddram=8'h74;//t
      9:ddram=8'h6f;//o
      10:ddram=8'hA0;//space
      11:ddram=8'h6d;//m
      12:ddram=8'h79;//y
      13:ddram=8'h77;//w
      14:ddram=8'h79;//y
      15:ddram=8'h64;//d
      16:ddram=8'hA0;//space
      17:ddram=8'h77;//w
      18:ddram=8'h77;//w
      19:ddram=8'h77;//w
      20:ddram=8'h2E;//.
      21:ddram=8'h7A;//z
      22:ddram=8'h68;//h
      23:ddram=8'h6A;//j
      24:ddram=8'h62;//b
      25:ddram=8'h2E;//.
      26:ddram=8'h6E;//n
      27:ddram=8'h65;//e
      28:ddram=8'h74;//t
      29:ddram=8'h21;//!
      30:ddram=8'hA0;//space
      31:ddram=8'hA0;//space
      default:ddram=8'hxx;
    endcase
    end
    endfunction
    //分频模块
    reg [16:0] clkcnt;
    reg clkdiv;
    always @ (posedge clk)
    if(!rst)
      clkcnt<=17'b0_0000_0000_0000_0000;
    else
    begin
      if(clkcnt<17'b0_1001_1100_0100_0000) //17'b0_1001_1100_0100_0000
       begin
        clkcnt<=clkcnt+1;
        clkdiv<=0;
       end
      else if(clkcnt==17'b1_1000_0110_1010_0000)//17'b1_0011_1000_0111_1111
       clkcnt<=17'b0_0000_0000_0000_0000;
      else
       begin
        clkcnt<=clkcnt+1;
        clkdiv<=1;
       end
      end
    reg clk_int;
    //原为clkdiv
    always @ (posedge clkdiv or negedge rst)
    if(!rst)
    clk_int<=0;
    else
    clk_int<=~clk_int;
    //显示允许
    always @ (negedge clkdiv or negedge rst) // T 为clkdiv的2倍,100000个clk: 500Hz,2ms
    if(!rst)
    LCD_E<=0;
    else
    LCD_E<=~LCD_E;
    //LCD初始化和显示,由状态机控制->state
    always @ (posedge clk_int or negedge rst)
    if(!rst)
    begin
      state<=IDLE;
      address<=6'b000000;
      LCD_D<=8'b00000000;
      LCD_RS<=0;
      LCD_RW<=0;
    end
    else
    begin
      case(state)
       IDLE:
       begin
        LCD_D<=8'bzzzz_zzzz;
        state<=CLEAR;
       end
       CLEAR:
       begin
        LCD_RS<=0;
        LCD_RW<=0;
        LCD_D<=8'b0000_0001;//清屏01
        state<=SETFUNCTION;
       end
       SETFUNCTION:
       begin
        LCD_RS<=0;
        LCD_RW<=0;
        LCD_D[7:5]<=3'b001;//功能设置3C
        LCD_D[4]<=LCD_Dwidth8;
        LCD_D[3]<=twoline;
        LCD_D[2]<=font5x10;
        LCD_D[1:0]<=2'b00;
        state<=SWITCHMODE;
       end
       SWITCHMODE:
       begin
        LCD_RS<=0;
        LCD_RW<=0;
        LCD_D[7:3]<=5'b00001;//显示状态开关设置0C
        LCD_D[2]<=open_display;
        LCD_D[1]<=open_cur;
    LCD_D[0]<=blank_cur;
    state<=SETMODE;end
    SETMODE:
       begin
        LCD_RS<=0;
        LCD_RW<=0;
        LCD_D[7:2]<=6'b000001;//输入方式设置06
        LCD_D[1]<=cur_inc;
        LCD_D[0]<=cur_noshift;
        state<=SHIFT;
       end
       SHIFT:
       begin
        LCD_RS<=0;
        LCD_RW<=0;
        LCD_D[7:4]<=4'b0001;//光标画面滚动
        LCD_D[3]<=shift_cur;
        LCD_D[2]<=left_shift;
        LCD_D[1:0]<=2'b00;
        state<=SETDDRAM1;
       end
       SETDDRAM1:
       begin
        LCD_RS<=0;
        LCD_RW<=0;
        LCD_D<=8'b10000000;//显示数据存储器地址80
        state<=WRITERAM1;
       end
       SETDDRAM2:
       begin
        LCD_RS<=0;
        LCD_RW<=0;
        LCD_D<=8'b11000000;//显示数据存储器地址80+40
        state<=WRITERAM2;
       end
       WRITERAM1:
       begin//写第一行数据
        if(address<=15)
        begin
         LCD_RS<=1;
         LCD_RW<=0;
         LCD_D<=ddram(address);
         address<=address+1;
         state<=WRITERAM1;
        end
        else
        begin
         LCD_RS<=0;
         LCD_RW<=0;
         state<=SETDDRAM2;
        end
       end
       WRITERAM2:
        begin//写第二行数据
        if(address<=31)
         begin
          LCD_RS<=1;
          LCD_RW<=0;
          LCD_D<=ddram(address);
          address<=address+1;
          state<=WRITERAM2;
         end
        else
         begin
          LCD_RS<=0;
          LCD_RW<=0;
          state<=SHIFT;
          address<=6'b000000;
         end
       end
      endcase
    end
    endmodule
    管脚绑定见图71,

    管脚绑定,一共8Data+3控制+2系统时钟和复位
    运行结果见照片72。

    实际显示结果,还是不错的。
    至此整个实验经历了从去年申请实验样板得到之后,前后翻阅资料、网上学习、看书直到节后初有眉目开始找到压箱底的DIY的板子,开始在Quartus II上倒腾了一番,尽管只是初级实验,但对CPLD-FPGA初入门的来说,是很不容易的一件事,因为与单片机、ARM芯片相比,两者完全不一样。实验暂告一段落,休整一下再继续。谢谢看过和关心过的所有网友。许多代码都是照搬的,因为她的语法现象只能说还是门外汉,但以后会从简单的开始逐步向较难的进军的。FPGA,我已经喜欢上了你!
    回复

    使用道具 举报

    您需要登录后才可以回帖 注册/登录

    本版积分规则

    关闭

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

    手机版|小黑屋|与非网

    GMT+8, 2024-4-29 15:39 , Processed in 0.131250 second(s), 18 queries , MemCache On.

    ICP经营许可证 苏B2-20140176  苏ICP备14012660号-2   苏州灵动帧格网络科技有限公司 版权所有.

    苏公网安备 32059002001037号

    Powered by Discuz! X3.4

    Copyright © 2001-2024, Tencent Cloud.