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

时间:2021-03-05 15:57:06

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

一、LCD16207工作原理

1、DE2下LCD16207规格

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

2、管教定义及含义

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

3、工作原理

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

  上面我们可以看到,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信号的线不同搭配产生不同的功能,如下图所示:

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

  注:上面写错了,应该是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中的位置。

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

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

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

5、指令表

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

  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、读写时序 

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

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

  具体参数其实大家在看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的驱动,之前一篇文章没写多少,下次再重新写一下吧!