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
显示效果:
图片显示待续。