LCD12864 液晶显示-汉字及自定义显示(并口)

  LCD12864带字库,型号:CM12864-12.其相关数据手册可以在百度中搜索“ST7920 系列中文图形液晶模块使用说明书”,里面有详细的介绍。这里就不在多描述。

其原理简图:(我们只需关心接口部分)

接口定义:这里注意V0,我一开始就栽倒这,网上搜到的资料中,这PIN可以悬空或接个滑动电阻,程序检查好多遍,没有发现问题,就是不显示,接到3.3V上也不行,后来把V0直接接到5V上,就可以正常显示。在这提醒大家数据手册仅供参考,具体还是以自己的实物为主。避免走没必要的弯路。

管脚号

管脚名称

电平

管脚功能描述

1

VSS

0V

电源地

2

VCC

5V

电源正

3

V0

对比度(亮度)调整.(直接接到5V上最靠谱)

4

RS(CS)

H/L

RS=“H”,表示DB7——DB0为显示数据

RS=“L”,表示DB7——DB0为显示指令数据

5

R/W(SID)

H/L

R/W=“H”,E=“H”,数据被读到DB7——DB0

R/W=“L”,E=“H→L”, DB7——DB0的数据被写到IR或DR

6

E(SCLK)

H/L

使能信号

7

DB0

H/L

三态数据线

8

DB1

H/L

三态数据线

9

DB2

H/L

三态数据线

10

DB3

H/L

三态数据线

11

DB4

H/L

三态数据线

12

DB5

H/L

三态数据线

13

DB6

H/L

三态数据线

14

DB7

H/L

三态数据线

15

PSB

H/L

H:8位或4位并口方式,L:串口方式

16

NC

空脚

17

/RESET

H/L

复位端,低电平有效(悬空或接到5V都可以)

18

VOUT

LCD驱动电压输出端(悬空)

19

A

VDD

背光源正端(+5V)

20

K

VSS

背光源负端(0V)

ST7920数据手册中,提到每次在写命令之前都要判断LCD是否处于空闲状态,是为0,否则为1,本次试验全过程只写不读,为了避开LCD忙的状态,可以采取隔断时间写一次命令或数据。在指令表中,可以看到每个命令执行的时间,这里注意,除清除显示和地址归位,网上有不同的说法,有的说是1.6ms,有的4.6ms外,其他命令执行时间都是72us,不管怎么样,我们还是取最大值更为靠谱,4.6ms取个整数,好听点的6ms吧。当然可以取比这个更大(LCD在显示数据时,是一个接一个的显示出来,就可以察觉到,取的越大,显示速度就越慢),看自己的决定了。利用FPGA分频,产生一个周期6ms的时钟,给LCD的E管脚,进行控制写数据或命令。在8为并口写操作时序图中,DB0~DB7是在E为高时,写入数据。

知道了何时给LCD写数据或命令,还得知道如何把自己想要显示的东西显示在LCD屏幕上,这点也不难:

第一得知道中文字行的编码,可以查国标GB2312,来调用CGROM字库,比如”文:CEC4、少:C9D9、清:C7E5“。或可以下载“汉字十六进制转换工具”软件直接生成。

第二得知道显示文字的地址该如何设置,就是一个文字我可以摆在第一行的开头或结尾或其他行。如下图示。

第三若自带的库中没有你想要的东西时,可以自己定义,比如代码中的星星月亮组合图标,库中没有,那么我们可以自己定义(组合图标的编码可以用字模软件进行提取)。自定义字符具体操作,先设定CGRAM存储地址,其次把该组合图标的编码数据放置到该地址中,在设置该图标在LCD屏幕显示的位置,最后连续写两次数据(注意写的是数据不是命令,我也被这东东栽倒一次),先写高8it,后写低8bit,就可以了。此时知道写这数据到底是啥数据。那么就得理解0x0000,0x0002,0x0004,0x0006这四种编码.至于这四种编码有什么区别,我也不是很明白,在程序中,0x0000和0x0006没发现有区别,显示正常;0x0002,在星星的左上角有个小点;0x0004显示乱码。

第四半宽字型,数据手册中写的是”半宽字型ROM(HCGROM),总共提供126 个西文字型(16×8 点阵)“,应该就是英文字符。程序中的”LCD12864″。

在写代码之前理清思路,程序的流程该如何跑,写起代码来也比较顺手。如下图。前面设置好频率后,每步中的延时就不用在考虑了。

代码:(使用并口,只有写)

LCD12864.v

  1 module LCD12864(
  2                     //input 
  3                     sys_clk,
  4                     rst_n,
  5                     
  6                     //output 
  7                     lcd_rs,
  8                     lcd_rw,
  9                     lcd_en,
 10                     lcd_data,
 11                     lcd_psb
 12                 );
 13 input sys_clk;// 50MHZ
 14 input rst_n;
 15 
 16 output lcd_rs;//H:data    L:command
 17 output lcd_rw;//H:read module    L:write module
 18 output lcd_en;//H active
 19 output [7:0] lcd_data;
 20 output lcd_psb;//H:parallel    module    L:SPI module
 21 
 22 /***************************************************/
 23 parameter T3MS = 18'd149_999;
 24 parameter    IDLE           = 4'd0,
 25             INIT_FUN_SET1 = 4'd1,
 26             INIT_FUN_SET2 = 4'd2,
 27             INIT_DISPLAY  = 4'd3,
 28             INIT_CLEAR       = 4'd4,
 29             INIT_DOT_SET  = 4'd5,
 30             SET_DDRAM      = 4'd6,
 31             WRITE_DATA1      = 4'd7,
 32             INIT_FUN_SET3 = 4'd8,
 33             SET_CGRAM     = 4'd9,
 34             WRITE_DATA2   = 4'd10,
 35             SET_DDRAM2    = 4'd11,
 36             SET_CUSTOM_L  = 4'd12,
 37             SET_CUSTOM_H  = 4'd13,
 38             STOP          = 4'd14;
 39 /***************************************************/
 40 //产生周期为6MS的lcd_clk给LCD
 41 reg [17:0] cnt;
 42 reg lcd_clk;
 43 always @(posedge sys_clk or negedge rst_n)
 44 if(!rst_n) begin
 45     cnt <= 18'd0;
 46     lcd_clk <= 1'b0;
 47 end
 48 else if(cnt == T3MS)begin
 49     cnt <= 18'd0;
 50     lcd_clk <= ~lcd_clk;
 51 end
 52 else
 53     cnt <= cnt + 1'b1;
 54 /***************************************************/
 55 reg lcd_rs;
 56 always @(posedge lcd_clk or negedge rst_n)
 57 if(!rst_n)
 58     lcd_rs <= 1'b0;
 59 else if((state == WRITE_DATA1) || (state == WRITE_DATA2)|| (state == SET_CUSTOM_H) || (state == SET_CUSTOM_L))
 60     lcd_rs <= 1'b1;        //写数据模式
 61 else
 62     lcd_rs <= 1'b0;        //写命令模式
 63 /***************************************************/
 64 reg [3:0] state;
 65 reg [7:0] lcd_data;
 66 reg [6:0] num;
 67 reg en;
 68 always @(posedge lcd_clk or negedge rst_n)
 69 if(!rst_n) begin
 70     state <= IDLE;
 71     lcd_data <= 8'hzz;
 72     en <= 1'b1;
 73     num <= 6'd0;
 74 end    
 75 else
 76     case(state)
 77         IDLE: 
 78         begin
 79             state <= INIT_FUN_SET1;
 80             lcd_data <= 8'hzz;
 81             en <= 1'b1;
 82         end
 83         
 84         INIT_FUN_SET1: 
 85         begin
 86             lcd_data <= 8'h30;    //功能设定
 87             state <= INIT_FUN_SET2;
 88         end 
 89         
 90         INIT_FUN_SET2:
 91         begin
 92             lcd_data <= 8'h30;    //功能设定
 93             state <= INIT_DISPLAY;
 94         end
 95             
 96         INIT_DISPLAY:
 97         begin
 98             lcd_data <= 8'h0c;    //显示设定
 99             state <= INIT_CLEAR;
100         end
101             
102         INIT_CLEAR:
103         begin
104             lcd_data <= 8'h01;    //清屏
105             state <= INIT_DOT_SET;
106         end
107         
108         INIT_DOT_SET:
109         begin
110             lcd_data <= 8'h06;    //进入点设定
111             state <= SET_DDRAM;
112         end
113         
114         SET_DDRAM:
115         begin
116             if(num == 7'd0)
117                 lcd_data <= 8'h81;//1 line
118             else if(num == 7'd12)
119                 lcd_data <= 8'h92;//2 line
120             else if(num == 7'd18)
121                 lcd_data <= 8'h8a;//3 line
122             else if(num == 7'd26)
123                 lcd_data <= 8'h99;//4 line
124                 
125             state <= WRITE_DATA1;
126         end
127         
128         WRITE_DATA1:
129         begin
130             if(num <= 7'd11) begin   
131                 num <= num + 1'b1;
132                 lcd_data <= dis_data;
133                 if(num == 7'd11)
134                     state <= SET_DDRAM;
135                 else
136                     state <= WRITE_DATA1;
137             end
138             else if( num > 7'd11 && num <= 7'd17) begin
139                 num <= num + 1'b1;
140                 lcd_data <= dis_data;
141                 if(num == 7'd17)
142                     state <= SET_DDRAM;
143                 else
144                     state <= WRITE_DATA1;
145             end
146             else if(num > 7'd17 && num <= 7'd25) begin
147                 num <= num + 1'b1;
148                 lcd_data <= dis_data;
149                 if(num == 7'd25)
150                     state <= SET_DDRAM;
151                 else
152                     state <= WRITE_DATA1;
153             end
154             else if(num > 7'd25 && num <= 7'd33) begin
155                 num <= num + 1'b1;
156                 lcd_data <= dis_data;
157                 if(num == 7'd33)
158                     state <= INIT_FUN_SET3;
159                 else
160                     state <= WRITE_DATA1;
161             end
162         end
163         
164         INIT_FUN_SET3:    
165         begin
166             lcd_data <= 8'h30;//功能设定
167             state <= SET_CGRAM;
168         end
169         
170         SET_CGRAM:
171         begin
172             lcd_data <= 8'h40;//设定CGRAM字符的位置
173             state <= WRITE_DATA2;
174         end
175         
176         WRITE_DATA2:
177         begin
178             if(num >= 7'd34 && num <= 7'd65) begin 
179                 num <= num + 1'b1;
180                 lcd_data <= dis_data;
181                 state <= WRITE_DATA2;
182             end
183             else begin
184                 num <= 7'd0;
185                 state <= SET_DDRAM2;
186             end
187         end
188         
189         SET_DDRAM2:
190         begin
191             lcd_data <= 8'h9e;    //4line
192             state <= SET_CUSTOM_H;//设置自定义显示字符编码
193         end
194         
195         SET_CUSTOM_H:
196         begin
197             lcd_data <= 8'h00;//高8bit
198             state <= SET_CUSTOM_L;
199         end
200         
201         SET_CUSTOM_L:
202         begin
203             lcd_data <= 8'h06;//低8bit 00:正常 02:星星左上角多了一小点 04:显示的是乱码 06:显示也正常
204             state <= STOP;
205         end
206         
207         STOP: 
208         begin
209             en <= 1'b0;//显示完了,lcd_e就一直拉为低
210             state <= STOP;
211         end
212         
213         default: state <= IDLE;
214     endcase
215 /***************************************************/
216 reg [7:0] dis_data;
217 always @(posedge sys_clk or negedge rst_n)
218 if(!rst_n)
219     dis_data <= 8'hzz;
220 else
221     case(num)
222     //1 Line 81位置显示 欢迎访问博客
223     7'd0   :    dis_data <= 8'hbb; 
224     7'd1   :    dis_data <= 8'hb6; 
225     7'd2   :    dis_data <= 8'hd3; 
226     7'd3   :    dis_data <= 8'had; 
227     7'd4   :    dis_data <= 8'hb7; 
228     7'd5   :    dis_data <= 8'hc3; 
229     7'd6   :    dis_data <= 8'hce; 
230     7'd7   :    dis_data <= 8'hca; 
231     7'd8   :    dis_data <= 8'hb2; 
232     7'd9   :    dis_data <= 8'ha9; 
233     7'd10  :    dis_data <= 8'hbf; 
234     7'd11  :    dis_data <= 8'hcd; 
235     //2Line    92位置显示 文少清     
236     7'd12  :    dis_data <= 8'hce; 
237     7'd13  :    dis_data <= 8'hc4; 
238     7'd14  :    dis_data <= 8'hc9; 
239     7'd15  :    dis_data <= 8'hd9; 
240     7'd16  :    dis_data <= 8'hC7; 
241     7'd17  :    dis_data <= 8'he5; 
242     //3Line 8a位置显示 LCD12864   
243     7'd18  :    dis_data <=  "L";  
244     7'd19  :    dis_data <=  "C";  
245     7'd20  :    dis_data <=  "D";  
246     7'd21  :    dis_data <=  "1";  
247     7'd22  :    dis_data <=  "2";  
248     7'd23  :    dis_data <=  "8";  
249     7'd24  :    dis_data <=  "6";  
250     7'd25  :    dis_data <=  "4";  
251     //4Line 99位置显示 谢谢! 
252     7'd26  :    dis_data <= 8'hd0; 
253     7'd27  :    dis_data <= 8'hbb; 
254     7'd28  :    dis_data <= 8'hd0; 
255     7'd29  :    dis_data <= 8'hbb; 
256     7'd30  :    dis_data <= 8'ha3; 
257     7'd31  :    dis_data <= 8'ha1; 
258     7'd32  :    dis_data <= " ";   //这两次空格可以不写的
259     7'd33  :    dis_data <= " ";   
260     //4line 9e位置显示星星月亮                            
261     7'd34  :    dis_data <= 8'h08;
262     7'd35  :    dis_data <= 8'h20;
263     7'd36  :    dis_data <= 8'h1c;
264     7'd37  :    dis_data <= 8'h10;
265     7'd38  :    dis_data <= 8'h1c;
266     7'd39  :    dis_data <= 8'h1c;
267     7'd40  :    dis_data <= 8'hff;
268     7'd41  :    dis_data <= 8'h9e;
269     7'd42  :    dis_data <= 8'h7f;
270     7'd43  :    dis_data <= 8'h1e;
271     7'd43  :    dis_data <= 8'h1c;
272     7'd45  :    dis_data <= 8'h1f;
273     7'd46  :    dis_data <= 8'h3e;
274     7'd47  :    dis_data <= 8'h1f;
275     7'd48  :    dis_data <= 8'h3e;
276     7'd49  :    dis_data <= 8'h1f;
277     7'd50  :    dis_data <= 8'h77;
278     7'd51  :    dis_data <= 8'h1f;
279     7'd52  :    dis_data <= 8'h41;
280     7'd53  :    dis_data <= 8'h3f;
281     7'd54  :    dis_data <= 8'h00;
282     7'd55  :    dis_data <= 8'h7e;
283     7'd56  :    dis_data <= 8'h00;
284     7'd57  :    dis_data <= 8'hfe;
285     7'd58  :    dis_data <= 8'h83;
286     7'd59  :    dis_data <= 8'hfc;
287     7'd60  :    dis_data <= 8'h7f;
288     7'd61  :    dis_data <= 8'hf8;
289     7'd62  :    dis_data <= 8'h3f;
290     7'd63  :    dis_data <= 8'hf0;
291     7'd64  :    dis_data <= 8'h0f;
292     7'd65  :    dis_data <= 8'hc0;
293     default:    dis_data <= 8'h00;
294     endcase 
295 /***************************************************/
296 assign lcd_rw = 1'b0;//只有写模式
297 assign lcd_psb = 1'b1;//并口模式
298 assign lcd_en = en ?  lcd_clk : 1'b0;
299 /***************************************************/
300 endmodule

View Code

显示效果:

图片显示待续。

  

Published by

风君子

独自遨游何稽首 揭天掀地慰生平

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注