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
顯示效果:
圖片顯示待續。