• (原创)详细分析LCD16207的工作原理


      在(原创)uClinux下控制LCD16207等字符设备显示中,我做了关于uClinux下控制LCD16207的实验,里面关于驱动以及LCD16207的最底层知识我没有详细讲,这里呢,我再详细分析一下LCD16207的工作原理。

    一、LCD16207工作原理

    1、DE2下LCD16207规格

    2、管教定义及含义

    3、工作原理

      上面我们可以看到,LCD的显示实质上是MPU控制LCD控制器的一个过程,这里面才用的是HD44780这个控制器,我们配置了这个控制器,就控制了这个LCD。

    4、LCD控制器的一些寄存器

      LCD显示是由一个LSI控制器控制,他包含两个寄存器,命令寄存器(IR)和数据寄存器(DR)。

      IR寄存器存储一些指令代码,包括显示清零、光标移位以及地址信息,这些信息都是为了显示数据RAM(DDRAM)和字符产生RAM(CGRAM)服务。数据寄存器(DR)暂时存放从DDRAM和CGRAM写或者读的数据。当把地址信息写入IR寄存器之后,数据就从DDRAM或者CGRAM存储到DR。

      RS和R/W信号的线不同搭配产生不同的功能,如下图所示:

      

      注:上面写错了,应该是DB0 to DB6

      RS R/W

          1、为00时,表示写入命令道命令寄存器;

      2、为01时,表示读地址信息,这里面低7位表示的是AC counter,最高位表示忙信号;

      3、为10时,表示写数据,将数据从DR到DDRAM或者CGRAM;

      4、为11时,表示读数据,将数据从DDRAM或者CGRAM到DR。

      解释几个术语:

      1、Busy Flag(BF)忙信号

      当RS=0以及R/W=1,忙信号将会输出到DB7上,当忙信号为1时,表示LSI控制器处于忙碌状态,下一个指令将不会接受。所以在输入下一个指令的时候,必须保证忙信号无效。

      2、地址计数器(AC)

      这个地址计数器是为DDRAM和CGRAM计数的。

      3、数据显示存储器(DDRAM)

      数据显示寄存器存储的是要显示的数据。

      下面的图很好解释了地址计数器和DDRAM在LCD中的位置。

      LCD的第一行的地址为00到0F,第二行地址为40到4F,计数器就产生地址,这样就从相应的地址取数据。 

      这里面关于DDRAM和CGRAM一些问题,我还是没有搞清楚,也就是我我只能利用CGROM里面的数据来输出到LCD上,自己并不能创造一些汉字,希望有人指点一下。以后能学会,暂时还没用到这一块。

    5、指令表

      1、清零命令

      写入的命令是0x01,作用是设置DDRAM的内容为00H并设置DDRAM地址为00H。命令执行的时间是1.53ms,时钟270KHZ,下同。

      2、返回到最初的位置

      写入的命令是0x02或者0x03,最后一个位置不关心,作用是将DDRAM地址设为00H,不改变DDRAM的内容,同时复位光标的位置,执行时间为1.53ms。

      3、模式设置

      DB2为1,DB1 I/D表示的是光标移动的方向,DB0表示的是移动显示的使能位。执行时间为39us。

      4、显示开关控制(参数)

      DB2表示的是数据显示的开或关,DB1表示的是光标的开或关,DB0表示的是光标闪烁的开或关。执行时间为39us。

      5、光标和显示移位

      不改变DDRAM的内容。执行时间为39us。

      6、功能设置

      DB4表示的是显示8位模式还是4位模式,DB3表示的是一行还是两行显示,DB2表示的是5*11模式还是5*8模式。执行时间为39us。

      7、设置CGRAM地址

      8、设置DDRAM地址

      9、读忙信号和地址信息

      执行时间为0us。

      10、读/写RAM的数据,包括DDRAM和CGRAM。

    6、读写时序 

      

      

      具体参数其实大家在看verilog语言的时候,是不需要多关心的。下面我们来看一看一个基于AVALON总线的LCD的Verilog控制器代码。说的再多,还不如来看看下面的代码。

    1 module LCD_Controller ( // Avalon总线接口
    2 avs_s1_writedata,
    3 avs_s1_address,
    4 //avs_s1_read,
    5 //avs_s1_readdata,
    6 avs_s1_write,
    7 csi_clockreset_clk,
    8 csi_clockreset_reset_n,
    9 // LCD Interface
    10 avs_s1_export_o_LCD_DATA,
    11 avs_s1_export_o_LCD_RW,
    12 avs_s1_export_o_LCD_EN,
    13 avs_s1_export_o_LCD_RS );
    14 // CLK
    15 parameter CLK_Divide = 200;
    16
    17 // Avalon总线接口
    18 input [7:0] avs_s1_writedata;
    19 //output [7:0] avs_s1_readdata;
    20 input [1:0] avs_s1_address;
    21 input avs_s1_write;
    22 //input avs_s1_read;
    23 input csi_clockreset_clk;
    24 input csi_clockreset_reset_n;
    25
    26 // LCD Interface
    27 inout [7:0] avs_s1_export_o_LCD_DATA;
    28 output avs_s1_export_o_LCD_EN;
    29 output avs_s1_export_o_LCD_RW;
    30 output avs_s1_export_o_LCD_RS;
    31
    32 // Internal Register
    33 //reg oDone;
    34 reg [9:0] Cont;
    35 reg [1:0] ST;
    36 reg oDone;
    37
    38 reg [7:0] mLCD_DATA;
    39 reg mLCD_EN;
    40 reg mLCD_RW;
    41 reg mLCD_RS;
    42
    43 assign avs_s1_export_o_LCD_DATA = mLCD_RW ? 8'hzz : mLCD_DATA;
    44 assign avs_s1_export_o_LCD_RW = mLCD_RW;
    45 assign avs_s1_export_o_LCD_RS = mLCD_RS;
    46 assign avs_s1_export_o_LCD_EN = mLCD_EN;
    47
    48 //state
    49 localparam LCD_INIT_STATE_0_WAIT_POWER_UP = 2'h0,
    50 LCD_INIT_STATE_1_SEND_COMMAND = 2'h1,
    51 LCD_INIT_STATE_2_WAIT_EN = 2'h2,
    52 LCD_INIT_STATE_3_DONE = 2'h3;
    53
    54 always@(posedge csi_clockreset_clk or negedge csi_clockreset_reset_n)
    55 begin
    56 if(!csi_clockreset_reset_n)
    57 begin
    58 mLCD_EN <= 1'b0;
    59 Cont <= 0;
    60 ST <= 0;
    61 end
    62 else
    63 begin
    64 begin
    65 case(ST)
    66 LCD_INIT_STATE_0_WAIT_POWER_UP:
    67 begin
    68 ST <=LCD_INIT_STATE_1_SEND_COMMAND;
    69 end
    70 LCD_INIT_STATE_1_SEND_COMMAND:
    71 begin
    72 if(avs_s1_write==1'b1)
    73 begin
    74 mLCD_DATA<=avs_s1_writedata[7:0];
    75 mLCD_RW<=avs_s1_address[0];
    76 mLCD_RS<=avs_s1_address[1];
    77 mLCD_EN <= 1'b1;
    78 ST <= LCD_INIT_STATE_2_WAIT_EN;
    79 end
    80 end
    81 LCD_INIT_STATE_2_WAIT_EN:
    82 begin
    83 if(Cont<CLK_Divide)
    84 Cont <= Cont+1;
    85 else
    86 ST <= LCD_INIT_STATE_3_DONE;
    87 end
    88 LCD_INIT_STATE_3_DONE:
    89 begin
    90 mLCD_EN <= 1'b0;
    91 Cont <= 0;
    92 ST <= LCD_INIT_STATE_0_WAIT_POWER_UP;
    93 end
    94 endcase
    95 end
    96 end
    97 end
    98
    99 endmodule

      这个代码,利用状态机实现将50M的时钟分频到270KHZ的效果,在第一个状态的时候,缓冲一下,进入第二个状态,判断是否写入命令,进而写入命令;在第三个状态进行时钟延迟,这里相当于分频效果,最后进入完成状态。这个代码是参照系统default程序中的一个代码写的,在SOPC Builder里面得到了验证,能够利用软件往LCD里面写东西。

      关于uClinux下LCD的驱动,之前一篇文章没写多少,下次再重新写一下吧!

  • 相关阅读:
    推荐一波好的代码托管
    二十一、如何导入svg图片
    二十、滑动开关css
    十九、CSS如何引入字体
    十八、移动端rem布局
    十五、css3 Filter--滤镜
    十四、css动画基础知识
    十三、初始化标签默认样式
    十二、移动端头部声明
    十一、使用a标签打电话、发短信、发邮件
  • 原文地址:https://www.cnblogs.com/yingfang18/p/1885110.html
Copyright © 2020-2023  润新知