你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

【经验分享】STM32H7的LTDC应用之汉字小字库和全字库制作

[复制链接]
STMCU小助手 发布时间:2021-10-31 17:42
53.1 初学者重要提示
: m# J# ]: a" p% O$ G  学习本章节前,务必优先学习第52章,需要对点阵字体字符编码有个认识。
! L/ `7 f' y' o  LTDC驱动设计和相关问题在第51章有详细说明。( L: h) l; q0 l7 D1 b4 s
  本章节为大家讲解的小字库和全字库方法,简单易用,是直接以C文件格式存储到内部Flash的。支持12点阵,16点阵,24点阵和32点阵的ASCII以及GB2312编码汉字显示。) k- P" ~, a3 b5 j$ x& l( }
53.2 使用MakeDot小软件生成C文件格式小字库方法
7 o4 Q. z) k0 b+ o" |) ?生成方法比较简单,这里做个介绍:% k3 R3 m/ K0 {; V

( {; p; ~6 L$ M  B( ~+ y3 j53.2.1 第1步,准备好显示的字符: Y% T5 B& ~7 g: M$ [0 V" \
比如要显示如下字符,采用16点阵格式:7 Z' s4 C4 \; G3 i! d% `
/ I) N5 k4 g8 s: I8 i
  1. 故人西辞黄鹤楼,烟花三月下扬州。+ d  O3 G$ q) F: i/ H: c$ K
  2. 孤帆远影碧空尽,唯见长江天际流。
复制代码

& v4 G2 r- ^2 I7 f. I53.2.2 第2步,复制要显示的字符到MakeDot小软件
" E/ r" x* o& `! n% _* ~选择16点阵,并将要显示的字符复制到输入窗口:
' U' u: a) G$ r. C5 J. ~
: _  O& Y6 v* g. t8 o
aHR0cHM6Ly9pbWcyMDE4LmNuYmxvZ3MuY29tL2NvbW1vbi8xMzc5MTA3LzIwMjAwMi8xMzc5MTA3LTIw.png

8 P0 E6 ]2 }8 h, X7 v3 i2 v  M, @2 m6 i- s5 l, e) m
点击生成数组按钮后的效果如下:
# h2 F1 p2 {! \# {/ J8 A
; p5 M! C& e2 t( E
aHR0cHM6Ly9pbWcyMDE4LmNuYmxvZ3MuY29tL2NvbW1vbi8xMzc5MTA3LzIwMjAwMi8xMzc5MTA3LTIw.png
  t& F( f- N% }, O; R

; u8 i3 E* E* Y. f; W1 D3 E53.2.3 第3步,复制生成的数组到工程中& }. r- K3 F6 ]: j. O
在输出窗口鼠标右击,选择“全选”,然后再次鼠标右击选择复制。
2 U( s& h! X3 }7 z% B; \
# I; g* P. k4 p5 s* W# X1 H
aHR0cHM6Ly9pbWcyMDE4LmNuYmxvZ3MuY29tL2NvbW1vbi8xMzc5MTA3LzIwMjAwMi8xMzc5MTA3LTIw.png

$ w2 I, I2 `- F1 X6 x
) X: s7 P2 ^+ G+ `这样就可以粘贴到工程的hz.c文件里面:& o/ B$ S- O3 A) S6 h5 c+ \
$ ?8 t" ]2 o  d. Z7 r# {) ]
aHR0cHM6Ly9pbWcyMDE4LmNuYmxvZ3MuY29tL2NvbW1vbi8xMzc5MTA3LzIwMjAwMi8xMzc5MTA3LTIw.png

/ u+ j  X% b/ O% `, C% I
2 d2 @) L/ m5 W( u将点阵数据放在相应的文件里面时要注意加上两个0XFF。hz.c文件的内容如下:
5 Q7 v3 K7 f  r  I/ N' f) H( k, O& B0 z
/*# C4 f3 T+ H+ O" E9 C- P: c
    FLASH中内嵌小字库,只包括本程序用到的汉字点阵
# U5 Q9 R8 I  o. P    每行点阵数据,头2字节是汉子的内码,后面是16点阵汉子的字模数据。+ I: A; {3 S" r, f5 |- P
  1. */
    . G$ d& l9 J% ~

  2. 8 O" A; x" O- U8 b: [! q2 A2 {
  3. #ifdef USE_SMALL_FONT
    " j+ l+ r* }4 K+ Y6 B
  4. ( `, {5 ^+ J1 W2 d7 Y3 X5 }
  5. unsigned char const g_Hz16[] = {
    3 |$ f+ ?0 H" V+ @  K

  6. " M# Q6 k+ C" N' `" {! Z8 K
  7. 0xA1,0xA3, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,// 。 //4 x4 j$ Q; C0 l! d. H
  8.            0x00,0x00,0x00,0x00,0x18,0x00,0x24,0x00,0x24,0x00,0x18,0x00,0x00,0x00,0x00,0x00,0 S. r/ z' b2 @, X, h

  9. . v7 N) ^8 ?1 i

  10. 3 S4 e% S( _1 c" Y( q) ^0 F4 Z
  11. 0xA3,0xAC, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,// , //
    % s8 y% ^1 Z& ?8 e& b, @
  12.            0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x00,0x30,0x00,0x10,0x00,0x20,0x00,0x00,0x00,+ G% c5 z& ?# t" w- |( {% v

  13. : a/ _5 e& n6 \' ^: N
  14. 5 E8 @9 i& C4 }2 I/ I# X5 v/ R6 C
  15. 0xB0,0xB2, 0x02,0x00,0x01,0x00,0x3F,0xFC,0x20,0x04,0x42,0x08,0x02,0x00,0x02,0x00,0xFF,0xFE,// 安 //* b" W3 @4 i) `  K' @
  16.            0x04,0x20,0x08,0x20,0x18,0x40,0x06,0x40,0x01,0x80,0x02,0x60,0x0C,0x10,0x70,0x08,  g6 e9 |; ~9 F! I
  17. $ O& e$ G2 \4 Z4 H2 s; a% I7 c
  18. /* 中间部分省略未写 */
    - N8 a1 e! K  L. ]
  19. ; E$ ]) ^" P- {$ i- F
  20. 0xD7,0xD3, 0x00,0x00,0x7F,0xF8,0x00,0x10,0x00,0x20,0x00,0x40,0x01,0x80,0x01,0x00,0xFF,0xFE,// 子 //
    & @' @% c3 R6 [& \/ {
  21.            0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x05,0x00,0x02,0x00,
    3 r) w9 A9 u6 h5 n$ k
  22. 2 q+ m( ^5 F8 M( a: Q4 @
  23. 6 m7 V1 I' v) |- Q; q+ u' h9 q& T
  24. /* 最后一行必须用0xFF,0xFF结束,这是字库数组结束标志 */5 r% P+ E: _- Y% f% {
  25. 0xFF,0xFF
    . q  S" m& S, b9 F5 L0 I  l
  26.   \6 C8 s# Z( x4 {) D3 Y! W
  27. };
    ; Y1 u2 \. P0 y" {7 v( D0 X! R3 C8 |

  28.   v/ `1 B3 H/ ^8 H' D- t$ U
  29. #else6 x: F; O; [* D: C: E
  30.     unsigned char const g_Hz16[] = {0xFF, 0xFF};" `  p& ~; l/ s" J  ?5 S
  31. #endif
复制代码
. i2 r0 D. J( B
添加完毕点阵数据后,在font.h文件里面使能使用小字库:
% @) O" Z8 l( U! d$ s' @
9 ^5 O) i4 l' g: ^1 W#define USE_SMALL_FONT     /* 定义此行表示使用小字库, 这个宏只在bsp_tft+lcd.c中使用 */
- E$ f+ G+ v& t, i- Q' Y: m- `& N. n/ z
至此就完成了小字库的汉字添加,用户就可以在使用16点阵时显示第1步中转换的字符了。. x( \  P, p/ D1 _& Q/ d9 w
* i6 L' j# V2 k, K0 l
53.3 使用MakeDot小软件生成C文件格式全字库方法7 Y( I& M% o3 i! i
生成方法比较简单,这里做个介绍:
8 K5 V! Z( d1 x6 x3 O9 W
( S* {/ j  S+ x/ X' Q' E53.3.1 第1步,准备好GB2312字符集
9 T- c: }9 u8 v; h7 [3 k6 V+ P% PGB2312字符集已经在MakeDot小软件里面存好,点击汉字编码按钮可以看到:# T/ C" Y, X5 F- o

" S. u, M8 \. k* H% @; C  H
aHR0cHM6Ly9pbWcyMDE4LmNuYmxvZ3MuY29tL2NvbW1vbi8xMzc5MTA3LzIwMjAwMi8xMzc5MTA3LTIw.png
8 P0 E; }+ Z4 M. b5 [8 S% g1 J
- O1 F0 _4 g% M& j; j$ ~/ `4 N
53.3.2 第2步,复制GB2312全部字符到MakeDot小软件
# D  y" v' ^' ^  U$ y复制MakeDot小软件中GB2312所有字符到“输入窗口区”(在GB2312字符显示区,鼠标右击选择全选,之后就可以复制了),2 r6 L5 U5 r) X2 g* M

4 C/ c( U  A' H8 l' G$ ^$ I, s
aHR0cHM6Ly9pbWcyMDE4LmNuYmxvZ3MuY29tL2NvbW1vbi8xMzc5MTA3LzIwMjAwMi8xMzc5MTA3LTIw.png

3 O9 ]9 O! o, d; h) P! _8 T3 L
. ^6 [# A/ z& X' U* m/ N. c点击生成数组按钮后的效果如下:
, k& k  o' W- R. E5 }  J. S- _+ f* M' G
aHR0cHM6Ly9pbWcyMDE4LmNuYmxvZ3MuY29tL2NvbW1vbi8xMzc5MTA3LzIwMjAwMi8xMzc5MTA3LTIw.png
- l6 _6 z( R2 j$ u& Y+ ~  T, a

5 [9 L( i# J. Q1 l. x4 o53.3.3 第3步,复制生成的数组到工程中
8 @/ L9 T! x# ?7 Q在输出窗口鼠标右击,选择“全选”,然后再次鼠标右击选择复制。, D3 H6 v, e6 K4 A4 ~$ e
1 r% P3 d0 M( s$ B5 ^
aHR0cHM6Ly9pbWcyMDE4LmNuYmxvZ3MuY29tL2NvbW1vbi8xMzc5MTA3LzIwMjAwMi8xMzc5MTA3LTIw.png

+ C9 N( O' f1 T  n9 u0 ^6 D3 r' l! {& j4 _3 U, h
这样就可以粘贴到工程的hz.c文件里面:
- I, G0 m6 y7 T# _, |5 {! w6 j5 ~2 s5 F" L1 R: W
aHR0cHM6Ly9pbWcyMDE4LmNuYmxvZ3MuY29tL2NvbW1vbi8xMzc5MTA3LzIwMjAwMi8xMzc5MTA3LTIw.png
" P, b$ y2 L( h: d7 f" l" m5 x
9 L+ R" X8 z" z. z0 ?& @% G% W
将点阵数据放在相应的文件里面时要注意加上两个0XFF。hz.c文件的内容如下:$ ~) F1 V) U8 k4 p6 N6 L

! }/ J$ h9 [# d
  1. /*
    9 s& p+ s+ U5 T9 f
  2.     FLASH中内嵌小字库,只包括本程序用到的汉字点阵# q7 S0 O  f* `
  3.     每行点阵数据,头2字节是汉子的内码,后面是16点阵汉子的字模数据。
    " t# y8 w1 r: c
  4. */% Z- b4 p) r4 G9 d3 h9 R
  5. ! U' W0 v" P9 L8 X1 Z3 ?1 `6 A
  6. #ifdef USE_SMALL_FONT
    0 u3 S  W3 T; c8 |& M. {# S

  7. 2 C; J" j; \/ j/ D- |3 w# G: C
  8. unsigned char const g_Hz16[] = {6 V# q2 `8 G, t4 S* l

  9. + q  z/ b( |7 R7 r2 S, ~
  10. 9 y5 o/ H# ~9 _- ^

  11. $ I) H1 h: s9 x# |. d. O
  12. 0xA1,0xA1, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//   //% m/ X! k. P# s) F: H. ~
  13.            0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,2 U, h4 J0 D5 {
  14. 7 ?: T- R4 E& i% a$ z9 x3 v. `  {) ]
  15. ) D8 l3 C) A8 K$ R! h
  16. 0xA1,0xA2, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,// 、 //" ^3 |8 t9 f; ]
  17.            0x00,0x00,0x00,0x00,0x20,0x00,0x18,0x00,0x0C,0x00,0x04,0x00,0x00,0x00,0x00,0x00,
    $ r3 X" f4 h  }  \3 r" }; O
  18.   x) ]; T, V8 j7 h

  19. % L: a& A5 X. S+ Y8 N
  20. 0xA1,0xA3, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,// 。 //
    ! ?8 p, u7 j5 \: s2 M, O
  21.            0x00,0x00,0x00,0x00,0x18,0x00,0x24,0x00,0x24,0x00,0x18,0x00,0x00,0x00,0x00,0x00,0 N/ }: n3 P1 O7 ~- [8 F4 b

  22. 6 }0 {% s* j9 t# L1 N5 a. p# o
  23. /* 中间部分省略未写 */
    ( l2 Q3 w& w; v! G1 c& S
  24. 4 O5 o" p, F+ |( S
  25. 0xF7,0xFB, 0x20,0x0E,0xCE,0xF0,0x82,0x22,0xEE,0x92,0x82,0x44,0x82,0x20,0xFE,0x44,0x00,0xF8,// 鼷 //
    1 z3 Z/ I( V! m# t1 C- u7 O
  26.            0x92,0x10,0x92,0x24,0xDA,0xFE,0x92,0x10,0xDA,0xFE,0x92,0x28,0x93,0x44,0xD9,0x82,* @8 R4 t- L5 W& l% z8 E

  27. . W4 I8 B3 E' f, `9 ~

  28. / Q6 d1 O) e6 C# \( J
  29. 0xF7,0xFC, 0x10,0x20,0x3E,0x20,0x22,0x20,0x3E,0x20,0x22,0xF8,0x3E,0x28,0x00,0x28,0x7F,0x28,// 鼽 //% K( Y3 V9 H  n7 h2 z# }3 z3 @+ B
  30.            0x49,0x28,0x7F,0x28,0x49,0x28,0x7F,0x2A,0x00,0x2A,0xFF,0xCA,0x22,0x46,0x42,0x80,8 l5 n. b* `- D. C8 |
  31. 1 B$ }9 p* g  p' j1 ?

  32. % h  p0 Q( I0 X
  33. 0xF7,0xFD, 0x10,0x00,0x3E,0x00,0x22,0x7C,0x3E,0x10,0x22,0x10,0x3E,0x10,0x00,0x10,0x7F,0x10,// 鼾 //
    " m- b6 H' Z- w8 k
  34.            0x49,0xFE,0x7F,0x10,0x49,0x10,0x7F,0x10,0x00,0x10,0xFF,0x90,0x22,0x10,0x42,0x10,
    $ ^: P; s2 y) @' Z7 O5 a% a/ K

  35. 8 J2 {" y; ~$ g* r1 U
  36. , z7 D' A& O9 ~  S3 h
  37. 0xF7,0xFE, 0x10,0x10,0x3E,0x10,0x22,0xFE,0x3E,0x38,0x22,0x54,0x3E,0x92,0x00,0x00,0x7F,0x7C,// 齄 //
    % V* ~: b/ |& t# A4 u3 [
  38.            0x49,0x44,0x7F,0x7C,0x49,0x44,0x7F,0x7C,0x00,0x44,0xFF,0x80,0x22,0xFE,0x42,0x00,8 n& c; f+ l# k5 o$ l& J
  39. : E! |3 Z  `* u. F% s+ V; A0 p
  40. / J9 D( S& V  P  V0 b- I
  41. /* 最后一行必须用0xFF,0xFF结束,这是字库数组结束标志 */. t$ u: n" S! v" k0 l
  42. 0xFF,0xFF
    : n0 A7 }6 r9 H4 w* _# K! _! P
  43. ) n4 ^4 S* [6 `' ?3 G
  44. };
    % n1 r6 D- S5 i: k4 b$ Y
  45. ; u5 ?$ B, W. X% j3 L
  46. #else, J& F* B# T! u: [' s6 }
  47.     unsigned char const g_Hz16[] = {0xFF, 0xFF};
    ; F2 j8 [- `& W+ h
  48. #endif
    9 u4 g) l) ^! ?  j- `
  49. 4 _  y. @) `! N0 m. K7 i+ M" i) X3 c
复制代码

; Q7 N8 @# P8 }- X+ Q添加完毕点阵数据后,在font.h文件里面使能宏定义:
/ W& Z' F0 S6 ^6 e6 I0 \4 I1 a% m7 _& z& E: b  i% O
#define USE_SMALL_FONT     /*这个宏只在bsp_tft+lcd.c中使用 */
& Z8 k" o. c$ g% j  S
  A4 G8 _: z' P4 O至此就完成了全字库的汉字添加,用户就可以使用16点阵的汉字了。: i' _9 `, m8 u& \
/ k+ \8 W) U2 Y: ?; D
53.4 C文件格式汉字使用方法
. A1 h7 ], V$ T/ y汉字的显示方法比较简单。9 k% j( F, t5 a- W( |

, _; ~9 F" V: q' z4 J2 m  定义一个FONT_T类型变量:' r0 M3 {" E# M2 u
  1. FONT_T tFont12;        /* 定义一个12点阵字体结构体变量,用于设置字体参数 */
    : V) |# N7 v+ w( v
  2. FONT_T tFont16;        /* 定义一个16点阵字体结构体变量,用于设置字体参数 */
    ! ~) k: v1 U9 {+ K+ Y  p+ n3 I
  3. FONT_T tFont24;        /* 定义一个24点阵字体结构体变量,用于设置字体参数 */
复制代码
3 i/ O% X. L1 z; j3 S0 F

0 e( Z' v; L0 f( @1 P6 M
8 F7 q) g' ^; rFONT_T的原始定义如下:
5 u7 T; j7 |  h+ [( r' x8 V+ e1 J5 p) L+ h
  1. typedef struct
    . y/ _3 k! y6 G
  2. {2 L( H/ `4 t: P/ J. _
  3.     FONT_CODE_E FontCode;    /* 字体代码 FONT_CODE_E  */
    - v0 X) R" J% t. N! e; b5 n. M
  4.     uint16_t FrontColor;   /* 字体颜色 */# ~; B$ D( g6 E3 R
  5.     uint16_t BackColor;    /* 文字背景颜色,透明 */& t/ T. t8 ]$ z/ `- X
  6.     uint16_t Space;        /* 文字间距,单位 = 像素 */
    2 g5 o, ]- h3 N' X; R, E
  7. }FONT_T;
复制代码
* X) s' l$ {* K# L( q  [

7 m* Z" b$ ?0 o' R3 D9 {) g
6 V5 a- L8 Y7 m; s6 A  初始化变量tFont:% h' m, r! Y$ [
设置12,16和24点阵。
* e4 t, f: c- ~3 d3 ]- S1 a
3 p3 f4 R0 X# S+ ^4 I
  1. /* 设置字体属性 */
    9 a, S; B/ _' ^2 R  r1 Y# i
  2. tFont.FontCode = FC_ST_12;        /* 字体选择宋体12点阵,高12 x宽11) */3 ?( w2 x7 L4 c# k0 m8 U& t
  3. tFont.FrontColor = CL_WHITE;    /* 字体颜色设置为白色 */
    1 [. k9 x# A6 G, V, I' r' U
  4. tFont.BackColor = CL_MASK;         /* 文字背景颜色,透明 */
    / e! l7 y6 L4 B" \# b4 |0 y: M
  5. tFont.Space = 0;                /* 字符水平间距, 单位 = 像素 */
    ! C- _7 r1 b( E% n9 t7 d

  6. + a. Y, @) z( {; w9 q) K' Q* \/ n
  7. tFont.FontCode = FC_ST_16;        /* 字体选择宋体16点阵,高16 x宽15) */- ~) P# T6 O* m, A: Z* B' p% M
  8. tFont.FrontColor = CL_WHITE;    /* 字体颜色设置为白色 */
    7 O- ~. \0 Q. q
  9. tFont.BackColor = CL_MASK;         /* 文字背景颜色,透明 */4 M2 ]* Y  q- J0 Q: }/ C" l
  10. tFont.Space = 0;                /* 字符水平间距, 单位 = 像素 */! K) _+ a4 c# H9 i
  11. & |* C! R7 V$ B3 u! M! E
  12. tFont.FontCode = FC_ST_24;        /* 字体选择宋体24点阵,高24 x宽23) */
    6 \8 t! v) o8 k) M9 ~
  13. tFont.FrontColor = CL_WHITE;    /* 字体颜色设置为白色 */
    3 [1 n3 C2 U' `8 Z/ R
  14. tFont.BackColor = CL_MASK;         /* 文字背景颜色,透明 */
    # Z" ^, c4 ~& u8 |& O" j; v
  15. tFont.Space = 0;                /* 字符水平间距, 单位 = 像素 */
    " }  p. E) d4 V2 Z! G$ P! @8 v
复制代码
# y; L( H7 h& {! V. w( c) {- e
  y, V' ?6 F3 y1 W- m
  调用函数LCD_DispStr显示字符:" C- U& l0 T# Y8 O3 j
下面显示了12,16和24点阵字符。
6 n# M: o" h7 C4 \2 h
0 I1 B; c% Y& m
  1. LCD_DispStr(5, 3,  "故人西辞黄鹤楼,烟花三月下扬州。<a href="http://www.armfly.com" target="_blank">www.armfly.com</a>", &tFont12);
    ) L# t9 K" e: ]: g! ]; X
  2. LCD_DispStr(5, 20, "孤帆远影碧空尽,唯见长江天际流。<a href="http://www.armfly.com" target="_blank">www.armfly.com</a>", &tFont12);
    / V# }; e- i; l5 a* z
  3. LCD_DispStr(5, 38, "故人西辞黄鹤楼,烟花三月下扬州。", &tFont16); / B) W% ]4 W1 {9 P; \# r8 `- N
  4. LCD_DispStr(5, 68, "孤帆远影碧空尽,唯见长江天际流。", &tFont16);
    2 _% P2 X8 C  `9 H2 a  P+ |
  5. LCD_DispStr(5, 98, "故人西辞黄鹤楼烟花三月下扬州", &tFont24);
    9 T5 q0 A" n  F
  6. LCD_DispStr(5, 128, "孤帆远影碧空尽唯见长江天际流", &tFont24);
复制代码

& z' U0 W) }; J2 h8 f3 F2 W& {& ?# u2 g; \8 v8 A1 p" U
& x2 U6 ~& \2 h; s0 Q- D
53.5 汉字显示方法解析
6 M$ J* a) _: a6 I2 q下面将汉字的显示流程做个说明,几个函数的调用关系如下:
8 C* I- j* a( Z
8 i# H! X2 m5 C3 vLCD_DispStr ----> LCD_DispStrEx ----->_LCD_ReadAsciiDot
2 ~6 @. I6 b1 _& f
  I& z; c3 F5 K# @_LCD_ReadHZDot
. R6 I8 K6 Q  l9 ]9 S/ ^1 x
& w* H9 M4 p: e- m  ^53.5.1 函数LCD_DispStr; K% y4 }. v9 H2 ^, N: X
中英文显示都是调用的如下函数实现:  x( c/ i/ o5 ]0 E

/ Z: [/ p' o/ ?7 T" O2 q7 |
  1. /*# h% M  I7 P  b" o
  2. *********************************************************************************************************
    ! D( B* q8 T6 y+ u0 ]
  3. *    函 数 名: LCD_DispStr
    5 m+ n+ |2 V6 w& T: a- ^; Z
  4. *    功能说明: 在LCD指定坐标(左上角)显示一个字符串9 ?7 S% o' P; _, k) Z: b5 `
  5. *    形    参:
    0 b% \) P! k: y3 J0 Z
  6. *        _usX : X坐标1 i* N# o" b7 T7 r
  7. *        _usY : Y坐标
    ! A7 C* k. f& T: r
  8. *        _ptr  : 字符串指针  `) N  h: {5 [8 z
  9. *        _tFont : 字体结构体,包含颜色、背景色(支持透明)、字体代码、文字间距等参数3 G* o5 g$ P6 ~* f$ m/ k0 D
  10. *    返 回 值: 无7 i0 I6 f: Q: _$ B- ?& |0 [
  11. *********************************************************************************************************  I/ r5 M+ \$ @
  12. */
    - i0 \/ c5 N; E' x
  13. void LCD_DispStr(uint16_t _usX, uint16_t _usY, char *_ptr, FONT_T *_tFont)
    # X9 d: \( z! {/ m
  14. {" E+ a8 K9 c! M( k4 `
  15.     LCD_DispStrEx(_usX, _usY, _ptr, _tFont, 0, 0);$ F" L* o1 ?% _6 r
  16. }
    4 A, J8 u' L3 i

  17. . U% N1 S+ ~  c2 h
复制代码

+ C. O7 G3 h) c2 {( W# ^这个函数的注释已经比较详细,这里就不再赘述了。而这个函数是通过调用LCD_DispStrEx实现。
' V' v$ s0 {$ K+ W
  l5 k- }# X( L) i, ]$ C& v53.5.2 函数LCD_DispStrEx
! _- v8 [- Q; r此函数的源码如下:/ z7 E' r7 _# a
  ?4 d5 p, W# Y1 y: u
  1. 1.    /*/ ^9 n; }1 w. ~) W, i
  2. 2.    ******************************************************************************************************
    5 Q- e7 h/ F3 H( o, y0 w
  3. 3.    *    函 数 名: LCD_DispStrEx
    ( C7 T5 e6 x; Q' J: }# z( K( h5 s
  4. 4.    *    功能说明: 在LCD指定坐标(左上角)显示一个字符串。 增强型函数。支持左\中\右对齐,支持定长清屏。8 j0 E& B  q! {( b6 v
  5. 5.    *    形    参:- N4 E' _$ }$ w( S8 @7 o8 E
  6. 6.    *        _usX : X坐标4 i7 Z/ S3 B$ |! J' T
  7. 7.    *        _usY : Y坐标
    . O2 l) n, Q! M; r
  8. 8.    *        _ptr  : 字符串指针9 o. w& f/ A# {3 }8 {. k8 Y
  9. 9.    *        _tFont : 字体结构体,包含颜色、背景色(支持透明)、字体代码、文字间距等参数。可以指定RA8875字库" V* z# S2 h" m2 Z; G& `
  10. 10.    *                 显示汉字。3 \& H8 w3 Y' E7 P3 A
  11. 11.    *        _Width : 字符串显示区域的宽度. 0 表示不处理留白区域,此时_Align无效
    5 ^! b0 K& I: e# P! @. y
  12. 12.    *        _Align :字符串在显示区域的对齐方式,
    / l& R, y: I8 r; g
  13. 13.    *                ALIGN_LEFT = 0,- C& i+ h+ ]( u7 A7 B
  14. 14.    *                ALIGN_CENTER = 1,
    : R4 M* Q+ q/ S: a6 d' L4 [- M
  15. 15.    *                ALIGN_RIGHT = 2
    * Q  ~9 z* D" M' ~
  16. 16.    *    返 回 值: 无
    ' a2 \3 z1 L) l$ I3 s
  17. 17.    ******************************************************************************************************1 U/ \* o8 L) v% c. P" G8 T
  18. 18.    */
    - r% ?; Y" R. J
  19. 19.    void LCD_DispStrEx(uint16_t _usX, uint16_t _usY, char *_ptr, FONT_T *_tFont, uint16_t _Width,& w4 ^* X9 s4 h' E7 L& |3 s$ T4 ]
  20. 20.        uint8_t _Align)
    * M+ @1 }5 C% x: `0 a5 s
  21. 21.    {
    1 }4 ?2 X! t, g- r4 k  j
  22. 22.        uint32_t i;8 T  i8 |* y/ j( y+ z! m
  23. 23.        uint8_t code1;/ S5 ]6 d1 \( u
  24. 24.        uint8_t code2;
    , I" B- }  L/ j/ u
  25. 25.        uint8_t buf[32 * 32 / 8];    /* 最大支持32点阵汉字 */! k6 R" C/ k2 _6 \! s
  26. 26.        uint8_t width;
    3 A9 `( s* v& n: O* C/ ]8 T
  27. 27.        uint16_t m;
    ( f, L/ s* y2 g& c8 ?5 }0 ]. n
  28. 28.        uint8_t font_width = 0;( D6 `+ h" e- d: n) ^( {
  29. 29.        uint8_t font_height = 0;
    - k7 v$ S+ X% O3 j
  30. 30.        uint16_t x, y;) {# }& c8 C0 p* B3 J7 ^
  31. 31.        uint16_t offset;
    & I8 ?. t7 b) u9 }# q$ G$ d
  32. 32.        uint16_t str_width;    /* 字符串实际宽度  */) {' h5 y3 ]; ]
  33. 33.   
    9 t; y& ~. x* S. s  f+ \/ w$ j
  34. 34.        switch (_tFont->FontCode)
      y( y4 V1 a0 p! T! k
  35. 35.        {
    3 S, |' U6 V; i. Q7 \* T0 E
  36. 36.            case FC_ST_12:        /* 12点阵 */
      I5 E: D$ r! \
  37. 37.                font_height = 12;
    5 l+ g- |& I* `4 M% V) Y5 @
  38. 38.                font_width = 12;2 [9 f. C1 B6 [) O
  39. 39.                break;0 e* \+ T6 G. {2 e
  40. 40.            
    1 }/ ~& Z4 |5 u8 v. J' A+ [
  41. 41.            case FC_ST_16:& M$ u9 k/ t7 u$ X) Z
  42. 42.                font_height = 16;, H1 @. ]8 n7 }/ T& a2 [' N/ ?
  43. 43.                font_width = 16;& G! ]8 @7 J7 _- m! r" D+ I3 o
  44. 44.                break;
    ( V) F+ q' L* N4 J- o
  45. 45.   
    9 Z0 g8 S% {7 i& e, g
  46. 46.            case FC_ST_24:2 ?" M! W9 T4 @) T6 y9 c: \' k
  47. 47.                font_height = 24;
    " t4 K) H7 T' K
  48. 48.                font_width = 24;
    1 j  C$ P. E# c" [5 h
  49. 49.                break;% K; T* |8 C! Z1 z2 h
  50. 50.                            $ Y& U& H6 m2 d# V& N) t
  51. 51.            case FC_ST_32:    7 A! J. k! }  x9 Y+ x3 j
  52. 52.                font_height = 32;% {! f. t8 U. m( P. u' y# N
  53. 53.                font_width = 32;- k  P- L; N, E5 @
  54. 54.                break;                    
    7 r; o; w/ G* a% F
  55. 55.        }
    # ~2 W! I& v, j2 s% @1 x( L
  56. 56.        
    7 T1 g. C+ }" e
  57. 57.        str_width = LCD_GetStrWidth(_ptr, _tFont);/* 计算字符串实际宽度(RA8875内部ASCII点阵宽度为变长 */4 \) j& l* C# t. ^# J) s
  58. 58.        offset = 0;9 k% s; }) Q! b
  59. 59.        if (_Width > str_width)
    ' q+ m% `, [4 p
  60. 60.        {
    ' [+ f( J1 m8 c. T0 J3 W) k
  61. 61.            if (_Align == ALIGN_RIGHT)    /* 右对齐 */
    . p& f" t: J0 G* @- n% x
  62. 62.            {
    . ~3 c0 y0 p0 _) E8 R4 N
  63. 63.                offset = _Width - str_width;
    ! l( o& O* g- U' ^' y9 ?" H" E- {- h
  64. 64.            }/ G; |% l! ]" y- B
  65. 65.            else if (_Align == ALIGN_CENTER)    /* 居中 */4 r7 `% }! T: W, C5 ]
  66. 66.            {7 k- v- z" o7 }+ e; Q
  67. 67.                offset = (_Width - str_width) / 2;
    5 g* `( s3 M* I0 L- m
  68. 68.            }" a) u9 b% E9 d
  69. 69.            else    /* 左对齐 ALIGN_LEFT */
    ( @1 Q) |& |; a/ o  P
  70. 70.            {
    0 Z2 Y3 `) w, q" L& `! R4 M
  71. 71.                ;5 S8 L. s2 F4 ?1 h
  72. 72.            }7 n+ l: ?- k! f# ?
  73. 73.        }
    - A& ]& I! T( Z" Q7 |$ r
  74. 74.   
    5 T3 o4 R4 F: ^6 P3 Z1 d4 @
  75. 75.        /* 左侧填背景色, 中间对齐和右边对齐  */& I% F" m2 `0 a- d" X- u  C
  76. 76.        if (offset > 0)
    : P% t& b, T" w0 C
  77. 77.        {  M' ~" t) O' W& d! @* @
  78. 78.            LCD_Fill_Rect(_usX, _usY, LCD_GetFontHeight(_tFont), offset,  _tFont->BackColor);" U% u' `& }+ t( a
  79. 79.            _usX += offset;
    - X+ t/ R7 `4 p' B( V: H
  80. 80.        }
    * P& f% U1 Q1 C' e
  81. 81.        ( u/ g- s2 C& x; _4 W! j2 H
  82. 82.        /* 右侧填背景色 */
    0 O. d, J) M0 E: g4 Q! i, `
  83. 83.        if (_Width > str_width)
    + l5 @: n% N: L- `# q! v- d
  84. 84.        {
    , H& F0 R6 l) N2 }1 G6 V
  85. 85.            LCD_Fill_Rect(_usX + str_width, _usY, LCD_GetFontHeight(_tFont), _Width - str_width - offset,# P( o2 P: r4 ^7 Y
  86. 86.                            _tFont->BackColor);1 c8 Z$ @2 E8 T: ]  f4 l% D# o+ U
  87. 87.        }
    0 B( S+ |2 f7 H2 u4 B* ~: j' J
  88. 88.        " L2 h3 w. D% n& }. y7 y* v/ A$ n
  89. 89.        /* 使用CPU内部字库. 点阵信息由CPU读取 */3 \. `5 j' l6 V; X# M) H# _
  90. 90.        {
    , b6 \8 A7 D" A
  91. 91.            /* 开始循环处理字符 */
    1 j2 x5 ]& C" O' y! i( q4 C% E
  92. 92.            while (*_ptr != 0)9 |) m& p; J2 m/ _: i' Q! K9 G
  93. 93.            {
    ( j- Z0 A  f. l  x. ?
  94. 94.                code1 = *_ptr;    /* 读取字符串数据, 该数据可能是ascii代码,也可能汉字代码的高字节 */
    5 m1 d# _. X, P$ P6 n2 o
  95. 95.                if (code1 < 0x80)  m9 H, ^, x+ `# j
  96. 96.                {" z/ ]- S2 s! h4 I3 o% k
  97. 97.                    /* 将ascii字符点阵复制到buf */
    % [3 S# h2 d9 h& M
  98. 98.                    //memcpy(buf, &pAscDot[code1 * (font_bytes / 2)], (font_bytes / 2));6 D* e% H+ a7 J
  99. 99.                    _LCD_ReadAsciiDot(code1, _tFont->FontCode, buf);    /* 读取ASCII字符点阵 */! `5 a" }+ Q4 j+ y9 `
  100. 100.                    width = font_width / 2;5 v" g  R* c5 ?$ V5 j
  101. 101.                }
    . }# D- k5 j5 x6 |9 ~6 }
  102. 102.                else
    1 d8 O" _0 n( V7 ~& G5 o/ Z: f
  103. 103.                {4 ~) }0 I3 d. Z& b) `6 C
  104. 104.                    code2 = *++_ptr;+ Z/ \7 v) o9 i' h# ?! `( G$ ~
  105. 105.                    if (code2 == 0)6 _4 w' t9 N5 T
  106. 106.                    {; M8 w" P* Z9 b% I) j! Z
  107. 107.                        break;
    7 x: \8 h4 t7 O! S, {1 n/ D
  108. 108.                    }
    1 K( l9 G% u* a: U$ M0 k3 F
  109. 109.                    /* 读1个汉字的点阵 */
    # A! D; C8 u6 y$ Y7 s
  110. 110.                    _LCD_ReadHZDot(code1, code2, _tFont->FontCode, buf);2 {3 A+ s: `  i2 A" B
  111. 111.                    width = font_width;0 W# }1 f' T) O
  112. 112.                }) p6 [! P& D5 r: G2 H0 I( Z4 \
  113. 113.        
    0 J6 e5 W. F+ A" Q
  114. 114.                y = _usY;6 [8 F# S# q# l2 a
  115. 115.                /* 开始刷LCD */" d1 C( r# K9 a& `0 j
  116. 116.                for (m = 0; m < font_height; m++)    /* 字符高度 */
    ; {# H+ ~0 i1 i6 U) \/ b
  117. 117.                {$ q3 l, X1 P1 D  ?9 k) g% g
  118. 118.                    x = _usX;4 F, B  O) S/ Y
  119. 119.                    for (i = 0; i < width; i++)    /* 字符宽度 */2 f) v) a$ n: D3 w# y& E, }4 X
  120. 120.                    {
    ) l' h1 g" f0 I/ _, P; K
  121. 121.                        if ((buf[m * ((2 * width) / font_width) + i / 8] & (0x80 >> (i % 8 ))) != 0x00)( W2 w5 ]8 D  q* v* Z
  122. 122.                        {0 Q2 L0 W/ E1 U! q1 @: u  X
  123. 123.                            LCD_PutPixel(x, y, _tFont->FrontColor);    /* 设置像素颜色为文字色 */9 `% O* u7 [5 n% h, e! S! T8 g( D
  124. 124.                        }
    - `3 Q) M1 c6 e5 ?/ q2 w7 G
  125. 125.                        else
    6 j* n% @5 v( `1 L
  126. 126.                        {% |$ M; G" t! C$ X2 f
  127. 127.                            if (_tFont->BackColor != CL_MASK)    /* 透明色 */
    ( Q. w. }- U$ \2 h" p. _  J3 I
  128. 128.                            {
    6 V& {7 C7 c6 Q; X- c
  129. 129.                                LCD_PutPixel(x, y, _tFont->BackColor);/* 设置像素颜色为文字背景色 */  Z& |, I4 I& O' B5 i
  130. 130.                            }, P+ F% o0 H. s1 d- ~. p
  131. 131.                        }
    & j# S9 n/ C9 }; m
  132. 132.        
    4 Q  m( Q# Q/ D2 [1 x' ~
  133. 133.                        x++;
    ; y  Z. r) v8 b0 e3 w  Q
  134. 134.                    }! L1 n  Y2 H, Q' ^, V. @
  135. 135.                    y++;! |6 }! I" T1 p& P, a- y
  136. 136.                }+ {, g- E" g2 \8 B5 Y
  137. 137.        
    7 S0 h; p; B/ k' X( K* g
  138. 138.                if (_tFont->Space > 0)- j/ E( p+ L# w2 t& B/ C
  139. 139.                {6 I: T- [4 c% t
  140. 140.                    /* 如果文字底色按_tFont->usBackColor,并且字间距大于点阵的宽度,那么需要在文字之间填# W0 s/ y' p7 ~3 {5 t: S* n* [  P
  141. 141.                          充(暂时未实现) */0 x* x: g! y& Z8 h2 Q
  142. 142.                }
    - j- R. H+ P+ @1 Z
  143. 143.                _usX += width + _tFont->Space;    /* 列地址递增 */* K% c0 }' T4 U& e% y( M5 e% J
  144. 144.                _ptr++;            /* 指向下一个字符 */6 e, M1 a0 ?; x2 F- X& i
  145. 145.            }- K( j* K% K. N
  146. 146.        }
    , w2 H5 ], x; H# S$ T( V1 @5 ^* W
  147. 147.    }
复制代码

; c5 `# G' H" D3 ?% r0 c6 s下面将代码中几个关键地方做个阐释:
4 [  n2 j- ~. {
5 h8 r; g# n2 D8 I9 c" f) \( p: a7 g  第34-55行,根据使用的的12,16,24和32点阵字体,设置字体的高度变量font_height和宽度变量font_width。% Q2 v6 `5 L9 R8 G. }7 ~
  第57-73行,通过函数LCD_GetStrWidth计算字符串的长度,然后根据设置的字符总宽度和实际宽度做比较,来实现左对齐,右对齐和居中显示。由于函数LCD_DispStr调用LCD_DispStrEx时,将形参_Width设置为0,所以这部分代码功能未用到。! R2 v% L, A, T8 D  Z$ _- Z# a
  第76-87行,用于填充显示字符以外区域的背景色,只有设置的字符总宽度大于实际宽度时才会用到,填充的就是实际宽度以外的区域。
1 e1 F5 k! R5 X! A* G9 |4 ?. V  第90-146行,显示所有字符。" G/ A2 J" `( z9 T0 [
  第95行,如果编码值小于0x80,表示ASCII字符。
1 t# o  T# P( ]0 x: D  s  第99行,根据编码值读取ASCII值对应的点阵数据到数组buf里面。
8 g7 k! U* ]1 `  第100行,显示ASCII字符仅需要一半宽度即可,比如显示12*12点阵字符,显示成ASCII仅需6*12即可。3 H* @: V6 k7 P! X3 T5 i" G
  第102行,如果编码值大于等于0x80,汉字编码在这个范围。
" k3 V4 y" Y/ n- D1 u0 T( b1 Q4 r  第104行,因为GB编码需要两个字节表示,所以这里再读取一个字节。
! _) c+ j( }0 W6 T& n6 g0 t* h/ y  第110行,根据汉字编码值对应的点阵数据到数组buf里面。$ \6 Q7 b& W  p, Q" q2 {
  第116-136行,采用从左到右,从上到下的方式刷新字符。这里特别注意点阵数据位置的获取:buf[m * ((2 * width) / font_width) + i / 8] & (0x80 >> (i % 8 ), V; V2 D' X: Z: A) c, k
对于这个公式,大家通过代数法,代入两次数值就好理解了。7 D' @1 k+ i1 {1 d' {8 M- S
0 C$ w  `/ K, ?- A5 Y
53.5.3 函数_LCD_ReadAsciiDot) E. y0 t/ [" |) ]# u) ]' b. S0 L
此函数的作用是根据ASCII编码值,读取对应的点阵数据出来。0 N/ P: }) ]" }7 w
1 A$ o7 c! {# Y
  1. 1.    /*7 o% D/ `! w  v; U
  2. 2.    ******************************************************************************************************
    . w/ E9 S5 l5 M; J8 W$ c
  3. 3.    *    函 数 名: _LCD_ReadAsciiDot3 @5 ~, K8 ]* Y9 x8 n% Y- v
  4. 4.    *    功能说明: 读取1个ASCII字符的点阵数据$ j6 S, p/ n2 ~; R* a
  5. 5.    *    形    参:
    1 k% u" n, t! |  L, A! u
  6. 6.    *        _code : ASCII字符的编码,1字节。1-128
    * B' ~7 {+ ^, V; Y+ x
  7. 7.    *        _fontcode :字体代码! h; R  X# ?9 K
  8. 8.    *        _pBuf : 存放读出的字符点阵数据
    8 m' i- o5 e8 |4 Z
  9. 9.    *    返 回 值: 文字宽度
    % P4 |8 c7 S. J3 h+ e% m
  10. 10.    ******************************************************************************************************4 ]& d7 @% Q2 P
  11. 11.    */7 ?# c9 ^4 l4 D' s7 T/ [% ]$ P" V. _
  12. 12.    static void _LCD_ReadAsciiDot(uint8_t _code, uint8_t _fontcode, uint8_t *_pBuf)
      ~% r- U$ @8 g
  13. 13.    {
    * S$ v7 h6 m& X6 Q, L9 h
  14. 14.        const uint8_t *pAscDot;. c; [" H2 }- C0 |1 A
  15. 15.        uint8_t font_bytes = 0;; {5 e0 a* ~6 D& x) p
  16. 16.    % o# c& H0 f( \# i9 C) U) X9 J
  17. 17.        pAscDot = 0;8 R7 u' P) s0 i
  18. 18.        switch (_fontcode)$ L3 ?( i8 ]+ o5 o, u6 B. C) }
  19. 19.        {2 j( m# N3 Z* I
  20. 20.            case FC_ST_12:        /* 12点阵 */" }+ w3 f! h, J  b+ A1 h# R
  21. 21.                font_bytes = 24;
    : i7 R; j0 ^9 _% K: ^8 h) f
  22. 22.                pAscDot = g_Ascii12;   
    . T- q/ F2 z; P2 x) R, [
  23. 23.                break;
    * `" Z' M- \  _( ~% Y
  24. 24.            8 i( C+ Y/ c0 a# l4 o
  25. 25.            case FC_ST_24:
    " T: q" g+ z: w' t
  26. 26.            case FC_ST_32:
    6 ~  D8 E% t, `; {" n. m
  27. 27.            case FC_ST_16:: o+ [  p7 p, Z9 t$ i4 |/ G
  28. 28.                /* 缺省是16点阵 */$ H' f, h0 g$ Q" N* J. ~
  29. 29.                font_bytes = 32;. M& B/ r6 k! j& i9 E" {4 o
  30. 30.                pAscDot = g_Ascii16;
    % d4 W0 _. p6 V+ t+ C) N" j* p
  31. 31.                break;
    1 q/ [! \  k/ j% u
  32. 32.            : S2 ^# n  ^. `: `' W' o: b7 B
  33. 33.            case FC_RA8875_16:
    # ]  t) X) B, s# I( F6 y
  34. 34.            case FC_RA8875_24:
      ?, P8 A, [( w$ R- l* e2 [
  35. 35.            case FC_RA8875_32:
    , Z  [: O* U3 p7 _
  36. 36.                return;
    ; m$ {6 D6 e0 O4 S3 i  e! @
  37. 37.        }   
    ( J' @/ z( T; R& d& T
  38. 38.    / j' M8 ~5 \+ _, k6 }
  39. 39.        /* 将CPU内部Flash中的ascii字符点阵复制到buf */
    * Z9 a. q- J3 y0 ~# }& z; s! I
  40. 40.        memcpy(_pBuf, &pAscDot[_code * (font_bytes / 2)], (font_bytes / 2));   
    6 L- x5 t& d( ?  W6 O
  41. 41.    }8 j8 ~2 Y6 U' i- Y) j) o- \
复制代码

  ~" T8 n' h- p, y
1 h, _# m! ?) z( l4 g3 U. y下面将此函数涉及到的知识点为大家做个阐释:
/ D" T8 u2 m" P
+ j: Z( o' I+ {  第20-23行,显示12点阵ASCII,每个字符需要24个字节,存储在数组g_Ascii12里面。
- k7 \9 }$ w4 j, j6 j  第25-31行,显示16,24和32点阵ASCII,这里采用同一大小字符进行显示。每个字符需要32个字节,存储在数组g_Ascii16里面。
6 e" F7 w7 L  M7 {' y  第33-35行,这个是RA8875的字库处理,V7开发板用不到。
- h* u7 P, {7 E+ ]  第40行,将ASCII点阵数据复制到缓冲_pBuf里面。
+ [8 I) A/ ^7 |! Y& M' n53.5.4 函数_LCD_ReadHZDot0 m  H( z; G' T
此函数的作用是根据ASCII编码值,读取对应的点阵数据出来。
2 t5 T1 }' x. F- ^; j& F0 e4 H* ]7 I- ]4 d6 N
  1. 1.    /*
    7 x2 @! K; L( a4 T8 G6 R0 W
  2. 2.    ******************************************************************************************************7 Z  S' n% i/ _8 V6 z; l6 f
  3. 3.    *    函 数 名: _LCD_ReadHZDot
    7 i5 ~8 O9 F/ A! r/ F8 ?7 Y
  4. 4.    *    功能说明: 读取1个汉字的点阵数据
    , B' Z# g2 D2 u+ `, q1 T( d
  5. 5.    *    形    参:
    6 V' i+ t( e* p
  6. 6.    *        _code1, _cod2 : 汉字内码. GB2312编码/ s" P& s! y( k. s0 ?8 B
  7. 7.    *        _fontcode :字体代码
    , p% x4 k$ ~% X$ R& R
  8. 8.    *        _pBuf : 存放读出的字符点阵数据8 a9 w3 o$ q" K- H
  9. 9.    *    返 回 值: 无
    , W* L& u+ R0 y( C9 f
  10. 10.    ******************************************************************************************************6 h9 q! k7 T8 c( D$ f. }" Z# k
  11. 11.    */  l5 ?9 E& T) {  x
  12. 12.    static void _LCD_ReadHZDot(uint8_t _code1, uint8_t _code2,  uint8_t _fontcode, uint8_t *_pBuf)$ y& j. \0 Q5 v4 b+ f, l# I- D+ }
  13. 13.    {
    : N! t  w# ^# [6 F! p0 a
  14. 14.        #ifdef USE_SMALL_FONT    /* 使用CPU 内部Flash 小字库 */2 x+ C5 V$ I$ F2 A  @9 {, N
  15. 15.            uint8_t *pDot;
      q* P0 ?! j5 z) j% q0 l
  16. 16.            uint8_t font_bytes = 0;3 Y+ @/ T7 J3 \, U# v  h* R! L
  17. 17.            uint32_t address;
    3 g  r  k8 |3 L* i
  18. 18.            uint16_t m;
    8 R6 _) c& T, V* A, m* L1 B
  19. 19.    ' m2 V3 {+ F. e- X
  20. 20.            pDot = 0;    /* 仅仅用于避免告警 */( {. C+ f% v- I& A& z! u
  21. 21.            switch (_fontcode)
    ! A: \: C5 w) n* [6 ?9 L
  22. 22.            {& k7 R1 }8 r: `, `; {
  23. 23.                case FC_ST_12:        /* 12点阵 */$ Y' W, Q& w, Y4 G! P
  24. 24.                    font_bytes = 24;, w* ]& B4 g4 z: R0 F9 z  v
  25. 25.                    pDot = (uint8_t *)g_Hz12;   
    / T! z, v/ a" g/ Z# u' d; ^/ {
  26. 26.                    break;
    " j0 W9 g$ F9 P9 g5 B' z
  27. 27.               
    0 m/ G8 k6 a3 ]# y
  28. 28.                case FC_ST_16:6 Q' E  i( N9 I1 A
  29. 29.                    font_bytes = 32;% p% s$ J0 a4 l7 U
  30. 30.                    pDot = (uint8_t *)g_Hz16;
    . |) d* ?: j9 S) }, I+ S% Y
  31. 31.                    break;
    " Y( J) z* a& O
  32. 32.        
    1 z- N* `5 a3 K+ O. k$ w) B
  33. 33.                case FC_ST_24:+ F( ~* A$ {$ k/ j
  34. 34.                    font_bytes = 72;
    : \1 W; Z7 I4 N& W$ {
  35. 35.                    pDot = (uint8_t *)g_Hz24;
    0 j7 T; O% }1 u, I* G$ O
  36. 36.                    break;            ; Y8 d* I& ~  @
  37. 37.                    
    . [; H8 c3 \# e! v: }+ o* e
  38. 38.                case FC_ST_32:    3 h' q, K" K* V- q
  39. 39.                    font_bytes = 128;" V7 b# {/ ]3 o7 D8 i
  40. 40.                    pDot = (uint8_t *)g_Hz32;
    ) L! w9 {5 N% @9 l4 ?
  41. 41.                    break;                        
    ) O8 `& B7 l* N6 W: {: H4 s
  42. 42.                $ }9 G# z) ^) O/ V) N; ^0 r7 @
  43. 43.                case FC_RA8875_16:
    # n- c; X& d' @
  44. 44.                case FC_RA8875_24:; u, Z) p; g0 s: b9 s. F) O
  45. 45.                case FC_RA8875_32:* X' ^9 i0 G6 D/ P* o
  46. 46.                    return;0 X0 c/ j' ?0 O
  47. 47.            }    7 x- H; H) W9 V8 C. i. p, C
  48. 48.    " ~, M+ X; S, n/ M# X! |
  49. 49.            m = 0;
    8 c& O% q6 S6 N
  50. 50.            while(1)4 S; m0 j" M" g3 Z2 E
  51. 51.            {
    7 T, f1 ?9 T( s4 j  O
  52. 52.                address = m * (font_bytes + 2);
    & B: t' y- x. \0 }6 `% Q
  53. 53.                m++;
    1 Z8 }, z  ~' S+ X6 i8 Q; q
  54. 54.                if ((_code1 == pDot[address + 0]) && (_code2 == pDot[address + 1]))7 ]- n- {5 J0 T1 C! [8 G
  55. 55.                {7 r; l) V% ]3 X3 Q' R/ g) V
  56. 56.                    address += 2;) J# H$ U8 q# x4 p! g
  57. 57.                    memcpy(_pBuf, &pDot[address], font_bytes);; J" H, V5 Z2 g8 q! f, R5 Z* M
  58. 58.                    break;- `1 c# X, h: n- `' e/ k
  59. 59.                }! K3 ^9 [; J& E- |. @+ i1 a1 k
  60. 60.                else if ((pDot[address + 0] == 0xFF) && (pDot[address + 1] == 0xFF))2 l- j9 k, j5 C7 q1 d# P3 c- z  ]3 W& s
  61. 61.                {
    6 f' p* h; q5 t+ s5 U9 g6 w
  62. 62.                    /* 字库搜索完毕,未找到,则填充全FF */
    2 U* @2 T' G* I- E
  63. 63.                    memset(_pBuf, 0xFF, font_bytes);
      I# n( `3 F" @
  64. 64.                    break;
    - w+ h; z9 D; g  J  y9 O
  65. 65.                }
    . R0 @# [4 [& n: G+ c7 l! e) J& p
  66. 66.            }( F" [# }2 }! k  p' l0 L) N
  67. 67.        #else    /* 用全字库 */( d. N) o* b; F8 p% w
  68. 68.            uint8_t *pDot = 0;2 R; t+ K& M! d$ d. M: F  m5 n
  69. 69.            uint8_t font_bytes = 0;
      Z1 R6 ~! _9 O9 G7 w' |6 h- W/ i
  70. 70.                $ z6 H8 z+ d4 Q4 S# {
  71. 71.            switch (_fontcode)
    4 _5 L  V- j5 D
  72. 72.            {
    0 A5 r- e; l7 S, T1 @* x
  73. 73.                case FC_ST_12:        /* 12点阵 */
    - P' u" E. w1 p+ s$ x2 Y5 y' I/ L) H
  74. 74.                    font_bytes = 24;
    . ~; E% i) @0 C7 n6 i* i9 j( y9 ?' [
  75. 75.                    pDot = (uint8_t *)HZK12_ADDR;    ) c. h9 B5 C( e4 n) t7 r
  76. 76.                    break;
    ( R2 K8 e0 X7 z  b
  77. 77.                # I# ]2 E0 \+ S
  78. 78.                case FC_ST_16:& |1 H4 J$ m5 u4 ]" U" p
  79. 79.                    font_bytes = 32;0 s3 s  j! \, t# s- G& w
  80. 80.                    pDot = (uint8_t *)HZK16_ADDR;
    9 u- N; X/ S9 R  ^  P" X
  81. 81.                    break;
    7 m" m; A. N; l4 d/ G# b5 c0 [
  82. 82.        
    7 t1 i* u& T$ s5 d; O
  83. 83.                case FC_ST_24:$ g% Y& Y- _. A8 a! d
  84. 84.                    font_bytes = 72;
    ; p6 a& k( r% P, d# E0 t# j
  85. 85.                    pDot = (uint8_t *)HZK24_ADDR;' [+ ~7 R! A2 F6 k! H. g* \. [
  86. 86.                    break;            & r7 h7 r3 F) o
  87. 87.                    
    ' u# L% T* [8 U$ f5 W9 @9 b" K
  88. 88.                case FC_ST_32:   
    ' S9 F, A9 Q; a8 I( H
  89. 89.                    font_bytes = 128;
    3 d7 w, T$ S  v
  90. 90.                    pDot = (uint8_t *)HZK32_ADDR;
    5 N( T' C9 w2 E5 U6 ~3 f
  91. 91.                    break;                        
    + |, ?" R! T8 x7 J
  92. 92.               
    5 C% z; l) F5 p' O" i* l4 `3 E
  93. 93.                case FC_RA8875_16:
    $ V9 z. I/ L+ F
  94. 94.                case FC_RA8875_24:
    . C$ I, r, R& B6 f# N& w7 U
  95. 95.                case FC_RA8875_32:
    + y' s4 C6 g* k: W7 N4 N9 s
  96. 96.                    return;
    . |- r& F, o7 l7 m8 d
  97. 97.            }            
    : Q, l" g+ B" J- N! B
  98. 98.        ) ]2 {7 O$ d5 {$ A
  99. 99.            /* 此处需要根据字库文件存放位置进行修改 */
    ) n! U% f9 h4 T0 E! i: I# _1 Y
  100. 100.            if (_code1 >=0xA1 && _code1 <= 0xA9 && _code2 >=0xA1)
    1 v+ `/ N0 J/ J& _& p
  101. 101.            {" ?3 }1 ?+ ~" B# b! R9 e& y- \: L
  102. 102.                pDot += ((_code1 - 0xA1) * 94 + (_code2 - 0xA1)) * font_bytes;" }% W' J* M" D' b3 @6 u
  103. 103.            }6 [3 w! R1 k. S* B( R  u
  104. 104.            else if (_code1 >=0xB0 && _code1 <= 0xF7 && _code2 >=0xA1)
      p) {9 f; ~: W' G; J% H! ]4 U
  105. 105.            {- H% z- G1 X: p" _1 A0 I
  106. 106.                pDot += ((_code1 - 0xB0) * 94 + (_code2 - 0xA1) + 846) * font_bytes;" T3 D- E$ r8 l' ]8 O- _3 C
  107. 107.            }
    ; W$ G- }$ W3 E' a+ O6 \4 M
  108. 108.            memcpy(_pBuf, pDot, font_bytes);- d3 S  E4 X% p) M
  109. 109.        #endif
      g/ r- z# Q: N* ?6 Z& J% _% w+ Y
  110. 110.    }
    - w1 O( j$ |. v" h4 X8 _9 x
复制代码

3 ?: Z4 ]  |% J2 H3 l  V# g0 S* c% {- Y0 L: X4 @* K
下面将此函数涉及到的知识点为大家做个阐释:
0 \1 M  [/ p" H% D5 f" l; u) N
! H2 w4 E) ]# U& z' w/ E$ _  第15-66行,小字库显示,这个方案既可以显示小字库,也可以显示全字库。2 V' ~$ @% z& P7 X0 r: B0 C
  第23-41行,获取12点阵,16点阵,24点阵和32点阵汉字显示需要的字节数以及存储点阵数据的缓冲地址。4 x; E4 o+ _1 G/ @9 a- I0 }
  第49-66行,这里是通过比较汉字的编码值找到点阵数据位置,如果遇到两个0xFF,表示检索到数组末尾了也没有找到汉字点阵数组。找到数据后,将其复制到缓冲_pBuf里面。# s+ ^3 X( _, Y$ w0 R
  第68-108行,本章暂时用不到这种方案,后面章节用到这种方案了再为大家做说明。. t4 K- w) h$ t. C7 \
53.6 LCD驱动移植和使用
' p/ D* ~* U; |5 {与第51章51.7小节相同,这里就不再赘述了。* z' R/ ]. B% D8 S) f' o, _# y
! q7 w+ l; S+ l6 }. X& n8 }
53.7 实验例程设计框架/ w0 L4 y5 N- [, t6 A/ o4 O' m
通过程序设计框架,让大家先对配套例程有一个全面的认识,然后再理解细节,本次实验例程的设计框架如下:
+ e7 u% [$ j# |6 a8 j1 C' Q. j$ a( Y+ N% q8 B: S
aHR0cHM6Ly9pbWcyMDE4LmNuYmxvZ3MuY29tL2NvbW1vbi8xMzc5MTA3LzIwMjAwMi8xMzc5MTA3LTIw.png

" v. A( d2 |- B3 h. V5 C
* F( O& }0 v3 v+ y/ h  第1阶段,上电启动阶段:+ H  B$ D$ J- ?

2 K2 j3 ?- K7 b" T2 q这部分在第14章进行了详细说明。. J5 D4 |0 G1 e
  第2阶段,进入main函数:
. A/ B5 I0 h, }- m; b8 t
% I  a" `/ A! I8 Y  X2 J/ f! h  第1步,硬件初始化,主要是MPU,Cache,HAL库,系统时钟,滴答定时器,LED,串口,LCD,SDRAM等。
: I5 }, F4 j9 S/ a: J" B! |8 F" `  第2步,LCD应用程序设计部分,显示汉字。通过按键实现三种界面的处理,其中GB2312有几十个界面。  A3 ~" z/ f$ P; P) ~# @
53.8 实验例程说明(MDK)9 D+ L4 q+ ?+ \6 _# \1 b* {
配套例子:
. |# [: l% i+ R! k* q6 g) L6 C5 D" p- v5 h2 r( Z5 J
V7-033_LCD的汉字小字库和全字库制作实验0 a2 M! x" A# ?/ r' D/ ^

5 D9 w; e; V: J3 i% N8 W5 f: I0 q8 p实验目的:
  u6 z7 U2 K$ v9 X8 n$ A9 H6 C) ^1 M8 x- p2 R  c: D
学习LCD的汉字小字库和全字库制作实验。
# J- T9 B$ x2 D% J1 Q$ t' l% s: ^" K9 {实验内容:2 P. ?6 X0 L8 g) `
LCD界面上展示ASCII字符和GB2312编码汉字。' v, O7 s/ k/ d0 Y
启动1个200ms的自动重装定时器,让LED2每200ms翻转一次。3 G+ w7 M- M1 m* b- F: D$ Z; o
实验操作:$ B, g9 a8 x% }( v9 }& a
8 n1 r# E0 p% R' |/ u
摇杆上键,增加LCD背景光亮度。2 M, R0 O) [6 _/ V" ?1 ^2 q
摇杆下键,降低LCD背景光亮度。5 ]# ^$ {8 M- T( l# f  }6 ]/ u0 u
摇杆左键,显示上一页汉字。" w2 N- R- M8 P* n7 J
摇杆右键,显示下一页汉字。
/ |9 u( t/ ?$ a: ]  w& o摇杆OK键,返回首页。# l  L; c- M9 e4 G& D
LCD的界面显示效果如下:
; n/ k/ o$ ]- h8 Y: T3 I( m  k* W$ i! u0 o6 C
部分截图:
* h, e- R5 C1 M& \* q* y- J) m
, ~6 ]2 }  k$ g4 Z& ^
aHR0cHM6Ly9pbWcyMDE4LmNuYmxvZ3MuY29tL2NvbW1vbi8xMzc5MTA3LzIwMjAwMi8xMzc5MTA3LTIw.png
7 K7 p7 i% X7 w
/ E* g( Y8 }  t, }! x  g3 y: K
4 T* ~" n; Q) c+ T0 r. e
aHR0cHM6Ly9pbWcyMDE4LmNuYmxvZ3MuY29tL2NvbW1vbi8xMzc5MTA3LzIwMjAwMi8xMzc5MTA3LTIw.png
8 {; c% n6 e. s) p( K( Y

! B9 {( c1 @, `5 V9 J2 M3 E
aHR0cHM6Ly9pbWcyMDE4LmNuYmxvZ3MuY29tL2NvbW1vbi8xMzc5MTA3LzIwMjAwMi8xMzc5MTA3LTIw.png

  v) F8 k9 |/ B( [$ p
( q9 O* x- g0 x/ g& M0 H上电后串口打印的信息:
. B7 h# e& j/ Z# F; z7 n
( p/ F" b8 b) h" M' R波特率 115200,数据位 8,奇偶校验位无,停止位 10 Q8 Y2 D& F( N5 o
( C9 F8 t5 V- r4 q
aHR0cHM6Ly9pbWcyMDE4LmNuYmxvZ3MuY29tL2NvbW1vbi8xMzc5MTA3LzIwMjAwMi8xMzc5MTA3LTIw.png
& J, L' _8 A/ k4 ]+ b" d+ ~

/ b7 a& w8 q4 U3 s) S; w6 k程序设计:
2 M6 ]2 v7 V5 M
  O+ [' e! e- r5 b  系统栈大小分配:$ n& x8 E5 [; B& z4 j/ [- o

2 J* o: C* b1 I# g. o5 v( y# |, L
aHR0cHM6Ly9pbWcyMDE4LmNuYmxvZ3MuY29tL2NvbW1vbi8xMzc5MTA3LzIwMjAwMi8xMzc5MTA3LTIw.png

' j1 J. y" n$ f+ R/ H& S8 Y7 ?6 R) q
  RAM空间用的DTCM:% Y. [0 t% A7 g3 f& X

; j! `. W1 K, C# u) a" b
aHR0cHM6Ly9pbWcyMDE4LmNuYmxvZ3MuY29tL2NvbW1vbi8xMzc5MTA3LzIwMjAwMi8xMzc5MTA3LTIw.png
4 n0 B# E) W- f; S  v8 t

! _! o4 d, y  G1 v  硬件外设初始化# @9 D  h, r1 m: ?1 R% Q

& d+ S" S3 n) Y' O# P硬件外设的初始化是在 bsp.c 文件实现:
' ~+ p/ e/ M4 |8 U; R' c) X& B* [$ P9 e& ]4 X
  1. /*2 h1 a9 ]: c5 V# o% t
  2. *********************************************************************************************************
    + C+ O1 b/ p9 r1 G" Z. }
  3. *    函 数 名: bsp_Init  M0 @$ V' R5 v
  4. *    功能说明: 初始化所有的硬件设备。该函数配置CPU寄存器和外设的寄存器并初始化一些全局变量。只需要调用一次- y% i5 w8 b" Q) q4 B3 D8 H
  5. *    形    参:无
    5 ?7 I7 q/ A. Z& f! y6 d9 g
  6. *    返 回 值: 无
      q8 h; h* r0 M3 t# Q$ S7 E, q  u! ^
  7. *********************************************************************************************************2 e5 X5 i+ V2 r* J' C2 H* J
  8. */
    % W; e# B* v5 A8 B( x8 k: z
  9. void bsp_Init(void)
    & Q( E1 w  M& X5 z
  10. {9 g, U& c- l, c( j/ I
  11.     /* 配置MPU */' t2 I" X% I+ [" s
  12.     MPU_Config();( `# x5 r& L- A9 v1 E- M( S: l- D
  13. 5 y6 f* [! v1 B, }& x6 |1 }* Z% ^
  14.     /* 使能L1 Cache */
    : X4 F5 s8 c, Y/ _0 K
  15.     CPU_CACHE_Enable();9 @. ~. u7 W* @7 ~* o* o
  16. + x8 U( `8 h- w" d7 K
  17.     /*
    4 P1 Z0 w2 \6 Z; }4 [( _
  18.        STM32H7xx HAL 库初始化,此时系统用的还是H7自带的64MHz,HSI时钟:
    7 R& N' z- J% Z8 J1 W$ D
  19.        - 调用函数HAL_InitTick,初始化滴答时钟中断1ms。
    * z0 r4 ~! x4 n+ Z
  20.        - 设置NVIV优先级分组为4。
    . f# a7 F( U" L) J, M, ^3 o
  21.      */
    + k5 U5 N' A  W, ^
  22.     HAL_Init();# {: O1 w6 {% ^

  23. 0 B* m& V0 u6 [
  24.     /*
    7 \& E' U/ z7 f5 {6 ]. D4 D# j
  25.        配置系统时钟到400MHz0 F9 ~* O; `  z6 U, O$ Q( B. k1 a
  26.        - 切换使用HSE。
    6 `& o. Z3 N7 U- ~" a; ~6 P& [
  27.        - 此函数会更新全局变量SystemCoreClock,并重新配置HAL_InitTick。
    7 b8 E$ c0 ~4 T8 [) x3 M6 e
  28.     */' V. n' ?. F+ \7 q
  29.     SystemClock_Config();
    2 p8 z# L1 S( ^5 l* N- t$ _! h

  30. : e- q9 ^7 P" j9 [  h
  31.     /* . s/ W* d7 {* d' Q# F
  32.        Event Recorder:
    8 r2 z: c9 _0 K& |# K
  33.        - 可用于代码执行时间测量,MDK5.25及其以上版本才支持,IAR不支持。3 j+ z. J2 O; _, z
  34.        - 默认不开启,如果要使能此选项,务必看V7开发板用户手册第8章0 e2 m! \$ @- H" A
  35.     */      o; p* v) c6 o4 P7 l
  36. #if Enable_EventRecorder == 1  + w8 C8 q. r+ Q  n6 ^
  37.     /* 初始化EventRecorder并开启 */
    5 s3 B3 V/ b2 r
  38.     EventRecorderInitialize(EventRecordAll, 1U);' }/ x- I7 Z5 k
  39.     EventRecorderStart();
    " J+ P% M: ]2 E3 _2 K9 k, ?. P# @
  40. #endif
    ) K6 B' [: n3 J& t, {+ C, t

  41. & Y1 g$ y5 v6 u" }% R
  42.     bsp_InitKey();        /* 按键初始化,要放在滴答定时器之前,因为按钮检测是通过滴答定时器扫描 */( t" Z6 h7 ^! D. u; U
  43.     bsp_InitTimer();      /* 初始化滴答定时器 */
    4 Z6 L, b7 z9 m
  44.     bsp_InitUart();    /* 初始化串口 */
    + V* z4 K5 L8 K
  45.     bsp_InitExtIO();    /* 初始化FMC总线74HC574扩展IO. 必须在 bsp_InitLed()前执行 */    ) Y: H; @  p8 e0 j+ ]% I$ n% V
  46.     bsp_InitLed();        /* 初始化LED */   
    4 W2 {7 n5 \" [/ r

  47. 3 @2 D& \2 i4 g, T. H) b: C
  48.     bsp_InitI2C();     /* 初始化I2C总线 */
    ; q8 t4 G0 I/ f, W4 x: ^
  49.     TOUCH_InitHard();   /* 初始化触摸芯片,LCD面板型号的检查也在此函数,所以要在函数LCD_InitHard前调用 */
    : h# M8 x" F% D( ?$ `' ^( ]
  50.     LCD_InitHard();     /* 初始化LCD */4 [) ~) i% g1 u- y+ }# |  }& X0 B
  51. }
    + H( {7 [: w7 r( P2 W
  52. # H* F0 x8 `6 [' ?
复制代码

% O& M7 |- F3 v! Z5 G  MPU配置和Cache配置:1 y. C1 I$ |8 _; n3 p

( ^# A, P6 O! i- q7 q% x- z: t数据Cache和指令Cache都开启。配置了AXI SRAM区(本例子未用到AXI SRAM),FMC的扩展IO区和SDRAM。由于SDRAM要用于LCD的显存,方便起见,直接将其配置为WT模式。
( H$ v9 i% G2 O8 s9 ^9 s6 ]( ^5 d: d/ `7 L
  1. /*! l0 G1 F: g: j$ u# m
  2. *********************************************************************************************************
    ! {3 G0 a$ ?& @+ L
  3. *    函 数 名: MPU_Config9 g% \$ J$ v; |* s( T: M
  4. *    功能说明: 配置MPU* q) P7 ?$ P! ^2 R6 s
  5. *    形    参: 无
    , Z6 |5 L; B* o$ N( u, g
  6. *    返 回 值: 无/ O. G: A, J- k. Q; G2 x- V, L
  7. *********************************************************************************************************1 Q4 m1 v+ r9 k% H% K8 T
  8. */
      j) F; e5 _/ ]* g7 t+ b  X
  9. static void MPU_Config( void )
    8 I' F8 t7 v2 l
  10. {6 }/ u, x0 [- f& ]
  11.     MPU_Region_InitTypeDef MPU_InitStruct;4 z  Z( T  M: C% b- ^
  12. 4 D$ |4 a: n2 Q2 h. O
  13.     /* 禁止 MPU */
    # U2 G1 i# a9 o# l, Q, B. P
  14.     HAL_MPU_Disable();
    ) C8 @# r' _: Q3 T  o. ~
  15. 9 W- J  c" g, J6 c9 C  W
  16.     /* 配置AXI SRAM的MPU属性为Write back, Read allocate,Write allocate */
    3 X0 ^# y9 w* Z1 H
  17.     MPU_InitStruct.Enable           = MPU_REGION_ENABLE;
    , l( N! k; O9 n' A3 z
  18.     MPU_InitStruct.BaseAddress      = 0x24000000;
    8 p2 [9 j6 j6 g- K) `5 I' l$ E8 Q
  19.     MPU_InitStruct.Size             = MPU_REGION_SIZE_512KB;
    : C, B0 r/ }1 ~
  20.     MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS;; k# v, _6 p2 O1 G; A
  21.     MPU_InitStruct.IsBufferable     = MPU_ACCESS_BUFFERABLE;3 I  R4 Y2 Y4 `. O  b
  22.     MPU_InitStruct.IsCacheable      = MPU_ACCESS_CACHEABLE;
    8 e. D9 [; C  c0 i% ^
  23.     MPU_InitStruct.IsShareable      = MPU_ACCESS_NOT_SHAREABLE;
    # w1 Z  w+ I' l& J% x4 E, }' r
  24.     MPU_InitStruct.Number           = MPU_REGION_NUMBER0;
    $ J8 `( m; a" V0 Y) d8 J& u9 K3 ^
  25.     MPU_InitStruct.TypeExtField     = MPU_TEX_LEVEL1;
    1 O: c7 O+ Y- _9 |0 O, J2 Z' r
  26.     MPU_InitStruct.SubRegionDisable = 0x00;
    * w1 y8 g( j) s! v+ a; Q
  27.     MPU_InitStruct.DisableExec      = MPU_INSTRUCTION_ACCESS_ENABLE;; F  ?8 a( Z8 y: z7 _! ~% A: r& Z

  28. ( H5 k& j0 v6 m6 d
  29.     HAL_MPU_ConfigRegion(&MPU_InitStruct);* I" Q+ G* u/ B  n, F

  30. . A) S; S6 M$ l
  31. ) ]! R  B! }, u- w% ^
  32.     /* 配置FMC扩展IO的MPU属性为Device或者Strongly Ordered */! X# {0 r7 \/ R+ y* }# X
  33.     MPU_InitStruct.Enable           = MPU_REGION_ENABLE;
    , U" @+ N) w! }0 O
  34.     MPU_InitStruct.BaseAddress      = 0x60000000;
    9 n- q  [2 e6 x. d( I/ Q4 N
  35.     MPU_InitStruct.Size             = ARM_MPU_REGION_SIZE_64KB;    ' K# Y& a1 V& U- C: M& q
  36.     MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS;& _0 {+ }1 ?) s! {% \
  37.     MPU_InitStruct.IsBufferable     = MPU_ACCESS_BUFFERABLE;. L& E6 l: U7 r
  38.     MPU_InitStruct.IsCacheable      = MPU_ACCESS_NOT_CACHEABLE;    8 w  g: Z5 u: M! y' j  i( P
  39.     MPU_InitStruct.IsShareable      = MPU_ACCESS_NOT_SHAREABLE;
    ! j! ~9 w  {) r3 ]0 ~5 D+ i
  40.     MPU_InitStruct.Number           = MPU_REGION_NUMBER1;
    8 f2 x" }% D# U1 O
  41.     MPU_InitStruct.TypeExtField     = MPU_TEX_LEVEL0;5 ~) T# x) e- J- B5 p: l* \/ c# C
  42.     MPU_InitStruct.SubRegionDisable = 0x00;
    3 s3 s2 i0 P- U& ?
  43.     MPU_InitStruct.DisableExec      = MPU_INSTRUCTION_ACCESS_ENABLE;) G* |  u0 v9 w! N- I9 C! G

  44. ( [' I+ x6 I7 D, S
  45.     HAL_MPU_ConfigRegion(&MPU_InitStruct);( H' ^/ |7 [; G

  46. % U( `, I: `/ ~- g& T" v
  47.     /* 配置SDRAM的MPU属性为Write through, read allocate,no write allocate */
    ! f8 i# j. O: r* C4 H
  48.     MPU_InitStruct.Enable           = MPU_REGION_ENABLE;
    % U1 @* Z) D- U
  49.     MPU_InitStruct.BaseAddress      = 0xC0000000;' @  t, f: s1 a# y; S
  50.     MPU_InitStruct.Size             = MPU_REGION_SIZE_32MB;; M6 S3 s; U7 j4 a- o' T/ Q  y
  51.     MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS;
    7 ?5 C# E) N0 B% |, U6 [! b
  52.     MPU_InitStruct.IsBufferable     = MPU_ACCESS_NOT_BUFFERABLE;6 J8 X; Z. U# S6 N- D  s6 A7 I% @
  53.     MPU_InitStruct.IsCacheable      = MPU_ACCESS_CACHEABLE;
      O- W1 P1 ?, P4 s8 P6 l9 E4 `
  54.     MPU_InitStruct.IsShareable      = MPU_ACCESS_NOT_SHAREABLE;" f" e$ N& \7 c9 h! h" k, b
  55.     MPU_InitStruct.Number           = MPU_REGION_NUMBER2;( ]- g9 g1 C1 ^* T
  56.     MPU_InitStruct.TypeExtField     = MPU_TEX_LEVEL0;4 z4 q, k4 B+ G; Y' U
  57.     MPU_InitStruct.SubRegionDisable = 0x00;
    $ ~* r: u( g/ _& |8 @& ~1 I
  58.     MPU_InitStruct.DisableExec      = MPU_INSTRUCTION_ACCESS_ENABLE;
    1 p( U0 S9 E. I# \4 x* J
  59. 0 D# E) H* p2 a+ y! `
  60.     HAL_MPU_ConfigRegion(&MPU_InitStruct);
    . ?/ V+ S4 ?, e2 G- p

  61. 4 c- j* w+ Z% @0 [7 \( y) I
  62.     /*使能 MPU */
    ; s6 H9 B) O3 d( J; ~& v
  63.     HAL_MPU_Enable(MPU_PRIVILEGED_DEFAULT);, U: U6 E+ n/ c3 Y2 X2 ]/ G
  64. }4 z9 v. `2 a8 L/ m2 e$ A0 v; n

  65. 1 ?5 r# J; y- R* D$ |
  66. /*: @3 y1 P3 b& D
  67. *********************************************************************************************************/ b& R* j( i6 b" \) y0 l% q
  68. *    函 数 名: CPU_CACHE_Enable* N5 C, ?; z+ a5 p' C: B  F( L/ y
  69. *    功能说明: 使能L1 Cache
    . c) Q0 R# i* |7 F& n6 _
  70. *    形    参: 无9 S3 x, ~7 T# W7 ^9 J, P$ B
  71. *    返 回 值: 无+ @8 X; ^6 R1 z7 K! f1 Z2 R
  72. *********************************************************************************************************$ S5 m+ n* y  V% u# z- f
  73. */
    ; s- _3 d3 W' q8 S( `
  74. static void CPU_CACHE_Enable(void)- c4 L9 m5 }8 N( G  `
  75. {
    ; @7 c7 Q+ ?, `8 a: B
  76.     /* 使能 I-Cache */" W8 X% M- ^& o" H% D
  77.     SCB_EnableICache();
    7 R9 |( Q' H5 b* a: K

  78. & ^; n7 h" d9 b
  79.     /* 使能 D-Cache */0 @* V/ O1 E7 f. y' l( ~2 B
  80.     SCB_EnableDCache();
    9 {- o7 B% d# a
  81. }
    * Y6 Y0 U6 Z/ L
复制代码
* ^  b! L1 M5 ~5 A8 Y; k

0 n. j: o  H, y8 ~6 D9 h1 w  主功能:
: I" x9 }1 w! |* a6 b4 ?/ P, D1 }1 O( e7 k$ k2 _! z" ~
主程序实现如下操作:9 D% i4 P: a7 u2 d1 {% K& o

7 [" p3 z/ M$ @& B$ V  LCD界面上展示ASCII字符和GB2312编码汉字" h0 J$ A# [( E8 a, C  d3 A  K
  启动1个200ms的自动重装定时器,让LED2每200ms翻转一次。
6 ]' u0 X0 S0 s/ f# `8 ]& }: D, ~  通过按键来实现翻页功能,方便查看所有GB2312编码汉字。
+ V9 F2 |( n/ T9 b2 w" k
  1. /*
    $ _" o, `# }! B
  2. *********************************************************************************************************7 o" r' Q' b9 A' t9 j
  3. *    函 数 名: main* p5 Q2 l8 C5 B. ]% F7 K, t
  4. *    功能说明: c程序入口3 [- ?" g% n2 o/ x3 y: v% I$ s
  5. *    形    参: 无7 O2 M2 {6 u6 j) L
  6. *    返 回 值: 错误代码(无需处理)  B  K7 l0 {) R3 ^! T' A  P
  7. *********************************************************************************************************: i2 y6 c: Y) q0 @4 n2 H
  8. */
    . P$ e1 z; V6 E5 O' ^5 k$ m7 _
  9. int main(void)
    4 l( C; a" t4 C$ |0 w1 _
  10. {
    : y: M1 k' i( Z  I! l* b
  11.     uint16_t ucBright;           /* 背光亮度(0-255) */
    / A$ o4 G' B3 O+ ?4 e
  12.     uint8_t ucKeyCode;        /* 按键代码 */! q* \) @4 N0 K
  13.     uint8_t ucStatus;        /* 主程序状态字 */1 V* `- J& R9 e& S1 N% N
  14.     uint8_t fRefresh;        /* 刷屏请求标志,1表示需要刷新 */# |- S1 E8 g4 ~. z/ c# W! W

  15. 2 H8 C* G2 B; ~& \/ s0 F7 T9 x6 f- G
  16. 6 P$ F- ?8 A" g' U) N# M& V, Y
  17.     bsp_Init();    /* 硬件初始化 */0 l% ?- M+ ~$ P
  18.     PrintfLogo();    /* 打印例程名称和版本等信息 */
    1 F; L7 y- d, M( ^, @; B. _. z% |  h
  19.     PrintfHelp();    /* 打印操作提示 */
    / u3 y, p* P$ t  u( Q1 X

  20. 6 B* h+ v2 |  l4 q/ ?* b
  21.     /* 延迟200ms再点亮背光,避免瞬间高亮 */: M1 u' e  D/ b
  22.     bsp_DelayMS(200);
    " h: y' [) \+ A0 j. F

  23. " m3 y) Y* C! ]) N! [
  24.     DispFirstPage();    /* 显示第1页 */
    & z/ h4 x" @( D. p8 B+ a

  25. 3 V! ^) S4 ]( f
  26.     /* 界面整体显示完毕后,再打开背光,设置为缺省亮度 */5 X% R6 L  w; n7 `# z2 r, g
  27.     bsp_DelayMS(100); ( Z5 ]/ s2 V! J6 D$ F
  28.     ucBright = BRIGHT_DEFAULT;
    2 k. K# ]% n4 ^
  29.     LCD_SetBackLight(ucBright);
    5 p: S& \+ ^7 Y" H; F1 S7 J, w

  30. 5 k1 r- Y: F# j! ~
  31.     bsp_StartAutoTimer(0, 200); /* 启动1个200ms的自动重装的定时器,软件定时器0 */
    9 P( e/ U7 G& H
  32. & ]9 L- m3 R$ M2 T. l. Z
  33.     /* 进入主程序循环体 */. ?  }* F) h2 A$ ?: t* ?
  34.     ucStatus = 0;. R! e- b9 Z2 ], ?9 r6 t& V( x
  35.     fRefresh = 0;    ) L, w( g1 |8 v, [! n- h9 U
  36.     while (1)/ s# U- r6 r9 O' j) P: R
  37.     {
    , y4 ^2 G5 b' E. k' |7 h
  38.         /* 判断软件定时器0是否超时 */
    % d3 L# k; f/ \  X5 ^  N
  39.         if(bsp_CheckTimer(0))
    4 \' }( g8 L( I8 W
  40.         {  s9 n2 u  L$ _9 e. E6 u- D7 `
  41.             /* 每隔200ms 进来一次 */  
    5 @5 k7 n# R8 N$ L% d) o  \
  42.             bsp_LedToggle(2);  f+ r  M$ {& x! J
  43.         }
    4 o, U8 ]4 t1 g9 a! ^/ n6 H5 V

  44. ) }* |2 i! g. x1 l: O- d4 I: O
  45.         if (fRefresh == 1)' ^2 n3 b- U' s( m
  46.         {  b% ]. R$ i: w1 x
  47.             fRefresh = 0;
    . P5 |7 X; c% o) ?- V5 v
  48. % s. k% d4 G% |2 @. t# A
  49.             switch (ucStatus)" H$ ^0 h- k  z% e! k( D- P
  50.             {; g0 `/ I1 t0 N
  51.                 case 0:& q- P( a. \) j
  52.                     DispFirstPage();    /* 显示第1页 */
    / t' s- }% ]5 E# d
  53.                     break;
    3 w  }) A# l/ E$ D7 I
  54. 4 q; n) \9 k9 H
  55.                 case 1:; v! E, Q. |7 p! I# {5 @
  56.                     DispAsciiDot();        /* 显示ASCII点阵 */# F1 P3 ?: e8 a, r( B, l
  57.                     break;; f' X6 o  f+ @1 {

  58. # R! C" x: V1 n& n
  59.                 default:: l0 Z* H2 C) \, j2 M' t& |5 G/ ~2 F
  60.                     /* 区码范围 :1 - 87 */7 i, e+ L& H2 v# `/ ~
  61.                     if (ucStatus <= 89)
    % k: M+ _! ]# x% c; y4 c! J$ ]
  62.                     {& c. x  _5 @) `4 }, G; W; q- m
  63.                         DispHZK16(ucStatus);    /* 显示一个区的94个汉字 *// Q- {% O! t2 t& _0 T& v
  64.                     }; j7 W) u! c- B
  65.                     break;
    " z5 F6 x: D+ ~% H" |
  66.             }& N; [; T' J/ R5 G( m6 \$ t
  67.         }8 h; u! @5 L. ^6 o& b! y4 r

  68. ! C$ M- q% L" L: e. i3 D' N: G
  69.         ucKeyCode = bsp_GetKey();    /* 读取键值, 无键按下时返回 KEY_NONE = 0 */
    8 I$ \+ Q% [5 T' N) \4 a
  70.         if (ucKeyCode != KEY_NONE)' `5 u  o" m' L8 v
  71.         {/ a& B* s  v+ x' V
  72.             /* 有键按下 */8 z5 g; c* y5 [! q# P- b
  73.             switch (ucKeyCode)
    ) G" q. N- Y* y8 v% c# i* z
  74.             {
    5 ~/ W( S  E5 ]( c3 Q+ X
  75.                 case JOY_DOWN_L:        /* 摇杆LEFT键按下 */5 \$ I" j4 M9 F6 M- q
  76.                     if (ucStatus > 0)5 M! v& T1 |+ A9 u. X- k7 N
  77.                     {
    6 `# ?+ k) j6 i
  78.                         ucStatus--;
    + a9 D' x  b1 B$ p; n# H
  79.                     }% q3 t' c; E( M# W0 s
  80.                     fRefresh = 1;        /* 请求刷新LCD */5 R9 N. o  y" Q- d
  81.                     break;4 H/ m0 C& q/ a* w

  82. & h# m0 R3 F. N8 ^
  83.                 case JOY_DOWN_R:        /* 摇杆RIGHT键按下 */
    0 q% d$ A$ A+ s. ]/ C+ I
  84.                     if (ucStatus < DEMO_PAGE_COUNT - 1)
    9 D+ N, o- n' V
  85.                     {
    6 E8 j% }. U3 ~7 T  Z( y
  86.                         ucStatus++;
    ) N" ^+ G/ d+ B% q
  87.                     }# }' m- B5 |, _" h: `" p# q2 h
  88.                     fRefresh = 1;        /* 请求刷新LCD */4 l, j2 U, l% d( b/ y7 j5 v% A! }% I) ?
  89.                     break;& r1 X7 _! S; q# p' d, f

  90. ; Z- ~8 e6 H+ F! B( W
  91.                 case  JOY_DOWN_OK:        /* 摇杆OK键 */
    + L6 }; F- x' H4 i. p4 d) O! g5 H
  92.                     ucStatus = 0;        /* 返回首页 */                    9 |# o/ x! K, K3 b8 g( _# L
  93.                     fRefresh = 1;        /* 请求刷新LCD */, A% W/ s9 o2 R2 `
  94.                     break;
    8 T6 P0 W# W6 I/ p$ s: A* v6 v
  95. 0 B! z' M# B3 W# ?
  96.                 case JOY_DOWN_U:        /* 摇杆UP键按下 */' Z  ~( ~4 M; d0 {& J
  97.                     ucBright += BRIGHT_STEP;, E: h; l/ J5 z
  98.                     if (ucBright > BRIGHT_MAX)
      f/ l" N+ X+ [9 K8 s. G8 a
  99.                     {
    & @! n2 p% L' l( o( A
  100.                         ucBright = BRIGHT_MAX;3 O& T& H; s  e5 x
  101.                     }4 t( l' E8 F- G+ p2 N
  102.                     LCD_SetBackLight(ucBright);* g' Z8 R" Z% u, j+ Y; Q
  103.                     printf("当前背景光亮度 : %d\r\n", ucBright);% |! q; `: s+ i' t0 [3 X
  104.                     break;3 j+ V2 [9 E3 _) S8 L" L6 W* A

  105. ; x1 z7 D0 z9 }, e
  106.                 case JOY_DOWN_D:        /* 摇杆DOWN键按下 */  O" T: ?! w: b; X9 e; `) T
  107.                     if (ucBright < BRIGHT_STEP)6 c0 D( ^2 |' ?* V: y- w4 P
  108.                     {+ C5 f: Q5 I7 @( R& f8 A  H
  109.                         ucBright = 0;2 o& a; x' \& j( t* I$ y# ^! ?
  110.                     }
    0 u% Z/ e8 |7 ~2 V! s1 s
  111.                     else9 i3 m7 I4 P+ w( Z
  112.                     {
    + Y6 ^8 V3 s2 O! b0 W3 _
  113.                         ucBright -= BRIGHT_STEP;
    * f' s0 \  [8 B: ^  [* D+ h" A
  114.                     }- q3 X0 Z: U  l8 K5 I
  115.                     LCD_SetBackLight(ucBright);
    & @# q$ W( p/ A! p
  116.                     printf("当前背景光亮度 : %d\r\n", ucBright);
    # }# \3 ?: D/ L) C
  117.                     break;, `4 h6 v6 \" B) j+ N, z0 k- C- r, e
  118. 9 r6 m4 X$ H  R
  119.                 default:
    ! g" v/ ^  }+ g" Q: g+ C
  120.                     break;) v  I- y: M, V2 C; i3 W+ B9 r
  121.             }/ |5 b5 A( q" k: {% E% v9 H
  122.         }7 D/ [& n5 B- D& F! U, {' a
  123.     }' ~& H' i$ r6 f: v; ]+ w
  124. }
复制代码

6 o- @' ^" ]' C: V4 L. p& o
; z; R2 [; R7 H, m, A! V7 A
5 W, h$ m; ]' }8 |6 F/ I. b下面的代码用于LCD首页显示:
; Y) n9 v( `3 Z2 ]% I  a. E  q/ w7 f9 h. ~
  1. /*8 M2 v2 i' R6 t! G
  2. *********************************************************************************************************. I# J7 [! U4 _" B6 {% K
  3. *    函 数 名: DispFirstPage( E7 D- I0 n. \3 F) E
  4. *    功能说明: 显示操作提示
    " Q3 u' V4 G) V7 L6 T' x- c
  5. *    形    参:无, y% o; I8 R! ~( R
  6. *    返 回 值: 无/ ?/ u" I. v) ~' @
  7. *********************************************************************************************************
    / A/ f/ |! K* d3 [3 ?
  8. */
    / c7 o2 ?0 S; L0 D0 H; S4 x- H
  9. static void DispFirstPage(void)
    # m! A4 u0 ~) I; O: v1 \
  10. {/ S6 E' _2 C+ H+ ]
  11.     FONT_T tFont;            /* 定义一个字体结构体变量,用于设置字体参数 */
    2 t3 o% ?* R4 L: {/ t
  12.     uint16_t y;            /* Y坐标 */! V, |3 N& N- D; L
  13.     uint16_t usLineCap;    /* 行高 */
    " g4 I2 y& o; n
  14.     uint8_t buf[50];
    % `( C7 ~) A) {. S/ i) `
  15. 1 K$ ]& ]9 Y3 R/ V
  16.     LCD_ClrScr(CL_BLUE);          /* 清屏,背景蓝色 */$ s. m8 s, K9 x
  17. 4 D' r+ L. u, ~

  18. / B/ B- x' \! B: \2 f
  19.     /* 设置字体属性 */
    : \2 d2 z. G2 u, R7 J9 {
  20.     tFont.FontCode = FC_ST_16;        /* 字体选择宋体16点阵,高16x宽15) */2 {( _8 ~# @" L  v4 D- r
  21.     tFont.FrontColor = CL_WHITE;    /* 字体颜色设置为白色 */# y% V: M# J$ d
  22.     tFont.BackColor = CL_MASK;         /* 文字背景颜色,透明 */
    % H  L+ m% o5 c  A1 P* o
  23.     tFont.Space = 0;                /* 字符水平间距, 单位 = 像素 *// w( N% Q$ J. r* _

  24. : B0 l: q& s3 `: l4 s2 K/ E. |
  25.     y = 0;4 n' o8 m& q5 b* I, P$ ?  `# h
  26.     usLineCap = 18; /* 行间距 */
    9 o+ x- V# L% _! B! h0 Q. R
  27.     LCD_DispStr(5, y, "安富莱STM32-V7开发板  <a href="http://www.armfly.com" target="_blank">www.armfly.com</a>", &tFont);
    . o1 I- o6 A- [0 n' Q9 z/ |' @
  28.     y += usLineCap;8 K8 J0 y0 j* ?5 p
  29.     LCD_DispStr(5, y, "汉字小字库和全字库测试实验", &tFont);$ c2 Y2 T5 s, m4 ~! z& z& |+ ?
  30. ! V# g# M5 i- O/ C* z: m
  31.     y += 2 * usLineCap;
    5 _* Q) ^; \4 ]3 Z8 o3 M
  32.     LCD_DispStr(30, y, "操作提示:", &tFont);& T: c) r3 ~5 k4 W6 t; l

  33. % Y7 V. m- t; G$ I- |
  34.     y += usLineCap;+ Q4 b2 T% D' |% |# n; c3 A& s
  35.     LCD_DispStr(50, y, "摇杆上键 = 增加背光亮度", &tFont);, j6 N) U- F8 w) X& u
  36. 2 v( @3 w, @* _) p' A% S
  37.     y += usLineCap;
    $ I4 j2 b7 ~5 @2 O( U1 m
  38.     LCD_DispStr(50, y, "摇杆下键 = 降低背光亮度", &tFont);( y0 t5 C/ c! D4 i& M5 B
  39. + M' A7 Q% L7 u- t
  40.     y += usLineCap;
    7 X! y1 b  n3 X, {1 l+ \
  41.     LCD_DispStr(50, y, "摇杆左键 = 向前翻页", &tFont);: ^& b$ t/ T& e
  42. 2 F2 `; @+ ^/ [# ~% Q
  43.     y += usLineCap;2 c5 Z1 L9 I- b! W" l
  44.     LCD_DispStr(50, y, "摇杆右键 = 向后翻页", &tFont);
    ! E2 h9 e: u* p

  45. : i) F) g7 Z5 z  w, n5 ?
  46.     y += usLineCap;, ^4 G  U* r3 Y
  47.     LCD_DispStr(50, y, "摇杆OK键 = 返回首页", &tFont);4 B- D; z$ \2 l9 v$ @/ ?" j3 g

  48. , U  `! Q3 e; a
  49.     y += 2 * usLineCap;    0 d$ g! a9 r- f/ h) F
  50. - A' M" G0 ?7 S/ K2 u7 i
  51.     sprintf((char *)buf, "显示器分辨率 :%dx%d", g_LcdWidth, g_LcdHeight);
    9 o+ t9 C( Q& O+ `2 h# A- _
  52.     LCD_DispStr(5, y, (char *)buf, &tFont);% i0 \4 P  j+ c% L; I

  53. 5 b8 ~/ T9 D' g# g# U$ Z# F
  54.     y += usLineCap;
    , i% z8 W' e3 J& ]% z- U( H
  55.     LCD_DispStr(5, y, "每行可以显示25个汉字,或50个字符", &tFont);1 M' c/ U  k+ J0 P
  56. }
复制代码
- |( v$ O3 q3 q( |; A

- `& p6 l0 P2 r2 c6 p" Y& m
. a0 }6 P8 F/ u+ p+ f, g下面是ASCII字符显示:
6 x/ r+ i1 z% f% W* ~, p7 J- }) o! a  K
  1. /*) q% Z$ H0 j; w% v
  2. *********************************************************************************************************
    5 q1 |" F& N9 K+ F7 M
  3. *    函 数 名: DispAsciiDot
    . \. T% H; {. x3 V1 R# C
  4. *    功能说明: 显示ASCII点阵3 \5 R5 O" A6 ~
  5. *    形    参:无6 ?) _5 q" r# U
  6. *    返 回 值: 无3 z0 \, y, ]1 I# y
  7. *********************************************************************************************************
    / j/ x) O! R8 w' l, R( d
  8. */
    5 L0 l9 r- P! ?1 u8 B' ?$ V1 ^9 b
  9. static void DispAsciiDot(void)
    ' m7 X' K. B( B, t6 c& H
  10. {
    6 T- a# v9 L& I! B- h( J% D
  11.     uint8_t i,k;7 E7 o# E8 @& ~5 [' C  q6 v$ |
  12.     FONT_T tFont;        /* 定义一个字体结构体变量,用于设置字体参数 */
    ' ^2 b  S  X' |5 Q, }1 q# I
  13.     uint16_t x;        /* X坐标 */
    4 P1 B/ `0 O3 ?# i! A# r
  14.     uint16_t y;        /* Y坐标 */   
    9 Y5 e2 n! w! c# ?! t2 h
  15.     char buf[32 + 1];+ n! j5 l" ]1 O; E( R
  16.     uint8_t ascii;
    9 S! j$ w# ]1 O5 }" B, C/ h
  17. 3 [* I5 P3 `5 J: U& H
  18.     LCD_ClrScr(CL_BLUE);          /* 清屏,背景蓝色 */& L- \- ~, H" d& V

  19. . V6 h' A% `6 y' C% g
  20.     /* 设置字体属性 */1 J5 b" A1 b% N+ Y: h
  21.     tFont.FontCode = FC_ST_16;        /* 字体选择宋体16点阵,高16x宽15) */
    6 Z9 D5 O+ a% E% x
  22.     tFont.FrontColor = CL_WHITE;    /* 字体颜色设置为白色 */
    ) z  K! b$ d( b. a3 z1 R
  23.     tFont.BackColor = CL_MASK;         /* 文字背景颜色,透明 */
    4 B0 x" R0 I% c2 u1 {
  24.     tFont.Space = 2;                /* 字符水平间距, 单位 = 像素 */# Z& A0 S; F& R# n# d" w# t9 |8 b6 G
  25. 6 R5 U4 \5 c. H1 \# P
  26.     LCD_DispStr(50, 0, "16点阵ASCII码字库,代码1-127", &tFont);
    . N& D4 [5 l9 Y2 \% D: ]
  27. 3 [5 k) e2 c; J; b2 v; \
  28.     x = 50;- a/ W. o+ o7 Y/ r5 a$ v
  29.     y = 40;
    0 _" j% ^# T' T3 b
  30.     ascii = 0;
    . w8 o% {, d6 ?+ I/ J% h
  31.     for (i = 0; i < 4; i++)
    6 o6 X/ ?2 F; }+ c
  32.     {
    & V, ~$ U0 }, Y, l. @
  33.         for (k = 0; k < 32; k++)
    7 ]6 v+ U$ `/ o/ g
  34.         {
    0 ~, M* g; W$ m1 v9 \% z" i/ ~
  35.             buf[k] = ascii++;
    ! R2 [9 v0 q- l) N
  36.         }
    ' J0 g" D) E2 \5 b3 i' h# |
  37.         buf[32] = 0;, L& H0 _- I- W) @3 _7 I6 y5 H. n
  38.         if (buf[0] == 0)
    0 F) k8 J' ^9 C- X
  39.         {5 G: I& `3 }" \. B5 f. e( W
  40.             buf[0] = ' ';1 R* z# p# M2 k/ \  h3 q* b
  41.         }
    4 U8 o) h! _( G9 F! K8 g/ ]' V
  42.         LCD_DispStr(x, y, buf, &tFont);
    & c- u! _6 O. S7 W% b
  43.         y += 20;
    / K6 E5 z; q, V! D: d9 |6 J5 l
  44.     }
    - D1 E# p1 y7 d' z$ M3 h$ E8 o
  45. }
    6 }; ^! n) j- B8 ?$ c7 y& ~/ S/ P2 v
复制代码

; L+ R+ t0 n* L. T, @
6 d  E7 J& p  ]3 p0 _下面是GB2312编码字符显示:
- C, [2 ?) Z) D# f2 o1 e8 u
& H5 W: [8 M9 q$ L7 W9 ^
  1. /*6 M$ z* l9 j% l
  2. *********************************************************************************************************
    : L8 n( _; X4 M9 [! [# W! Q
  3. *    函 数 名: DispHZK16
    / ~. _1 F0 \, ?: }( {8 b3 d( }
  4. *    功能说明: 显示16点阵汉字阵
    ; R" H4 i' q* \
  5. *    形    参:无
    . j/ m' q7 q5 b) R, r" `% g, S
  6. *    返 回 值: 无3 r) P3 }% u- y& W, f
  7. *********************************************************************************************************- L5 ~- c* r1 k. M$ O4 p
  8. */
    ! V8 s" E: u1 `4 c
  9. static void DispHZK16(uint8_t _ucIndex)$ S& i! \+ J  `# d
  10. {
    6 E/ N( A2 D0 `8 A+ `( j8 p
  11.     uint8_t i,k;
    ; a& L0 z' C! q; g
  12.     uint16_t x,y;6 w% A& P2 x4 m& ~
  13.     char buf[50 + 1];( H* T$ |$ {- F$ p
  14.     uint8_t code1,code2;    /* 汉字内码 */
      C2 f6 b0 x9 u  K+ Q1 G
  15.     uint8_t usLineCap = 18;
    ( p/ D3 M3 j; F) g0 H# Z
  16.     FONT_T tFont;            /* 定义一个字体结构体变量,用于设置字体参数 */6 N+ y8 A1 ~6 G6 p$ d* \4 F

  17. 2 g, J& P0 r* U5 u* k+ n
  18.     printf(" Display HZK Area Code = %d\r\n", _ucIndex - 1);) w, U2 |7 Y3 }- I$ E

  19. 2 G3 b; s* F  }$ ?
  20.     if (_ucIndex == 2)
    1 ^4 L8 k8 y! t
  21.     {+ E$ j$ Y1 N7 x2 |" ~- u" ~
  22.         /* 第1次清屏,以后显示位置不变,可以不清屏,避免闪烁 */
    - n; t$ h! z7 T* P$ H
  23.         LCD_ClrScr(CL_BLUE);          /* 清屏,背景蓝色 */
    5 k) U4 A9 c3 z( ]" g
  24.     }
    ( _0 Y0 w/ R7 J% l. o/ g

  25. 5 e7 R, ?6 L( f/ b) r4 U
  26.     /* 设置字体属性 */2 o. y" w; [" Q  C
  27.     tFont.FontCode = FC_ST_16;        /* 字体选择宋体16点阵,高16x宽15) */
    % v# r6 c) f* Z# a
  28.     tFont.FrontColor = CL_WHITE;    /* 字体颜色设置为白色 */
    ! @1 E5 f' G! `$ _
  29.     tFont.BackColor = CL_BLUE;         /* 文字背景颜色,蓝色 */
    ; P, T# E+ l' A! }- `1 }8 P
  30.     tFont.Space = 0;                /* 字符水平间距, 单位 = 像素 */
    , P" o, I. Q- [" B4 x: A

  31. 4 k# I3 U. T& `, u" |
  32.     y = 0;
    2 l' I; D0 I2 c4 z! V
  33.     LCD_DispStr(20, y, "国标GB2312 16点阵汉字库(区码1-87,位码1-94)", &tFont);2 @( q+ ^# ?( f" N' l2 p2 @

  34. + W. G* {$ L% u3 J1 S- o# ^+ i. q
  35.     code1 = _ucIndex - 1; /* 得到区码 */
    $ o! R' R% c3 a
  36.     code2 = 1;            /* 位码从1开始 */9 f$ j5 l# B# X, B2 g; p

  37. + w  x2 f3 y* c; x0 Q" ]
  38.     y += usLineCap;' S- k& z0 `7 B# b: ~, E
  39.     sprintf((char *)buf, (char *)"当前区码: %2d, 本页位码:1-94, 第10-15区无字符", code1);( Z  A2 U5 y: b4 L# Y
  40.     LCD_DispStr(20, y, buf, &tFont);
    0 C2 M5 J, ~" ]4 Y/ ]
  41.     y += (2 * usLineCap);
    5 s- }/ v- T  w2 a7 c+ _

  42. + S/ A$ W. [8 j/ H0 Z: Y, M
  43.     /*9 h6 y5 K$ i5 `% i  n; s
  44.         机内码高位 = 区码 + 0xA0% ?8 Y/ r2 @; l; w
  45.         机内码低位 = 位码 + 0xA0" U1 L8 s% w. T
  46. , T* x* H7 z$ w" X* R6 Z, ~' S
  47.         区码范围 :1 - 87
    * ~, K2 S4 b" Q* ]1 r+ y
  48.         位码范围 : 1 - 94) C5 q0 v; L" m9 \0 C& J; J; j1 q

  49. ) y7 @3 [; z6 o5 \7 j$ [
  50.         每行显示20个汉字,一个区是94个汉字,需要5行显示,第5行显示14个汉字
    ; I/ Z) y. }) W7 P) w. `
  51.     */
    # |& M2 h3 h+ `9 t
  52. : m8 r4 E8 V: V$ I9 I' z5 }* c
  53.     x = 40;
    . \* Y) q, @% ]" O2 p- _
  54.     code1 += 0xA0; /* 换算到内码高位 */% e! I; {% {' _
  55.     code2 = 0xA1;  /* 内码低位起始 */
    2 l/ T9 r" X; N" q) S
  56.     for (i = 0; i < 5; i++)
    2 W# J" k4 t, ?. s1 g
  57.     {. u" u" ]) z- P, V) X0 N
  58.         for (k = 0; k < 20; k++)
    ! D& C* i2 H9 Y2 u5 @4 \% m1 C* n
  59.         {! n; j9 h  h0 T' O6 A
  60.             buf[2 * k] = code1;
    9 r" N, ?2 B1 c' ~+ i1 @
  61.             buf[2 * k + 1] = code2;4 s# e6 }+ K- ?! e: J8 m
  62.             code2++;( U* s' N) x, y0 s6 `" n+ Z
  63.             if ((i == 4) && (k == 13))
    " L' j+ k! X  A; s
  64.             {; R  @9 Y' ?. [( u1 Y' `8 C
  65.                 k++;, V2 x; G' q4 [$ j" R
  66.                 break;6 c1 s# F6 f6 @6 l7 @. t$ \" ?
  67.             }
    2 R& w; y1 O2 E# }+ I
  68.         }3 Q+ I4 j, C+ g; w! m2 C
  69.         buf[2 * k] = 0;& K) @+ q( H$ a/ C: ~# L" g( w
  70.         LCD_DispStr(x, y, buf, &tFont);
    + y4 }; n3 j1 h
  71.         y += usLineCap;
    & x" C8 H5 k" w  b
  72.     }
    ) ?4 R' T" P& L) Q5 |
  73. }
复制代码
4 q3 j7 d2 p( G, \. `
" V" L5 G0 D* E) P3 @

* `6 P! H/ s& ^$ K53.9 实验例程说明(IAR)& c, F8 ?/ J* d
配套例子:
+ D  G. W3 E  u9 N0 Q' t
- z1 e+ J* e' u) N7 f9 M( vV7-033_LCD的汉字小字库和全字库制作实验) m- H5 x- [5 z
2 C+ I1 E8 W. U+ q: N' K
实验目的:$ S% x) V0 O1 Q( m* i- _5 q

$ T/ R9 Y6 Y9 N1 L  n1 p学习LCD的汉字小字库和全字库制作实验。
- g& r2 S3 U$ Y" q  w# G7 ]( |& i实验内容:
, R$ j- e/ m& DLCD界面上展示ASCII字符和GB2312编码汉字。
$ f! @! M, _6 ~7 C9 c8 y& B启动1个200ms的自动重装定时器,让LED2每200ms翻转一次。5 y+ A! c( O) j
实验操作:, n, D+ Q. r1 J% c
& o% W9 |7 _% {0 P& E
摇杆上键,增加LCD背景光亮度。/ w3 z" s( u9 j! {6 |: E) J
摇杆下键,降低LCD背景光亮度。
0 L" g( ]8 b2 h9 z1 u' A0 ~摇杆左键,显示上一页汉字。; Z$ h* }- @: g# F6 x; {
摇杆右键,显示下一页汉字。2 s& L, I( t7 X; z6 a% F% _
摇杆OK键,返回首页。
' q8 Z' x9 ]/ p2 I: f+ B+ n2 O" D0 {LCD的界面显示效果如下:$ ?1 _. Q; ?8 b. [+ O0 s6 d# D

* K4 o8 x8 o& i% X/ u% l6 _7 a部分截图:
0 K+ d5 B7 k# l, s$ [& a- m3 G) `- e8 ~) v; P. C( d0 V& J' t

9 x' N1 f  H5 N8 r4 I
0 w. L- H! l2 {4 m. G* q8 S+ K' }, M# G% J
aHR0cHM6Ly9pbWcyMDE4LmNuYmxvZ3MuY29tL2NvbW1vbi8xMzc5MTA3LzIwMjAwMi8xMzc5MTA3LTIw.png
( M/ @6 M) B* ~4 f3 e7 Q
9 h) |7 B- v: M  ^# t$ ]) k5 C  j, r
aHR0cHM6Ly9pbWcyMDE4LmNuYmxvZ3MuY29tL2NvbW1vbi8xMzc5MTA3LzIwMjAwMi8xMzc5MTA3LTIw.png
$ ?% Y3 N* l8 ]3 T# k& O& R

/ s" m$ N+ ?' y4 ]$ F5 ^2 W/ c; B) m0 C
' C; b8 z! n. H% c* E上电后串口打印的信息:5 j3 W* g9 Z' {) c5 u. R1 W
+ I! j& y5 n2 d/ i7 ?* z: g% x6 [
波特率 115200,数据位 8,奇偶校验位无,停止位 1
- X, F/ v8 k* A% J
2 ]* I% P+ m- K) M  A9 ^1 }7 B
aHR0cHM6Ly9pbWcyMDE4LmNuYmxvZ3MuY29tL2NvbW1vbi8xMzc5MTA3LzIwMjAwMi8xMzc5MTA3LTIw.png

# I/ w: o2 C+ W' S& h) y8 R# U! b4 F5 O0 p% C
程序设计:/ S, f6 l5 _( X

6 U& K# H- K' f  系统栈大小分配:( V- H4 Z& Q% c0 O

% \( K* `( L5 j. p9 x+ h
aHR0cHM6Ly9pbWcyMDE4LmNuYmxvZ3MuY29tL2NvbW1vbi8xMzc5MTA3LzIwMjAwMi8xMzc5MTA3LTIw.png

. w4 i/ o9 d, Z9 t+ }5 l: e4 H) F$ r8 A* i
  RAM空间用的DTCM:
" T: T( l3 F4 x5 w
5 C# X: B6 |- _" ]5 T8 F: y* V2 d, I& A
aHR0cHM6Ly9pbWcyMDE4LmNuYmxvZ3MuY29tL2NvbW1vbi8xMzc5MTA3LzIwMjAwMi8xMzc5MTA3LTIw.png

6 ?/ f; V  T% e7 `/ S3 ?5 S. j+ M) S
  硬件外设初始化. G% r+ ^2 N  a2 O0 n5 e" \. {
2 R. ]. l( O2 r* U" j
硬件外设的初始化是在 bsp.c 文件实现:7 a! u; p# G  R$ u
3 r4 p# p5 g* v7 T2 d4 u' N# j" Y# q- d
  1. /*8 v! N* n/ Q( ?5 X2 b
  2. *********************************************************************************************************
    1 h, U  c% [$ i1 @
  3. *    函 数 名: bsp_Init
    5 H# Y9 b( u. U% {" n. t% ~
  4. *    功能说明: 初始化所有的硬件设备。该函数配置CPU寄存器和外设的寄存器并初始化一些全局变量。只需要调用一次- K" _" _# I7 N% o
  5. *    形    参:无. \6 X* ~. h" h* n  T: n4 Z
  6. *    返 回 值: 无* P# R: B9 F. a; o3 O7 d% X
  7. *********************************************************************************************************
    8 {9 @8 t+ m  u
  8. */
    # v) N* y: b8 y6 x; i$ }% S
  9. void bsp_Init(void)% F: M3 q6 Y* f5 Z$ U
  10. {# R3 a7 U: C6 }2 _
  11.     /* 配置MPU */2 J& q5 O6 a/ {5 W3 f
  12.     MPU_Config();2 O* g+ y* v+ v6 [  e
  13. 1 Y2 @8 j4 Y0 G' y. T9 h' V% y
  14.     /* 使能L1 Cache */
    " x4 L: y# e/ x+ y+ p
  15.     CPU_CACHE_Enable();
    2 O2 o8 Y0 r3 o$ s3 a9 Q
  16. , D4 K3 k6 P) j7 L' B
  17.     /* 2 U& Q: I; z9 w! K. v) B) C
  18.        STM32H7xx HAL 库初始化,此时系统用的还是H7自带的64MHz,HSI时钟:
    ! ^4 b1 r' Q+ y$ W! W% @
  19.        - 调用函数HAL_InitTick,初始化滴答时钟中断1ms。
    3 A# T  _: N- }7 q
  20.        - 设置NVIV优先级分组为4。% h; H  N+ U5 S/ g) x, \0 o
  21.      */
    3 P: s1 Z9 W* v8 u. `
  22.     HAL_Init();
    ; r5 N6 P& g! P4 k5 D) u) K
  23. 4 n  a% Y7 d3 ?+ j2 Y! T3 i, a
  24.     /*
    " F/ J! r) e7 X6 {$ D/ b
  25.        配置系统时钟到400MHz1 Z0 C6 L- L) |# d" U
  26.        - 切换使用HSE。& ^, g) V' [; f% m0 d. u$ C5 E
  27.        - 此函数会更新全局变量SystemCoreClock,并重新配置HAL_InitTick。
    ! P; O2 c: _8 i9 \+ Z) V
  28.     */  x9 o- f5 Z+ |2 Z, s0 e( g
  29.     SystemClock_Config();
    # f4 Z/ G% n8 \- Q. H
  30. # o, k6 i4 |& ~+ W5 }; D
  31.     /*
    . e# D) i. n' E, f* k
  32.        Event Recorder:
    # Z! e7 S$ s0 J6 @2 J* d- v5 B4 o7 B
  33.        - 可用于代码执行时间测量,MDK5.25及其以上版本才支持,IAR不支持。
    ( N% K* `- P+ n/ B
  34.        - 默认不开启,如果要使能此选项,务必看V7开发板用户手册第8章
    - y) N( B  R  C3 f1 w3 r& K2 B, Q
  35.     */   
      V+ c" W: ]6 Y
  36. #if Enable_EventRecorder == 1  
    # a0 M9 r8 |3 z6 W1 T$ ]4 U$ Q* L( [
  37.     /* 初始化EventRecorder并开启 */- M9 D8 \, U3 @% q0 I  W0 o! ?9 h! {
  38.     EventRecorderInitialize(EventRecordAll, 1U);/ G( C; i; V' N
  39.     EventRecorderStart();
    ) r. g4 Y4 R  ~' P
  40. #endif# y$ ?6 z1 s& R% W' X4 K8 ]# w' c
  41. 0 b( w" |0 B+ H
  42.     bsp_InitKey();        /* 按键初始化,要放在滴答定时器之前,因为按钮检测是通过滴答定时器扫描 */
    & ~* o* G+ L4 I- d' z6 y* T! E
  43.     bsp_InitTimer();      /* 初始化滴答定时器 */
    + G& r2 n) m! H1 o5 F
  44.     bsp_InitUart();    /* 初始化串口 */
    : ^. |! x' `$ p; {; \% P
  45.     bsp_InitExtIO();    /* 初始化FMC总线74HC574扩展IO. 必须在 bsp_InitLed()前执行 */    . d0 \- y2 h4 G: M. _" Z& }, G
  46.     bsp_InitLed();        /* 初始化LED */    + |" X2 I, Z* n1 t$ x* _' _
  47. : c. d$ G! X6 {$ \- s2 `+ |
  48.     bsp_InitI2C();     /* 初始化I2C总线 */
    + `, H- i. V% u/ M
  49.     TOUCH_InitHard();   /* 初始化触摸芯片,LCD面板型号的检查也在此函数,所以要在函数LCD_InitHard前调用 */   o/ P5 n. b" b& g  a
  50.     LCD_InitHard();     /* 初始化LCD */7 `9 x- S; u8 S4 r" A2 A
  51. }
复制代码
) T  s$ b$ \0 v4 L% j8 [* Z
+ x: E1 E3 r3 h  W& C

" d+ H* t& f: g- E: M' p5 q  MPU配置和Cache配置:; \8 M/ N. a) f" F" F/ s# K" G

$ l" R+ M% [: v3 V% H! x* x/ E. [数据Cache和指令Cache都开启。配置了AXI SRAM区(本例子未用到AXI SRAM),FMC的扩展IO区和SDRAM。由于SDRAM要用于LCD的显存,方便起见,直接将其配置为WT模式。
. W# p, K  \) L2 Q8 X7 u
& Z' K2 q$ w9 I3 ]" V
  1. /*$ f+ V. k# @$ ]7 Y7 T  ]; i
  2. *********************************************************************************************************) s% R' r8 B8 B- t2 W0 n4 c% {
  3. *    函 数 名: MPU_Config7 u! \' b0 S  C+ j0 g( C
  4. *    功能说明: 配置MPU/ W% g1 ]" v* ^2 O
  5. *    形    参: 无
    $ ]6 }$ ?$ N3 N( v  r
  6. *    返 回 值: 无
    - [7 C: {: d+ I# t
  7. *********************************************************************************************************8 ^8 ^5 S; T# x9 h4 }$ C: X$ e
  8. */5 o) m' ^. g7 ^  M, m
  9. static void MPU_Config( void )
    9 k+ a6 ~2 j" l/ h
  10. {
    , d- R0 O$ c. L$ Y
  11.     MPU_Region_InitTypeDef MPU_InitStruct;
    3 P& p5 k4 k' l( M

  12. ' Y% l2 m+ x& t3 E3 g4 }: l
  13.     /* 禁止 MPU */
    & _+ A# W& T4 U  C9 E
  14.     HAL_MPU_Disable();
    + [% u6 {: o. j- ], K; T7 D

  15. ! X* ]9 Q4 m- K+ p$ K
  16.     /* 配置AXI SRAM的MPU属性为Write back, Read allocate,Write allocate */
    0 @$ h# j6 ?) [3 o4 s1 y$ i+ A0 i0 o
  17.     MPU_InitStruct.Enable           = MPU_REGION_ENABLE;
    6 G  u+ g. S. w: Z/ i. b
  18.     MPU_InitStruct.BaseAddress      = 0x24000000;$ ]# h0 B  S- P! ]2 Q
  19.     MPU_InitStruct.Size             = MPU_REGION_SIZE_512KB;
    0 Y5 g2 i; r! u" W' Q0 N0 I
  20.     MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS;
    ! t! F: u3 e5 Q
  21.     MPU_InitStruct.IsBufferable     = MPU_ACCESS_BUFFERABLE;7 @/ I. u% }+ O9 S
  22.     MPU_InitStruct.IsCacheable      = MPU_ACCESS_CACHEABLE;
    4 f5 ?6 _2 l! i# u
  23.     MPU_InitStruct.IsShareable      = MPU_ACCESS_NOT_SHAREABLE;4 `2 }7 Y  ^2 U, r
  24.     MPU_InitStruct.Number           = MPU_REGION_NUMBER0;2 R. L+ `3 ]4 Y) @( Q% k
  25.     MPU_InitStruct.TypeExtField     = MPU_TEX_LEVEL1;
    1 G* z5 k# y7 t& n1 D1 y' Y1 ]
  26.     MPU_InitStruct.SubRegionDisable = 0x00;) ?& S8 @/ R% e2 E
  27.     MPU_InitStruct.DisableExec      = MPU_INSTRUCTION_ACCESS_ENABLE;6 q4 l8 I6 x0 u, h$ U" f

  28. . X/ X( ], V% M9 @6 Y" K! b
  29.     HAL_MPU_ConfigRegion(&MPU_InitStruct);8 G# C; `$ ]2 Q% E/ T* b/ d

  30. 6 g8 T* h  ^5 ]
  31. 3 P) j+ @0 }  W* a
  32.     /* 配置FMC扩展IO的MPU属性为Device或者Strongly Ordered */
    - e; u+ n( S6 g, u; k2 _
  33.     MPU_InitStruct.Enable           = MPU_REGION_ENABLE;
    # g- B( k  F% t+ E7 C) v" F
  34.     MPU_InitStruct.BaseAddress      = 0x60000000;
    & N1 V* _1 I+ w) W6 X
  35.     MPU_InitStruct.Size             = ARM_MPU_REGION_SIZE_64KB;    ; h) {7 p( l, `
  36.     MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS;) o' \$ [) e+ p& y
  37.     MPU_InitStruct.IsBufferable     = MPU_ACCESS_BUFFERABLE;
    0 D* e" ]2 f5 {/ V) z- `3 h' N
  38.     MPU_InitStruct.IsCacheable      = MPU_ACCESS_NOT_CACHEABLE;   
    6 N6 i7 `8 x. `( Y6 Z8 ]+ a( t% p
  39.     MPU_InitStruct.IsShareable      = MPU_ACCESS_NOT_SHAREABLE;: N# ?% ~: ]2 v; v# z+ ^* n
  40.     MPU_InitStruct.Number           = MPU_REGION_NUMBER1;
    , T' L/ b% V" ^2 f% G
  41.     MPU_InitStruct.TypeExtField     = MPU_TEX_LEVEL0;
    ! y2 t# u. \4 p
  42.     MPU_InitStruct.SubRegionDisable = 0x00;% v7 |$ a7 f9 }# I1 A0 ~
  43.     MPU_InitStruct.DisableExec      = MPU_INSTRUCTION_ACCESS_ENABLE;
    2 o( p* E0 `! L& K4 h

  44. ) k5 R; f1 f, r5 v
  45.     HAL_MPU_ConfigRegion(&MPU_InitStruct);3 i$ o$ h  R* B0 K
  46. * W) C! R/ p# h) g6 d
  47.     /* 配置SDRAM的MPU属性为Write through, read allocate,no write allocate */
    4 H9 `& z& k: t# M* o" s
  48.     MPU_InitStruct.Enable           = MPU_REGION_ENABLE;) W6 O$ E  P5 i; K  o
  49.     MPU_InitStruct.BaseAddress      = 0xC0000000;
    $ k# p4 J5 a" x; Y9 Y! F
  50.     MPU_InitStruct.Size             = MPU_REGION_SIZE_32MB;
    / ~4 U' F# H; b9 \/ L
  51.     MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS;
    ( e6 ?. W# Z0 Y$ [$ {$ H! B8 g
  52.     MPU_InitStruct.IsBufferable     = MPU_ACCESS_NOT_BUFFERABLE;& m7 g* q- L4 U$ H- d8 s% t
  53.     MPU_InitStruct.IsCacheable      = MPU_ACCESS_CACHEABLE;6 {/ E/ W- ~+ t! k( j( l$ ]
  54.     MPU_InitStruct.IsShareable      = MPU_ACCESS_NOT_SHAREABLE;% I9 v( G! t- z9 u6 P: s- v
  55.     MPU_InitStruct.Number           = MPU_REGION_NUMBER2;
    / z4 h. p; O+ m# ~' x0 f! x; V
  56.     MPU_InitStruct.TypeExtField     = MPU_TEX_LEVEL0;. b$ ]! L, f3 g: Z; }% X
  57.     MPU_InitStruct.SubRegionDisable = 0x00;+ i8 F8 s, g; \$ T% a+ a# U
  58.     MPU_InitStruct.DisableExec      = MPU_INSTRUCTION_ACCESS_ENABLE;  T! R# [2 y+ l9 Q; _

  59. ) A7 b# m: i% p% B
  60.     HAL_MPU_ConfigRegion(&MPU_InitStruct);
    " c8 S7 `% u; z' p/ }' G
  61. ! _9 o8 m3 _3 ]6 [8 |: t2 J
  62.     /*使能 MPU */
    + A- C, V/ s  j& Y1 L
  63.     HAL_MPU_Enable(MPU_PRIVILEGED_DEFAULT);
    7 o7 o7 O6 Z0 s8 B! p- J) D3 x) n
  64. }* r8 N3 d4 q' C9 \* Z" `8 x2 A

  65. 7 c  O( ^4 g- K, k; F; n( v
  66. /*# h; J# @1 p0 \; i
  67. *********************************************************************************************************+ O& X- A( H* T) K4 R9 w
  68. *    函 数 名: CPU_CACHE_Enable
    # T" z$ e+ y! z$ r
  69. *    功能说明: 使能L1 Cache$ g. ~3 z# P0 h& A/ B' y% y
  70. *    形    参: 无% o9 I$ @3 s) ~
  71. *    返 回 值: 无
    ) d# \; r( v9 T/ ~' u! j
  72. *********************************************************************************************************: l% M  U5 {% g7 S
  73. */
    5 T4 k3 G3 \# [( V' B5 S
  74. static void CPU_CACHE_Enable(void)8 x, `/ C, k1 g) y6 q8 B  N' N# ~
  75. {0 u5 K2 J& f! I8 m" y) P
  76.     /* 使能 I-Cache */
    ) y4 G( W* l. g
  77.     SCB_EnableICache();( i0 K* O. J% G  q3 }* r* M

  78. 3 i' N. e- s5 h
  79.     /* 使能 D-Cache */
    2 p: ?! _4 G& Z9 f
  80.     SCB_EnableDCache();! H+ p* f' N2 o( l& n
  81. }5 a6 H' {4 a$ C4 d2 G
复制代码

* a0 [( w) V; L' r7 w: T3 L1 n" Z! s2 p
  主功能:
: c4 _' B$ k/ l
( ]1 A% Q9 C3 u6 X2 v; j. O1 v2 ?主程序实现如下操作:4 O+ Y" s5 F3 s  S
# d6 m8 W5 n7 e! |
  LCD界面上展示ASCII字符和GB2312编码汉字
! b# W- D5 `& ?) H  启动1个200ms的自动重装定时器,让LED2每200ms翻转一次。
" ?8 h1 I: a7 W; a  通过按键来实现翻页功能,方便查看所有GB2312编码汉字。# a: F) \! d+ G" ~8 \' v- F
  1. /*& c4 \4 a- I7 b- _! [! h8 f: R: U" L
  2. *********************************************************************************************************+ y! Y- S4 q! M4 P9 k
  3. *    函 数 名: main0 n9 g9 E4 H5 [9 S5 b
  4. *    功能说明: c程序入口
    ( `4 ?5 \7 Y# O' h! u2 [+ g
  5. *    形    参: 无
    - o1 h. l0 {% _: W6 }  Z
  6. *    返 回 值: 错误代码(无需处理)
    % N+ k5 l; G  f0 e2 z
  7. *********************************************************************************************************
    6 C- w0 ^( p1 ^  q' G0 |
  8. */& k. z+ X3 n* F" |/ W( q
  9. int main(void)
    9 N6 J1 F5 v6 r* [' g" J" D
  10. {
    ! ]# \$ a3 T- m' v
  11.     uint16_t ucBright;           /* 背光亮度(0-255) */
    % A+ ^8 @" b- V8 Q
  12.     uint8_t ucKeyCode;        /* 按键代码 */# _1 K+ p  @4 E# {2 V2 @  @
  13.     uint8_t ucStatus;        /* 主程序状态字 */
    6 b1 B4 m4 K+ J+ t# l
  14.     uint8_t fRefresh;        /* 刷屏请求标志,1表示需要刷新 */3 N, v3 L/ L4 O& [4 X

  15. . K9 u4 S, a0 ]$ I  d1 e/ c
  16. / [/ _. C' W% T! C  e
  17.     bsp_Init();    /* 硬件初始化 */' N: Y0 ]) ^& }  F: h
  18.     PrintfLogo();    /* 打印例程名称和版本等信息 */
    * l, z8 i( \3 q) I- c. N4 C% _
  19.     PrintfHelp();    /* 打印操作提示 */5 D1 M- J) O( T/ U3 T
  20. 3 Y+ B; B1 f% x+ J- r1 }! j
  21.     /* 延迟200ms再点亮背光,避免瞬间高亮 */* B. P7 j/ Q9 `$ X2 E5 Y
  22.     bsp_DelayMS(200);
    * m* s0 K* d0 y) O. @8 V

  23. 4 ~5 G4 g8 y0 ^3 X' f5 B3 b4 A
  24.     DispFirstPage();    /* 显示第1页 */
    ' \# F! S) w: M2 K6 U, b

  25. ! b1 S+ S  P! ?! L
  26.     /* 界面整体显示完毕后,再打开背光,设置为缺省亮度 */
    4 L. L, y* y- n  F6 B) r6 v- {
  27.     bsp_DelayMS(100); 3 \! b1 [/ D! c  S0 N' y8 {. v
  28.     ucBright = BRIGHT_DEFAULT;
    8 A, B% R  l. ^6 {  A+ J
  29.     LCD_SetBackLight(ucBright);4 q/ Y  b9 v/ D: v5 P( s

  30. # ^  c3 Q* I' x3 R9 G
  31.     bsp_StartAutoTimer(0, 200); /* 启动1个200ms的自动重装的定时器,软件定时器0 */7 z# J' C- F9 T
  32. ' ?; l) _* M2 S+ t7 j1 w
  33.     /* 进入主程序循环体 */
      C3 C% v' ~2 q( a* u; ^$ }
  34.     ucStatus = 0;" P' A0 l4 C( x) a
  35.     fRefresh = 0;   
      n5 h3 M7 a  C4 M; N1 R2 Z
  36.     while (1)+ L! E+ D- t: D) V$ I- p
  37.     {, s2 m* J* }! Q
  38.         /* 判断软件定时器0是否超时 */
    9 O6 y" n  _$ ~$ Y! q  K
  39.         if(bsp_CheckTimer(0))2 }* |$ h6 I; ~7 ?
  40.         {
    + M) ^0 U: ]: n7 y5 I0 a
  41.             /* 每隔200ms 进来一次 */  9 z: h  O" r, c- b  n  B
  42.             bsp_LedToggle(2);- ]( J; h# D3 b
  43.         }
    $ r. X0 M8 h5 z* H

  44. 7 o4 P& R8 R) F7 X- M
  45.         if (fRefresh == 1)5 r. H: R* r# b4 w; i
  46.         {
    2 R( C, f* I9 q7 o. V* e
  47.             fRefresh = 0;: e% G& x8 c9 Z7 |  j  n
  48. 9 ^! {, Q4 n+ v+ H
  49.             switch (ucStatus)
    7 Q  k9 d$ J- c( X  R! T! ~% ^
  50.             {
    : ]0 \# q8 h# V1 t6 C3 ^
  51.                 case 0:
    ( k1 N' F" H0 `6 k3 L
  52.                     DispFirstPage();    /* 显示第1页 */
    + t7 O4 j* [9 Q( _! C7 A+ R
  53.                     break;: [0 `8 s$ y" [( |+ d
  54. - {' |5 Q3 H& ^, e, H
  55.                 case 1:) K8 |- W; O3 n  |( c- _, r2 _
  56.                     DispAsciiDot();        /* 显示ASCII点阵 */1 `3 g. q6 n6 t
  57.                     break;( h, W4 b- f) R) ^; D
  58. ' @# _& O3 \) X& v9 G8 O: n, ^
  59.                 default:
    4 N5 r7 b. H6 s" d& e7 V
  60.                     /* 区码范围 :1 - 87 */# M& F4 c' P' b* L& L$ ~
  61.                     if (ucStatus <= 89)
    # L$ o* Y, T( d2 N4 [4 @( F
  62.                     {
    9 F+ O) S/ \2 z0 m
  63.                         DispHZK16(ucStatus);    /* 显示一个区的94个汉字 */
    $ L1 M5 ?1 i. K8 }! ?# @8 S
  64.                     }
      i7 N, `1 |9 H; Y$ z0 A. A( K
  65.                     break;
    % ]: P- e5 a; l9 n3 q. \( q
  66.             }
    * h* N2 Q: o  L. o
  67.         }# W! W' P' D) L' z: a& t

  68. - S' i# Z6 O' E/ x
  69.         ucKeyCode = bsp_GetKey();    /* 读取键值, 无键按下时返回 KEY_NONE = 0 */- a8 u2 H2 H$ R
  70.         if (ucKeyCode != KEY_NONE), n6 m/ T1 }' T" w0 H# x
  71.         {) m. |* m/ h$ \$ j. r) E
  72.             /* 有键按下 */0 u- q& X) X- i) R: b+ }. O
  73.             switch (ucKeyCode)
    4 `% [9 k; Y, r" Q/ P
  74.             {
    3 c7 _5 h$ i; K. N3 D
  75.                 case JOY_DOWN_L:        /* 摇杆LEFT键按下 */4 C; }0 W: R, ^% @1 f0 m
  76.                     if (ucStatus > 0)% F- m8 |5 S8 B# ^9 s& P( b/ g$ z
  77.                     {) \) Q9 [; J/ |+ f
  78.                         ucStatus--;
    5 C! L2 n  f. m9 u# u  e
  79.                     }
    % ?5 q4 \' B- ^% Z5 m
  80.                     fRefresh = 1;        /* 请求刷新LCD */, p! u7 [; q% w: c* `0 I8 r+ j
  81.                     break;
    # c6 ^% _- f/ @2 ^; Z# V+ Z
  82. + N" L! s1 O7 P* b* m$ T
  83.                 case JOY_DOWN_R:        /* 摇杆RIGHT键按下 */. s5 u* Y" b: ~+ W/ r
  84.                     if (ucStatus < DEMO_PAGE_COUNT - 1)
    ) f( a4 u4 J1 Y+ w
  85.                     {
      _1 G9 @' _% I/ B* l, a! Y: x
  86.                         ucStatus++;
    8 z4 A. m/ ?% {, |0 R$ z
  87.                     }
    7 a. }5 c# r8 |1 j
  88.                     fRefresh = 1;        /* 请求刷新LCD */
      _: i5 P1 f' K' W; j( n
  89.                     break;) }, }4 [' g8 ^6 ?/ p* P

  90. . z' j. S3 S7 _" c) f& r$ Q. L" v
  91.                 case  JOY_DOWN_OK:        /* 摇杆OK键 */
    0 Y: k, T! ]6 j! I1 `. f+ s& g
  92.                     ucStatus = 0;        /* 返回首页 */                    
    5 z$ O7 u& w: ?& n
  93.                     fRefresh = 1;        /* 请求刷新LCD */
    3 T1 v6 W, C0 }- |- `1 ?; [% `
  94.                     break;$ `! P2 K7 z% e) c2 F6 K
  95. 5 |  B; d, J; J( D7 {% @
  96.                 case JOY_DOWN_U:        /* 摇杆UP键按下 */$ T5 g" z# E( }% a; x
  97.                     ucBright += BRIGHT_STEP;$ r; M4 |) H8 s
  98.                     if (ucBright > BRIGHT_MAX)
    3 n4 j( v& d7 e; N" n% i1 b  }
  99.                     {
    1 e8 r5 g( k3 [7 B2 a8 ?5 u2 D
  100.                         ucBright = BRIGHT_MAX;
    $ ^$ e1 T' w! a2 l1 e! o! f  M0 P
  101.                     }
    3 y7 V6 [; Q$ E# _1 X
  102.                     LCD_SetBackLight(ucBright);9 w' G; z- V2 u7 X0 {3 i9 K
  103.                     printf("当前背景光亮度 : %d\r\n", ucBright);4 @# Q% t% d- j5 k( `
  104.                     break;
    % ^# P+ n5 P3 \, |2 G: p

  105. 6 x$ \- G$ m2 M, i
  106.                 case JOY_DOWN_D:        /* 摇杆DOWN键按下 */) Y, Q  }1 W4 X4 l) n
  107.                     if (ucBright < BRIGHT_STEP)
    $ T/ x0 d' W- k1 r
  108.                     {6 w$ C: Q+ P" \/ p- I8 X+ V
  109.                         ucBright = 0;+ ]$ n* l! k8 w; f) h0 _
  110.                     }
    ' _0 E3 s8 _$ u; o& ^
  111.                     else
    8 z/ T6 Q' n+ n  A6 \- ?
  112.                     {
    ' `& U1 T9 ]4 B  {; T7 k
  113.                         ucBright -= BRIGHT_STEP;
    ! f0 C3 j8 J, l8 R: ~5 U( B
  114.                     }' ?1 g8 X" g, q* y
  115.                     LCD_SetBackLight(ucBright);
    - \7 O$ }( q# [# T8 h- K0 ]
  116.                     printf("当前背景光亮度 : %d\r\n", ucBright);
    % Z- K1 C& i8 E) i# Z
  117.                     break;; |" K# ~+ z$ U4 ^0 y9 T, \- z
  118. ; U  u. G$ s0 e, O. |2 k" I
  119.                 default:
    + _# d8 z3 a; |  |3 f  S" Y& @4 a
  120.                     break;
    5 V" H- N8 @/ J! T) J$ x' h. w" G
  121.             }
    # C  Z0 I' l4 V+ l
  122.         }' ]9 k5 V& [+ K6 ?$ ]% \/ z2 w5 ^
  123.     }
    7 w* y$ l# U+ t* m, }5 C
  124. }
复制代码

' o8 _0 c* p4 U# R8 l" t# B3 W9 K" e# l

9 p4 ?. l: ~, m% j7 f下面的代码用于LCD首页显示:
; p9 d8 _6 w  V, _1 P1 Q7 s  D. N1 L$ {* W9 ]/ L
  1. /*& x- q0 p$ s8 x; _( p" g
  2. *********************************************************************************************************
    2 w) [8 z  @# X6 g( ~3 h
  3. *    函 数 名: DispFirstPage
    ! R8 z2 Y) N6 h% L4 W" |: L
  4. *    功能说明: 显示操作提示
    ) _1 Y3 X8 T  h% b) ]
  5. *    形    参:无' A6 i$ I& _# g5 F
  6. *    返 回 值: 无/ {0 l; k% h* U- W2 b6 G: p
  7. *********************************************************************************************************
    9 A. k/ N/ U4 M, k+ s
  8. */
    7 b' f2 L7 p: }7 @& t
  9. static void DispFirstPage(void)
    7 D; C; a7 x, j. @7 H6 P
  10. {
    / g8 M1 O: d9 ]
  11.     FONT_T tFont;            /* 定义一个字体结构体变量,用于设置字体参数 */
    & X( Y* _- }+ j
  12.     uint16_t y;            /* Y坐标 */
    + q7 j9 F% O, w; G6 v7 X% }: I
  13.     uint16_t usLineCap;    /* 行高 */% H+ |( Z- d+ J0 F; q, y
  14.     uint8_t buf[50];
    * ?* Q- ]! ^) X- D+ h. D1 L4 U

  15. . O4 F! I, k- h5 x
  16.     LCD_ClrScr(CL_BLUE);          /* 清屏,背景蓝色 */
    5 j) j, T7 A  R/ U
  17. 7 E$ j5 E2 V' o0 ^) ^+ U: I, x" S

  18. , S  w7 |/ ?% b+ \0 [" z$ X' `
  19.     /* 设置字体属性 */
    : ?- c3 O6 ?, r  i/ ]
  20.     tFont.FontCode = FC_ST_16;        /* 字体选择宋体16点阵,高16x宽15) */  u, m! s/ l/ B0 h8 y
  21.     tFont.FrontColor = CL_WHITE;    /* 字体颜色设置为白色 */" V- ]/ p$ b) o) G0 I  y( }. J
  22.     tFont.BackColor = CL_MASK;         /* 文字背景颜色,透明 */6 S7 w% X2 ]: \0 A, U
  23.     tFont.Space = 0;                /* 字符水平间距, 单位 = 像素 */
    5 d" w$ w& G# m
  24. 8 A$ E0 N7 w  [0 G
  25.     y = 0;
    : Y; e" X9 a0 ]9 Y
  26.     usLineCap = 18; /* 行间距 */
    . s3 i3 t: Y7 |' I) m
  27.     LCD_DispStr(5, y, "安富莱STM32-V7开发板  <a href="http://www.armfly.com" target="_blank">www.armfly.com</a>", &tFont);' ]: a5 z$ _9 G) i% E- F9 V
  28.     y += usLineCap;2 N' E# f7 V0 g
  29.     LCD_DispStr(5, y, "汉字小字库和全字库测试实验", &tFont);
    3 ?3 L4 P0 H7 y  d( Z) Y' x. P2 `

  30. * o& u- O  n& x2 J, G- I# I/ f) ?
  31.     y += 2 * usLineCap;
    7 E, \; m& s" T! D& b  q6 c
  32.     LCD_DispStr(30, y, "操作提示:", &tFont);) d# r2 j1 Y3 k4 W8 H8 Y; |! k

  33. * \2 B5 Y8 N  `( c$ E# q: t7 ^3 b
  34.     y += usLineCap;1 P3 T, W! b4 y) C
  35.     LCD_DispStr(50, y, "摇杆上键 = 增加背光亮度", &tFont);
    % K* y9 A2 t% g8 S& I
  36. 6 h8 ]3 @3 {  U4 M8 \- p  ]+ O
  37.     y += usLineCap;
    ; M5 d, C, U) e  Q% q
  38.     LCD_DispStr(50, y, "摇杆下键 = 降低背光亮度", &tFont);
    1 \1 ?- G3 _+ N3 M6 V
  39. 0 m, w, b: n. K. L
  40.     y += usLineCap;
    ( T0 A1 l& Z, s' C  j* J
  41.     LCD_DispStr(50, y, "摇杆左键 = 向前翻页", &tFont);
    7 }+ |/ m, t4 j% y8 ^: x' K

  42. ( m) H$ G" q) u, a* O
  43.     y += usLineCap;
    4 ^  Q) K. a7 p( x8 u. l
  44.     LCD_DispStr(50, y, "摇杆右键 = 向后翻页", &tFont);! Q5 U/ c. J3 m$ u
  45. ) P3 I3 u/ P  A9 }
  46.     y += usLineCap;
    9 o$ Z& O1 K7 o, g! F
  47.     LCD_DispStr(50, y, "摇杆OK键 = 返回首页", &tFont);
      r6 s! C, o$ d$ K  d( c4 P0 ]5 m
  48. ) [# E; L# |5 E5 w; T
  49.     y += 2 * usLineCap;   
    - d7 E1 i' S0 I4 p8 t! f. ~

  50. # u! P, g% J! H+ x7 n6 _; ^8 N. `
  51.     sprintf((char *)buf, "显示器分辨率 :%dx%d", g_LcdWidth, g_LcdHeight);
    2 G+ |% ]: `+ ]
  52.     LCD_DispStr(5, y, (char *)buf, &tFont);
    : b3 Z- L" T; d/ L. A8 K

  53.   H) [& C! W/ S4 s
  54.     y += usLineCap;. t5 z# K0 y9 H
  55.     LCD_DispStr(5, y, "每行可以显示25个汉字,或50个字符", &tFont);% {9 f: n1 O8 j
  56. }
复制代码
: _3 t! V0 N0 ]( ^3 B

7 S/ |* n) Q) f& F4 x1 X
9 s8 j6 k4 a; }# |5 s下面是ASCII字符显示:' g/ N) x, o$ B- ^& X( P9 j

5 N' U. f* P$ I, N
  1. /*# |+ S* |) q: \6 w9 H2 W+ y
  2. *********************************************************************************************************
    . O. k! s: ]# V
  3. *    函 数 名: DispAsciiDot
    ( j' T% J; n* N; B7 a* y3 k* S! H& G
  4. *    功能说明: 显示ASCII点阵2 y, x9 b5 [& i6 x4 l/ M! ]: O
  5. *    形    参:无; P% u8 r  R: W
  6. *    返 回 值: 无$ G: |: V7 P" V
  7. *********************************************************************************************************
    , V8 {+ d9 ]: ?; q7 M$ ~2 D" o( Z% w
  8. */
    : E& K8 U% y# D0 e
  9. static void DispAsciiDot(void)
    ! O) a; P6 S7 U* F7 L) ?
  10. {1 i( k8 {+ t/ f0 h
  11.     uint8_t i,k;# B3 m2 f# D% u  q2 B3 M6 \- B
  12.     FONT_T tFont;        /* 定义一个字体结构体变量,用于设置字体参数 */
      r/ E2 x+ u2 t3 e7 k; I
  13.     uint16_t x;        /* X坐标 */  R, n9 s; t0 X& Q
  14.     uint16_t y;        /* Y坐标 */    1 Q0 q1 N' n; R6 K: |
  15.     char buf[32 + 1];0 I8 ?2 r9 r& a8 ^( c) Q6 W
  16.     uint8_t ascii;
    9 t+ G7 W  _1 Y) C1 O+ \; |
  17. 7 n  Q5 f# Z  o/ k' [
  18.     LCD_ClrScr(CL_BLUE);          /* 清屏,背景蓝色 */
    , H  y# @) L- V( v* U5 ?9 W7 v: l# ?

  19. + {' w3 j* C, s) E4 P' P: d& X& ^
  20.     /* 设置字体属性 */
    # {  u( t3 v& {, F: X# {* i1 Y% F: s
  21.     tFont.FontCode = FC_ST_16;        /* 字体选择宋体16点阵,高16x宽15) */$ T) x. J6 B, L4 D; Q% r
  22.     tFont.FrontColor = CL_WHITE;    /* 字体颜色设置为白色 */4 q! H" Q! s- i: j5 H! x- R
  23.     tFont.BackColor = CL_MASK;         /* 文字背景颜色,透明 */6 ^- i' a. x. W6 E: S4 _# D/ N$ ~( }
  24.     tFont.Space = 2;                /* 字符水平间距, 单位 = 像素 *// ]* ~% w4 X# ]3 G' N

  25. ) s6 G( t/ a9 `; M6 m; ]
  26.     LCD_DispStr(50, 0, "16点阵ASCII码字库,代码1-127", &tFont);* T. r4 ~$ D$ F2 m/ J
  27. ) @& V8 m4 k3 A$ ^8 a
  28.     x = 50;6 k* c" L8 P* n/ i4 a& `0 a% A
  29.     y = 40;
    ; D) G5 X3 S9 \# K% W  d; W
  30.     ascii = 0;
    4 l4 {, a0 l; P' U+ A0 ^) L
  31.     for (i = 0; i < 4; i++)- t( x, W9 E( \- k" e/ b, [: ^
  32.     {& k2 ^5 S3 d8 ?6 P* P- B& c
  33.         for (k = 0; k < 32; k++)
    # R  I8 c5 P( K$ V
  34.         {! @" M! D7 g9 m4 u/ g5 n( ~: |, O8 ^
  35.             buf[k] = ascii++;$ X: k# a- ^% K! c( c, s
  36.         }
    + L- Z, R. P" f2 U& U: D
  37.         buf[32] = 0;
    ' t; U* j) q5 M& p
  38.         if (buf[0] == 0)/ c3 ^* P- p  ]* v
  39.         {" u( m/ r( {* l7 l% x
  40.             buf[0] = ' ';
      z' H. B9 p* _5 M( K8 [
  41.         }
    / V. p5 g( E+ M' V
  42.         LCD_DispStr(x, y, buf, &tFont);
    4 M; u. y% p1 l( i; b
  43.         y += 20;
    7 E7 x9 X1 F# c5 R( Y7 f
  44.     }* W. }# _' R, S- e6 ^
  45. }
复制代码

% ~, T) N0 T0 i" ]0 j
3 y* }0 A4 n% F2 M7 v3 l# H/ z3 L% g
下面是GB2312编码字符显示:
8 V+ w+ Q& [0 M9 a  r
. S- H: j" J9 e/ ~
  1. /*/ n# \/ [5 t$ D
  2. *********************************************************************************************************
      i5 U% g# ^+ _1 ^6 }
  3. *    函 数 名: DispHZK16
    ( a- i  j; {3 L/ I/ ?4 @# k
  4. *    功能说明: 显示16点阵汉字阵  d: H' d2 C! m- i- i1 O- o+ O
  5. *    形    参:无
    6 P" `% z' S* p7 l! T
  6. *    返 回 值: 无
    , p/ c6 l2 }2 o6 C: r
  7. *********************************************************************************************************) O9 k0 r7 U" W& |
  8. */
    % n; Y3 r) D6 E6 g
  9. static void DispHZK16(uint8_t _ucIndex)
    7 E3 G9 s4 }! J0 q$ C  x
  10. {& z6 |# d" F) d( u& H0 E! S( y8 z/ b- R
  11.     uint8_t i,k;
    , n5 ^% Q6 `1 c0 F- g' ~; w
  12.     uint16_t x,y;
    ) p' Y. g: ~5 x/ G
  13.     char buf[50 + 1];8 g; @* ]! }: ^4 T. ?$ P
  14.     uint8_t code1,code2;    /* 汉字内码 *// t6 Z, s  S% f; C
  15.     uint8_t usLineCap = 18;( b0 u/ D4 ?" S% D7 P3 k
  16.     FONT_T tFont;            /* 定义一个字体结构体变量,用于设置字体参数 *// W- _' n, W! E  G3 E

  17. 3 M3 P6 S- k% H5 |3 y
  18.     printf(" Display HZK Area Code = %d\r\n", _ucIndex - 1);
    : e/ j) @7 e* @* N* @

  19. ) C$ q, \! C& I! s5 t. X
  20.     if (_ucIndex == 2)" G5 b. n$ J8 A' K
  21.     {
      }' u$ Q6 P/ `
  22.         /* 第1次清屏,以后显示位置不变,可以不清屏,避免闪烁 */! U2 n  t9 v7 v: R
  23.         LCD_ClrScr(CL_BLUE);          /* 清屏,背景蓝色 */
    * R0 f; d. Y3 n" E. `, Q
  24.     }
    ; T7 v1 d, X5 H

  25. 1 o2 H9 H; u8 ^1 S) p; B3 u
  26.     /* 设置字体属性 */* {' x$ s. L7 y+ K6 W. c0 Z+ r
  27.     tFont.FontCode = FC_ST_16;        /* 字体选择宋体16点阵,高16x宽15) */! T3 W+ h7 c& \' ^  s' S
  28.     tFont.FrontColor = CL_WHITE;    /* 字体颜色设置为白色 */9 E% S, c: Z1 g" x* v7 x$ j
  29.     tFont.BackColor = CL_BLUE;         /* 文字背景颜色,蓝色 */
    ! L/ ?8 p! I* k/ [% J$ m; ~
  30.     tFont.Space = 0;                /* 字符水平间距, 单位 = 像素 */
    & V# ?$ {" e' t6 X' `" ~
  31. * d! {6 m  n) p( F, B5 R) @3 L
  32.     y = 0;! c% |2 R8 x: l( o
  33.     LCD_DispStr(20, y, "国标GB2312 16点阵汉字库(区码1-87,位码1-94)", &tFont);
    $ v& X! l7 ~! D# `
  34. * J+ x$ D" Z% |, }8 O
  35.     code1 = _ucIndex - 1; /* 得到区码 */; B/ e* k5 r9 z1 A
  36.     code2 = 1;            /* 位码从1开始 */
    6 A  W  n) }6 [. L9 j$ I0 q

  37. + Z' _* o  X/ N) t
  38.     y += usLineCap;
    1 P% x0 k4 b* N# r5 t
  39.     sprintf((char *)buf, (char *)"当前区码: %2d, 本页位码:1-94, 第10-15区无字符", code1);- @8 a6 `) d6 Y/ n* \5 Y% [/ F3 g
  40.     LCD_DispStr(20, y, buf, &tFont);
    ' V5 \# A+ O( |3 g) m  J1 T  w
  41.     y += (2 * usLineCap);+ V( b7 z" T% E1 k/ m( c8 G7 ~. a
  42. ( Q0 W+ P$ D5 n) [" a
  43.     /*  x# m/ s2 k5 ^- x) w0 A- R
  44.         机内码高位 = 区码 + 0xA0. `; e2 L0 d4 f. O6 b$ M( e0 g# H
  45.         机内码低位 = 位码 + 0xA0
    2 Q9 N8 G' X2 C* p+ w

  46. 8 X( e* q6 v; l; M4 M  L2 F& s% B
  47.         区码范围 :1 - 87. t4 A  q* F( b  t4 i" @: b* B4 u3 N
  48.         位码范围 : 1 - 94
    : w  j/ u* \3 w

  49. $ \6 _" k) r. \4 I5 i
  50.         每行显示20个汉字,一个区是94个汉字,需要5行显示,第5行显示14个汉字9 J5 ]& M: {# W' }' K& T: L0 G. \
  51.     */) N+ ^5 d' B( _8 t1 A5 O, s" @

  52. 2 _- d7 l5 k3 H% [/ W
  53.     x = 40;
    3 P6 m: j* [$ Q
  54.     code1 += 0xA0; /* 换算到内码高位 */
    : O; O  g6 J8 R! v; f$ O0 J
  55.     code2 = 0xA1;  /* 内码低位起始 */
    ! w4 D  h% }+ l) @
  56.     for (i = 0; i < 5; i++)
    . u6 p. I% ~/ n* x: e
  57.     {
    : o; s( y& z% E- k$ ]
  58.         for (k = 0; k < 20; k++)9 r* M; T* D  k& |2 R
  59.         {
    # c: Y5 D  x/ C' w
  60.             buf[2 * k] = code1;+ O: |5 u2 S! D" a2 f, |! F) |
  61.             buf[2 * k + 1] = code2;
    8 S3 g: Z& ~0 j6 O) h" m0 g
  62.             code2++;
    $ x0 I7 V* J+ K" l; W0 \
  63.             if ((i == 4) && (k == 13))+ Y8 w& L8 t; G  g' g4 g
  64.             {
    ; G$ [2 O* @$ S( n1 s0 j
  65.                 k++;. B8 N* F# u- s4 m
  66.                 break;* H1 ~/ [) k# Q. m- g8 p5 k
  67.             }/ h" s& K9 _+ A6 N$ F
  68.         }
    ! v' d+ S6 v( n
  69.         buf[2 * k] = 0;' [9 r. E* O3 x3 r1 {
  70.         LCD_DispStr(x, y, buf, &tFont);1 M5 ?6 L* b9 f0 k6 x; a
  71.         y += usLineCap;$ S, T  Y0 ~" e3 m; {  X
  72.     }: x5 q( J" z% N3 z! d! p5 F. ~
  73. }
复制代码
' }7 s' J2 F8 z0 ?( S# k$ t
3 \% S5 X4 t, L. K: z5 [

- C) @/ `$ X1 N+ P53.10   总结
1 |/ w: M) q6 ?本章节涉及到的知识点比较多,需要大家花点时间去掌握,直至可以独立驱动一个显示屏。
$ k2 a! ^8 z$ h! ^
# Q- x4 J8 @  e. d# ^6 p" Q1 {% u3 W4 b* g
aHR0cHM6Ly9pbWcyMDE4LmNuYmxvZ3MuY29tL2NvbW1vbi8xMzc5MTA3LzIwMjAwMi8xMzc5MTA3LTIw.png
赞 收藏 评论0 发布时间:2021-10-31 17:42

举报

0个回答
关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
人形机器人运动控制、感知与智能配电
半导体创新技术与应用方向
EE架构与软件定义汽车
12V/48V 汽车智能配电(SPD)
区域控制单元(ZCU)与分区架构
关注我们
st-img 微信公众号
st-img 手机版