本帖最后由 caizhiwei 于 2015-11-5 11:04 编辑
; f2 Z6 f5 s3 V
9 R6 b. ~, j" Q! |: ^ 虽然很久之前(51时代)就开始接触lcd12864,如今在工控机里面,LCD12864还是应用比较普遍的!/ U2 p6 w! B$ c' i# l% `2 j( _
我用的lcd12864类型为串行接口,3.3V st7920
: w$ b6 {/ r' h- L代码优化说明:, c: z1 N5 B& s+ k/ ^& P& [
1.修复了字符串,汉字串不能自动换行的bug
/ Q' u( J' Y2 A% Y7 q注意:1 o) g# D" b6 v" I% p
1.在使用带jtag接口的I/O时要特别注意9 z. D6 {# |; B3 ]
PA13:SWDIO/JTAG_TMS
+ I* ^2 L6 b0 h$ j PA14:SWCLK/JTAG_TCK
5 x' @& V. g: E/ ?7 r3 F, m" r PA15:JTAG_TDI. H. q4 } m" Q
PB3:JTAG_TDO- D/ l( K: P1 ~( U, ? y
PB4:JTAG_RST
& M7 r5 o) U/ n2 `1 h硬件设计缺陷:
2 n3 l, ` A0 l" R) i' E1.没有引出LCM的复位引脚,导致偶尔显示不正常之后,mcu复位(LCM并没有复位)
( b' D) Z# C9 d# n; N$ e也无法解决,只能强行断电重启。( [0 d. k7 B! g$ n2 _. }3 r6 t% K
2.BLK液晶背光引脚的输入电流至少在20mA以上,没有用三极管驱动,而是直接用IO驱动,: c/ Z- i2 n) N1 P
需要较大的驱动电流。
. T; p3 [7 Y9 b0 Z" W) t: C3.
) L5 \$ t7 R% p6 a6 h编译器缺陷:
- ]8 k% r N, i# B2 G' v1.由于使用的是iar6.70版本,编译器在编译汉字串数组的时候可能会使带字库液晶产生乱码。
3 y# B) u8 {. G! s" }$ X. ?$ a4 j 所以在有汉字数组的C文件中统一使用简体中文(GB2312)(全选--右键--Charracter Encoding)
9 M+ P# V' x: [$ t0 {( _
* p f% a+ M% c7 i7 r部分硬件结构说明:
- E. Q( v8 S. W. S, y s: [# x1.按键按下,(上连接VCC)连接电阻下拉到地,检测IO连接上端,检测到高电平。8 F# ]: q. k5 }9 I' T
2.lcd12864底板反面接线图:
3 W2 \) L% B* r! |+ I- o) M+ c$ J* B" S' y8 S% |
从反面看:
% X( B+ G0 D3 S4 \2 Y5V RW GND GND LED K2 K4 GND2 L% t7 X3 _) ?1 a
GND RS E BLK GND K1 K3 5V9 s' Q! W. } o6 {
* x1 R& V2 n. \) v( O2015-6-10 原工程代码在23楼!|r' H3 N' I+ W) I1 F5 M
2015-7-12 程序更新了,,代码在35楼!: y* R( N5 W9 Q, c) k0 S' _
更新记录:
% b: D! P7 Y, {( p9 P8 R2 r) O1.增加了24*32大字体显示功能;9 H+ B# ?6 r. a0 _( g
2.增加了16*32大字体显示功能;5 Y0 I' R1 p: i& i+ v7 Y
3.优化了读LCD忙的代码;
% H) Q1 l, I x/ ?9 |( ?4 _4.新增了是sprintf的任意位数数字直接显示;
+ O- K5 N8 U' ~, U9 J# D6 f5.新增了CGRAM的写入,读出操作函数;
3 y6 B' z* b4 T6.优化了绘图GDRAM函数的操作,绘图速度提高;
7 p+ Z- u: r1 ^# z+ W# ?2015.11.04 ,看到很多评论说链接失效,现在重新找了一份完整的工程代码,整理之后传到网盘:" G3 N! `+ L1 B+ p, H6 d
这个代码优化了.h文件中的宏定义,方便用户移植,C文件和gui.c文件均不用修改。
. r6 f9 B! k, k7 Mhttps://pan.baidu.com/s/1pJw3wHd ) ]# @) O5 A. l, I! Y) u
; M4 |' E# I0 m" ? `- 5 ?: W/ C4 T' ~. B" v4 B) i) T! W
- #include "gui.h"0 Q+ \$ ?* Y) U* P1 q
) B* ?& g+ e @+ y- X- p( s% T- /******************************************************************************* . K0 V' u' @9 B) [6 J! Y, J
- DDRAM地址- ]8 x) T; q& M8 _7 R
- 0x80 0x81 0x82 0x83 0x84 0x85 0x86 0x87 //第一行汉字位置
+ n; w! M1 Y6 h - 0x90 0x91 0x92 0x93 0x94 0x95 0x96 0x97 //第二行汉字位置
7 t5 a$ o( J! F% o, a0 R' X - 0x88 0x89 0x8a 0x8b 0x8c 0x8d 0x8e 0x8f //第三行汉字位置
. C- ~; x$ W1 m$ H - 0x98 0x99 0x9a 0x9b 0x9c 0x9d 0x9e 0x9f //第四行汉字位置+ o3 J, v/ D6 r0 S8 v6 ]
. k: b6 m; f$ l' b [! Y; u/ p- *******************************************************************************/
- s( f' S/ L* z4 ?5 }1 }
6 h) w) F7 E8 x! {8 K- /*******************************************************************************
K4 ^6 C, d. F5 E; z }3 ? - * 名称 : LCD_SetPos
/ `5 \; p1 Z2 ~, ?/ U/ V/ Z - * 功能 : 设定显示位置 / R5 D& ]) s- r$ j
- * 输入 : x (0~3)行
3 `) j+ y- U* _& ~5 X - y (0~7)列& @% a% S: z: p( o) c
- * 输出 : 无 ( @4 z: U9 L* m
- *******************************************************************************/
0 z+ E. E" r; K" Z - void LCD_SetPos(u8 row, u8 col) , S# o4 A5 T: E% }& m0 g
- {
0 ?+ z5 }( I# a; ~ V0 j& q& ^ - u8 pos; ; f) ^' {. [, c; J$ v" t" K% q
- if( row == 0) ! Z% P" U, A2 d( K+ D# R) d: y
- row = 0x80;
4 a# p0 G# k; D5 p9 \ - else if(row == 1) 5 S1 K8 P5 V8 Z, m1 d
- row = 0x90;
, G0 q" d0 T( d% a6 k z5 x - else if(row == 2)
$ T: P5 t8 O* V. e/ C - row = 0x88;
+ g/ N) i# M. J, I - else if(row == 3) 4 z' x0 D8 b6 f0 V, M
- row = 0x98; 9 _ G1 \5 m. @
- pos = row + col;
" I+ Q2 U y% U3 v+ j - LCD_WriteCMD(pos);//在写入数据前先指定显示地址
% ~' J; G) G f8 s& ~ - delay_us(10);# |2 z' e+ y' m4 l" G
- } K$ I/ {8 L. X( k) n
6 r& C9 o( A/ l! j- d- 3 {% i' \, s3 k; j
- /********************************************************************
$ |" z R! M6 \3 u- R0 w - * 名称 : ShowASCII $ V9 _' L% P+ ^2 N- Z
- * 功能 : 在当前坐标位置显示单个字符
( y: [5 ~3 G7 e - * 输入 : *s
2 t E: H4 P w& `; z4 i, i) h - * 输出 : 无
4 ]! R7 V8 \* k" d7 a9 P5 t7 c - ***********************************************************************/ , n+ J" [( @! u
- void ShowASCII(u8 i)
+ A. b- H+ q! i/ r" b3 w/ k* H - {. v/ L7 w- W+ Y0 H% S6 L1 q+ T
- LCD_WriteDATA(i);% Q% V7 @( l# x T5 L8 [
- }5 [& `( U4 J9 v8 I
- & P1 \. a( z% M
- void ShowCharPos(u8 row, u8 col,u8 dat)
6 a& ?1 ?. Z% B8 p' `( V - { $ A# }5 T- t) F8 D" |
- LCD_SetPos(row, col);
5 }3 p1 q- y. Q - ShowASCII(dat);
5 |' ~" S! B- N9 G - }4 Y- I( T( Q. b Q
8 s' V* a- m) V, ]- o& ~- /******************************************************************************* 7 i% G; F; e$ R. S# x
- * 名称 : ShowEnString(u8 *s) * V$ O Y2 I" X! M5 O& z7 W9 C& ]
- * 功能 : 显示英文字符串 4 @/ d3 r3 M2 W; _4 W
- * 输入 : *s 2 { y; G% Q& o- j6 P
- * 输出 : 无 6 K2 Z! ?6 d( u$ Z2 Z! i' p
- *******************************************************************************/ + d- l/ q8 N3 r# \0 C
- void ShowString(u8 *s) 8 x f8 r% U4 \; M
- { ) g8 s: C1 T0 ?2 l, H! I
- u8 i = 0;
: R2 s! v. Q' [ - while(s[i] != '\0')
, Y" M9 m- {* R7 _- p) w+ I# x) j - { - u" u7 R) f' v( ?
- ShowASCII(s[i++]); 8 ~2 `6 |) ?/ l7 R6 E
- } ) ?% ?; x# M ]! Z6 {! k$ n
- }
% C! W G* m+ g3 e2 k; ^) d
C( x: P7 G+ x Z& T. A- void ShowStringPos(u8 row, u8 col,u8 *s) //col is full char wide - H/ h0 ~3 N8 ^5 Q Q- I
- { 5 D0 w0 O, m5 s5 l, K4 j9 A
- u8 i = 0;
$ O- j: D' c5 H: @ - LCD_SetPos(row, col);
8 h. i* B' V9 C; e# U - while(s[i] != '\0')
) @, [- } |5 L - {
& h# o8 Q, i( `; c - ShowASCII(s[i++]);
& V$ v0 {# y+ i6 F; }) _, q - if((2*col+i)%(16)==0) //must 16, is OK
# W, d6 K/ ] W* j P* D - {
# O! n) D0 v0 q9 L* H& f - LCD_SetPos(++row,0); //display start at next row." E' {6 ?6 F' j6 U% D
- }, K. M3 c; T/ V7 T
- 3 q1 d+ L, d5 ?# K: E
- }
R5 u7 v" @6 P' x+ H* B+ x% { - }
/ l+ l& R; P( Q" p2 ^+ J - : N+ b! v# r4 x# {8 _
$ G3 t: ?2 i! z
; G. F+ V2 x" q0 Y! O. r8 w9 u( N; {- /******************************************************************************* 2 |# F) C8 F. q7 B! L, L
- * 名称 : ShowGB
- n6 p* y+ ~& L# Q8 {& G5 |0 Z - * 功能 : 显示单个汉字0 a: e1 Z; i0 @. r, _+ ^7 z, Z
- * 输入 : i
1 z9 d9 \. L* j4 R6 T - * 输出 : 无
$ K( h$ Z- \/ J# {% s' P; [ - ********************************************************************************/
9 d) L. M5 t- f$ k H/ X - void ShowGB( unsigned char *HZ)5 H6 h! W- Z x! i8 Z& T
- {" @( x7 y" W% ?0 U
- LCD_WriteDATA(HZ[0]); //写入汉字的高八位数据. Q3 G6 b/ m" O9 g1 u+ ]7 f
-
& I- \- X) c- c2 @ - LCD_WriteDATA(HZ[1]); //写入汉字的低八位数据 . ~+ ^2 T1 R) c6 j4 B( l
-
) i ^- z, p7 _# m3 s0 S - }( j ]* L" _$ L( y u
- 6 F6 R0 U% F8 P# V( C0 j8 F
- void ShowGBPos(u8 row, u8 col, u8 *HZ)
" J+ h6 v" g o0 K - {
3 |) \7 y' R, m2 J ?+ }9 t - LCD_SetPos(row, col);- y" o0 E/ h* h9 S2 k9 ?+ @
- ShowGB(HZ);
+ T3 C3 k# E& J* U" n - }
- i: l& F7 ]: e- _5 f. L7 W1 n
9 Z6 z+ G/ [" ?/ A- /******************************************************************** 3 B9 \- v" j# w( b* r( c4 g0 r
- * 名称 : ShowGBStringPos 1 j& V6 }# @; O! k9 ~& f' s8 W2 [
- * 功能 : 显示多个汉字
' v, g$ n' D4 U' `* o x - * 输入 : u8 row, u8 col :汉字串的起始地址
6 S( J' j& X6 x* _! F& M$ f- Y6 t; S - * 输出 : 无
1 D& J! ]3 h1 u# U - * 说明 : 自动换行:lcm默认换行顺序是乱的,0--2--1--3--00 [' m9 S: v5 j( ~! o/ t4 n
- ***********************************************************************/
1 q$ K5 ~* P( K" r - void ShowGBStringPos(u8 row, u8 col, u8 *s)8 r! X' u, ]7 F4 }# a! U( h
- {
. i& v1 k$ ?# W3 k9 v - u8 i = 0;
* l+ ^2 N, Z3 w$ |! e" u& L - LCD_SetPos(row, col);- k- R: t4 i3 r& x, e
- while (s[i] != '\0')
6 S. Y! ], `0 ~) Q; r- h - {# ~- W( P5 N$ |
- ShowGB(s+i);3 ~! r! [5 M! P* j
- i+=2;
# ], O6 v0 { F/ E1 h# N - if((2*col+i)%(16)==0) //如果满一行
4 P1 d* Y$ H; |; X - { 9 n1 R! t( o6 n: F
- LCD_SetPos(++row,0); //重新设置显示的起始地址1 u+ @6 l- j& n7 Z8 k( F9 H8 r+ b
- }
& D* h- H* ?! A' P+ t9 x: U Y - $ x# t" G+ v# f2 t0 a- |" g6 H
- } 4 G( B0 S' F4 n+ y- @& z1 w
- }) u( L5 s+ ^; s( a* V$ W$ ]" z6 H
8 e9 V% ]% I3 ~+ ]* W0 p- /*******************************************************************************' G j. M9 a. m c- ~% f: H; m
- 测试函数
5 e# Y. W9 l/ F - Function: 用户移植程序之后,用该函数测试液晶是否初始化成功!
* \% e* K! a. x7 C, m - ********************************************************************************/$ J+ b* A1 ]# V- ~
- void LCD_Test(void)
1 u& Y. G# h V2 [$ U: J( C( P' B - {
' `# Z: A% w0 c% S0 e - ShowCharPos(0,0,0x10); //右箭头
" ~) @+ g" t2 ~+ M - ShowCharPos(1,0,0x10); //右箭头 8 P! ~; {8 ], k3 d" M& z( P! f
- ShowString("Hello,world!") ; & o8 Z H f: M6 v: Q. V
- ShowCharPos(2,0,0x10); //右箭头
- J2 G& V6 ^( ?/ ]4 }, ` - ShowASCII(0x11);//左箭头
8 H' F+ p* @' Y5 X - } 5 J6 j+ a) X5 x3 j4 Z
-
* T4 x/ F m" T+ Z - * w/ o% ]' i o. x! X" ]+ J
- 7 ~5 y! j( {4 S2 U( F
- ) j3 l2 g% ~3 }) {7 Q
- * ]; E4 n, \" ^
- //自定义字符写入CGRAM: \' q: k, A6 g- [& @8 p
- void Write_USR_CGRAM(u8 data1,u8 data2,u8 addr)
. z* @; B& @# i; p: q# R. B& ? - { % O8 w% d! ^9 g5 ?8 N( u( w; i
- u8 i;
* d- y* U" H9 J& j# y - for(i=0;i<16;)9 D+ e. T6 u7 j& f8 Y2 ?6 v
- {
B9 V. ~) k0 }1 l( B - LCD_WriteCMD(addr+i); //设定CGRAM地址8 a2 j; y9 q. E; _
- LCD_WriteDATA(data1);8 O! g% r5 d1 J& ]
- LCD_WriteDATA(data1);( l' I" y, G2 p* ^
- i++;
7 f* a$ ~0 x! x1 O# V) v1 G! [0 S - LCD_WriteCMD(addr+i); //设定CGRAM地址7 v. i2 q" f3 s4 _- g% i; k1 R
- LCD_WriteDATA(data2);7 _' |# i0 a3 y% n7 f" ?, n
- LCD_WriteDATA(data2);
" C+ w, v7 c g! `+ @ - i++;$ e. {1 }: P4 C1 I* |
- }
. C! E4 o2 L3 Z - }
. b1 |5 `8 Y2 T N! O* c; `9 a& K - 1 i0 P2 f7 O# T2 w" Y$ \, N
- //显示自定义的字符,并把这个字符填满全屏16*16/ S P9 D# J% P) i' z$ D
- void Show_USR_CGRAM_Char(u8 addr,u8 i): ?* } d+ ~% A& e) _9 A
- {! o/ C- p5 A. ?0 c
- u8 j;
8 [; @( K+ c6 g, ^* T - for(j=0;j<0x20;)
4 H& X+ }7 r, I) n2 G: C# N - { , ]% w+ e$ l- U* k/ c" U- @+ h
- LCD_WriteCMD(addr+j); //设定DDRAM地址( S9 [* b2 w3 B; t. ?2 b8 a
- LCD_WriteDATA(0x00);8 L+ y3 S% N3 u/ ? f7 Q+ [6 U
- LCD_WriteDATA(i);
8 Y3 n' r& c$ j. u( ~3 F) u8 Z - j++;, c1 H: C$ k S* T
- } ; }- K+ {6 C. `% _1 v
- }/ c8 u7 q) u0 J# _
- ' m! j. e( Q% D8 v' ?: a4 w
- //写入GDRAM 绘图,Y是Y绘图坐标,2个字节一行,X是图形起始坐标,CLONG是图形长度,以字节
* U2 l4 J) o1 Q( [ \+ o - //为单位;HIGHT是图形高度,TAB是图形数据表.12864M的图形显示范围是256*32点阵.& l7 @; `9 D1 {
- //要在12864M里显示全屏,取模时一幅图横切成两半$ ]& Z7 a% F- S9 X- Q
- |! v. z: Y0 W4 ~4 M- /*$ p# j! {: ]) i. h
- ST7920提供64×32 个字节的空间(由扩充指令设定绘图RAM 地址),最多可以控制256×64
g" H9 g3 a; U - 点阵的二维绘图缓冲空间,在更改绘图RAM时,由扩充指令设置GDRAM地址先垂直地址后水平
8 Q: e4 E6 I' ?% p- y - 地址(连续2个字节的数据来定义垂直和水平地址),再2个字节的数据给绘图RAM(先高8位
: A5 x8 P' w- \7 r4 ^" Z - 后低8 位)
# }: i" J- B5 h: ]: ? - */# p) K" c8 ?# f, `- T/ K5 d# y
- void WRGDRAM(u8 Y,u8 clong,u8 hight,u8 *TAB1)) n; t/ n3 l1 A; V+ T' C$ ^2 v3 z
- { ! ]0 G6 v7 j; L F
- u16 k=0;/ ?( \. H: K: D0 n* V
- u8 j;5 j2 u+ [' w4 h0 W8 P( o1 V
- u8 i;
5 J3 d; N' g6 F& ^ - LCD_WriteCMD(0x34);
* O, F' R. l+ r: E: r2 s! R U - LCD_WriteCMD(0x36);
3 @( r. a0 `6 y' J6 Z - for(j=0;j<hight;)
; _0 W7 g2 ?* f& O1 Z - {3 Y/ d- B, K. C0 I
- LCD_WriteCMD(Y+j);) q! y/ M d* m0 H4 P+ G7 j$ v
- LCD_WriteCMD(0x80);//X坐标
9 f( }. u8 T0 {& u - for(i=0;i<clong;i++)//
2 Y# m1 }; a9 {2 @% L* l - {- _7 V% C5 U3 {# z7 ?" Q
- LCD_WriteDATA(TAB1[k]);8 l% Z, o- S) n+ \
- k++;
; M/ [1 k: @6 f# ]% x0 R. T. G - }/ l9 L" Z0 C0 C( q0 g
- j++;/ v% X1 }/ j. p" l- C( |
- }
5 \. N& A n! A# x2 ~" K2 T - }
/ ]) a# A2 c- |3 }
0 G& }$ m7 E! U6 v _- /********************************************************************
. R" C: G7 ?! _ - * 名称 : ShowBlankPos * ?' o( Q; k2 _* |( d
- * 功能 : 在当前坐标位置显示单个字符
' ]0 R; T) {- h! \* g$ H3 ^, Q - * 输入 : num 半宽字符的个数
) W" |% i' `: q1 b - * 功能 : 黑板擦功能,擦除不显示的内容8 `* _* B5 }6 ?8 y
- ***********************************************************************/
. o& F. U- y4 G9 u+ o* q+ ^ - void ShowBlankPos(u8 row, u8 col, u8 num)
5 H" N3 }, a6 g/ Q) v' y! P5 P7 \ - {
* v/ m: Q7 ^9 K+ u" h N - u8 i ;
. x: T! U7 t- X8 n1 \! N3 Z - LCD_SetPos(row,col); y! T" @/ `. ?6 \7 g' s
- for (i = 0; i < num;i++)
( R$ o5 }6 {0 `( H1 T, c: d; u m Q6 M - LCD_WriteDATA(0x20); //写空格
. T* d" y! w- q7 i: ]$ ] p - }
X# g2 Q* K+ }* a0 V
/ t. W, `, m# W9 _2 P5 M6 E
0 W4 k( Q! B* N
/ w! k9 C& y' \" I: v D/ f
- @9 x* A r( T$ G9 G+ j2 I" {- ' G/ K3 C" {6 ]4 ~
4 m# ~6 V# o9 ^6 x1 E- 8 j' j9 t/ q0 B- k9 k+ v. y; Y
- - I2 M, w- C" H5 E J2 p( I9 T: t
/ S( `3 w6 i) @( o; m% p" M
& M' S6 x! J! ? ?3 b! `) a0 X7 N- # h' _; Q: E4 d/ F2 N. J
& k- K. {5 G5 t6 h) s6 c- 8 C8 T7 `* X- M$ h
- ) U7 _8 m2 a8 \) N ?7 A
- |- N9 {$ X0 J
7 `5 ]( C& s1 H" D7 I, U- 0 M1 p0 {$ K, x- B, X4 a. }
复制代码 上图:
; P, |- f% |: i$ [
& O1 j P' m6 I5 k" W2 s6 }. u
Hellokity:
: W) q! i/ N& {4 L6 o* r& y' C
?4 l7 c! I7 f8 }
2 g0 o+ V% n4 |
& U3 C D0 y* t/ B# [6 |$ H0 A6 i0 b# Z; y% f3 r2 `
1 V' r9 D, ?1 H+ |: {8 i3 b2 J
, G& j0 B$ z5 O5 H8 Z9 k
$ K1 p2 D6 ?0 r; n+ G5 N
|
点评
需要创建一个屏幕大小的缓冲区数组,将要显示的字模数据放入数组里面,后面再使用绘图模式,统一将数组刷上去就可以实现了& c: H' I7 _* U5 B4 }& k
是的,多了一个字母~~
这个是3.3V的屏,很好驱动的撒,这个是标准屏,目前还是用的很广的
你居然认识我哟?TA在第10楼~
还是没有花羊羊好看吧!!!