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

STM32项目设计:基于STM32F4的电子阅读器制作教程

[复制链接]
STMCU小助手 发布时间:2022-8-15 19:42
一、项目功能要求
" }7 R4 M5 x6 W& O项目说明:
1 D' w9 i$ A3 M" y项目偏软件,但是要依赖于自己对硬件的熟悉和驱动才能完成

& z& x0 O) a- ]0 j7 S& }用到的主要技术:
& I4 C0 z, B4 P% c% CSD卡驱动(难–不过可移植 SD卡驱动细节可在用完再了解其驱动协议)
+ p  ^% Y' a0 c2 d0 r$ q- JFatFs文件系统移植使用
. ~- P) n- ~! F, {( {0 y1 ZLCD屏驱动(加载字库文件 做字库在LCD上的显示)

3 H% q, n; b7 I
& `* Y# R0 d# J! m. x/ E! K功能要求:
1 i- T2 x) n& ^9 i9 C% f7 L开机Logo
0 l: P# T, L! D电子书列表扫描
0 g( W6 _/ ]. N: n5 E电子书列表显示及小说选择菜单+ }1 V! i8 g/ i2 s& Z" \6 J
阅读功能:9 _$ A2 i# M: b# [4 {! v" |7 Z7 d
字体选择
& n5 A# L" g- ]* E9 s% P字体大小选择
( F) |* J. X8 F! y! K字体颜色设置
) C/ j/ i0 y5 q0 L" j阅读背景设置3 B7 b3 H# z) E2 i6 q+ y7 X
书签设置
# z3 a6 W: U/ S1 V- ~8 T能够记录每本电子书的退出时处于什么阅读位置 下次进入从该位置继续阅读; [1 c$ w9 U( C' r) Y) ]
目录生成功能(字符匹配)8 J, z  e5 y: ~2 O5 D. ^
章节跳转功能(基于目录生成功能), m% k% D1 I  L4 h
阅读翻页设置(滚动/切换)
6 `9 L! Q: m& a3 j
8 P- n3 M# ?$ a8 L4 L' u  f
二、材料准备
2 o( D, J& m3 s* n+ g- ^7 q1、普中STM32F4ZGT6最小系统板一块(或者其他STM32F4板子)) R* @, k+ O* g0 ?
(注意要买能插LCD屏的)( ^9 m1 g) a+ I0 U! Z. R
作用:主控芯片、处理各种数据# Q* {- D3 G' n( K* M1 v
2 ~* O/ `% A6 R# l
4JD9F[NFX]UH}9G2CQAFARS.png 5 F8 D7 q/ {/ \1 p

- W( S5 r' f# E7 h2 Z' T3 C2、800*480 4.3寸电容触摸LCD屏(我用的正点原子的屏)
1 m5 ^( u+ Z# Q) ]3 k5 o7 Y作用:显示与触摸控制

; @3 T. D, X2 L: h. c( N$ Q5 s, k6 E- x# C% }
4 L4 ?2 O- l5 ~: H
UYQL2~X(IYQ4OZ`QQM)N38E.png
7 E$ l- H/ V$ t9 S' V; I; x2 g0 q- I8 t
3、一张32G以下的SD卡和一个读卡器
# K. ?8 q8 J! z
) _# z! n& I& b( W作用:存储小说文件与图片文件4 }% c3 F2 V; c; q6 g# I5 S- }

2 n0 l* q% [- q4 i0 j3 f, |) f JN0_R81S2)T7@SX%]G4T[DF.png
+ O6 |8 c: i+ C2 p. ]: e
. O' I" P$ P& G* m* V3 c$ x二、硬件连接! S0 f! j2 o- ~& A' u9 |
1、把屏幕插到开发板上即可
9 \! N# u8 f$ S% Y" ^) K
# x; b. f0 Q" s+ I5 T三、相关知识点
! |( t8 E% ^2 G- b; F- B" [# C+ `! Y(一)、txt文件数据的读取
! D' ]8 l* i5 P5 F# X, z; ~( q; C
1、谈谈txt文件
- ?. d/ P' `6 G# P+ B! f! k5 j* ^* J! `; d
学过C语言的文件IO都知道,用open函数打开后,用read函数读取的第一个字节开始就是文本内容,txt文件是文档文件,对于我们程序员来说文档文件是最容易操作的文件类型之一,因为它不像图片那样还需要考虑头部的一大堆信息* S5 ~' c1 X3 C- J4 L# B

/ E9 O# k5 h0 j) {% T' f2、读取txt文件数据9 ~2 v  S2 H2 M5 w7 w% K& H5 l
( N8 b# H3 B# w1 _- a" v
利用FATFS文件系统提供的函数f_open 、f_read即可对数据进行读取出来,当然读取出来的都是文字的编码,可以先用串口函数打印出来看看数据对不对 printf("%s\r\n",buf);" W- [; U5 I3 S& V

  w6 k# c. o1 j: F, f$ k(二)汉字的显示(具体代码参考正点原子“汉字显示实验”)+ }  D9 e( D* u! d
+ Y; r. W& e8 N: n; U
1、汉字的显示原理, X% a0 M( q3 G  h' h# v

5 j6 d0 `$ e4 N# h; {$ _7 g1)学习过屏幕驱动的应该都知道,屏幕的显示无非就是在屏幕上打相应颜色的点,比如要显示一个字符 ‘A’ 那么我只需要知道 ‘A’ 相应的点阵数据就可以把它显示出来,汉字也一样。& g3 `" e! a, S2 w  z0 _
& H  Y. s0 r" Y) r9 N1 U. j
2、汉字库的存储% P& ]3 s1 |3 t) H; I% O

; d3 h/ E  Y4 g! t/ I2)但是汉字与字符不同的是,汉字有1万多个,字符却只有100多个,并且汉字的显示明显比字符的点阵复杂程度高,比如说字体是12的字符占用点阵是12x6,每个字符需要12x6/8=9个字节的存储空间。字体是12 的汉字占用12x12的点阵,每个汉字需要12x12/8=18个字节存储空间,这还是最小字体,大的字体所需要的存储空间只会成倍增加- Y$ f* T+ ?) z) y! x4 }% C
0 |* E/ P. x; V
3)一般12号字体的汉字库需要500K字节、16号字体700K、24号字体1.6M、32号字体3M,这对于单片机来说数据量太大了,内部FLASH512K~1M表示压力很大

$ z% |8 `1 d% ]* W, Q3 _" |
" n, t, _2 s2 j8 L3 o) W: c
% {: [" t- w3 c6 o9 u
20201217162029866.png 1 q6 K! o; E0 F3 ]3 T+ H8 {3 T! j

2 n7 Y6 {; I' N8 f+ v4)需要把汉字库通过SD卡再保存到外部FILASH才行,w25q128无疑是个好选择,它拥有16M的存储空间,SPI通信协议,读写速度也是相当快。5 @6 H4 c/ ~1 V$ K

' j0 g2 a  _5 B) {(三)txt文件数据显示到MCU屏( E4 p: M! Q# t# y, ]
* A0 f  l9 I# T3 t3 f" x: H* {2 H$ W
1、数据编码格式的问题9 M* y3 S- }5 c& P
6 l6 N# ~- y& Q& ?' }8 N( a! M
有关显示汉字就必然会涉及编码格式的问题,不同的编码格式对应的汉字编码是不同的,比如UTF-8编码的文件用GB2312编码打开就会乱码。
* k" e1 R" z, m5 H# u同理,比如文档的格式是UTF-8编码,但是我的字库是GBK编码,读出来的数据直接显示到屏幕就必然会乱码
2 C- J0 m) C# D3 ~1 m' ^
4 ~0 c) p2 M" h# d. ]( J/ d四、下载调试8 a0 f3 o; y0 {
* g: }; V5 u" X
1、SD卡根目录文件拷贝
9 j6 p* |7 X0 j5 a1 o7 R# G$ H
  Z8 h( E9 L3 a4 f+ x* O下载好本博客配套资料,把下面两个文件夹拷贝到SD卡根目录下
* M; t2 N8 H( S8 j

2 x' f6 i' x) e+ j' [' c9 Z

! k6 }% i0 d5 N, ]* i 2020120719291362.png
! x: e& X! I# L6 u! X  f5 V% o: B2 u; C
()一定要是根目录,不然不能正常运行

+ Y+ c" I: H+ f4 ~) s, C2 v5 K; I5 ~% _6 p( ~% s5 S3 R! L
2、初始化外部FLASH -W25Q1288 Y3 y6 {$ M; U+ _  z
用keil打开代码工程,编译通过后下载$ D, I' M+ Q+ ?3 k4 P
下载完成等待外部FLASH -W25Q128初始化完成,一开始会黑屏一段时间,是在擦除FLASH,然后会提示字库加载进度,直到LCD显示阅读界面为止
7 m7 m/ u# M. f5 i" o. P

- h" D) E0 L$ }

) D/ g( X2 Q) `3 M* T' Z 3}D6J3X%~W7WDI[ZHJ{D`XP.png
  r* C; J2 z3 U  c) U( @( k# U# i2 n% P* {) b2 |$ ]+ l
如果下载代码后运行不正常:
' S1 Y3 Z' ]& W6 U1)注释掉这些代码,编译下载

1 ~, Y" B2 Q; q+ l( z% h  u" V( g5 K
$ l; a0 M( t" k: m

: D* X. n" \: W  N- C* q' k 8BA9(4R~RG8}BJ`EIB%N@6K.png * ]0 i$ s# w6 m$ w

' n4 r7 d7 O; {+ d' o# G  o2)不要断电,取消注释这段代码,编译下载,下载完成后W25Q128初始化完成,应该就可以运行
/ M1 q& k# ^# f/ U
9 a5 |" q  @: f* W1 W- c; A
1 J% j) U- I4 _1 L/ e
20201217154828284.png - r8 \7 s1 ]  E! w
. ]( d7 F4 _- w5 {. S) t* [  l0 z
3、化作尘动态logo
4 e7 l2 d8 g$ Q
% C* n2 D5 f( v& `/ I
4、进入主界面7 U& Z  P' q/ v" ^
啥都没有,先导入图书
) x" f5 v+ q5 S7 T图书要从SD卡中导入,txt文件在资料里已经打包好了,直接导入
4 _: D0 f, H/ R. g
2 _. h6 h$ E/ I: x% w: ^. H5、导入图书
3 A" ]9 s4 K+ `1 z找到0:/TXT目录下的.txt文件,选择导入
. G6 U2 ~5 r3 {7 h8 V! ?, V; a" s/ K( I6 H! ?
导入“斗罗大陆.txt”,主界面开始显示
* k9 h) H$ A7 ?7 N, \$ f6 q图片是系统自动匹配,检测是否有与小说同名图片文件,比如“斗罗大陆.txt” 对应 “斗罗大陆.jpg”, }) G, d& t& \. F5 u

3 `. Y9 l  B" k$ k/ X如果没有匹配图片会显示默认图片5 a+ o3 a2 i' U/ o; l
7 o9 B/ @) x2 T3 }
6、删除图书
: ~) f* [8 k7 _! P' n; X点击左下角删除图书,再点击 X 即可移除图书操作,只是移除,并不是真正删除。
( _# N4 y0 F4 V! b) Y/ K, t! j) _7 W9 p3 X) h9 u+ S' D
0 ^  \- e" f* C
7、阅读界面! K1 ^- V7 M3 d/ D" ?) X
阅读界面都是根据页数匹配相应文字,因为读写速度问题加上需要算法识别加载,翻页加载过程都会有一段时间! H) O0 t5 S+ Y* b# ?: }# v2 K

  A, t; a1 ~; }( g) ?$ [: r, k& E' k  G" r& R  I# ]
8、目录功能
4 t# v( R0 M* K$ N) Y5 _1 c$ p. Q自动检测目录,通过检测“第” 与 “章”加上相应算法就可以检测显示目录,并记录偏移,可以跳转,上划可以显示下一页目录
8 d) E: T4 S. s- F2 f- n' `' c/ o5 k8 b/ \4 _$ C' W" Y
9、设置字体、背景
/ p0 T7 G! r# ]1 T  ?可以设置显示背景,字体颜色,字体大小来适应自己喜欢的阅读方式1 z3 A$ L8 u1 l; @8 T
1)24号字体 、白天! C# N0 c% L. `( `

2 v/ M. @0 K9 e2)24号字体、护眼4 d* C/ B) B; X; ?6 H! c( m+ E2 A% p

+ P5 f9 |  n# d) m3)12号字体、护眼2 K$ F% p) f9 h
; M. L: t0 \( ?, [3 P

8 W# f% `4 ?3 J( S1 u; `5 m3)24号字体、夜间
: U- l* C6 P. Z9 c) R( K% q7 f) t( ]( |

1 G. G9 u% [" ^; g0 I5 v: ^五、程序设计4 X0 p6 G1 W5 A; u& I- S" g" B% I3 g
代码过长,只展示部分代码:

  Z: B: h/ [8 E& W' X7 _/ d1 M, L8 D
% K4 @. M* |) }' i- Y& v' \% u( Y
  1. #include "sys.h"
    . V1 t' c7 k& N3 T- k: b/ Z% k3 G8 M
  2. #include "delay.h"
    / l8 r( o+ J. Z% D5 m6 H+ g. k
  3. #include "usart.h"# B# O0 h7 F# ^3 g4 J
  4. #include "led.h") z' w1 ?- |: x* S3 {' ?8 b( H
  5. #include "lcd.h"  P% T& O) {) l- u+ z
  6. #include "key.h"  6 I4 Y. a4 k: x, Y# T# N. ~: G$ u
  7. #include "sram.h"   
    $ h+ H+ i; |+ _# q0 r4 ?7 M. ^
  8. #include "malloc.h"
    9 v2 N# h( b6 ^9 {8 o, N8 X& z
  9. #include "usmart.h"  2 r' ~& i, ~4 k1 v! x
  10. #include "sdio_sdcard.h"   
    . \. R% p, ]: H! a! d1 q0 u
  11. #include "malloc.h"
    , Y5 ^6 }) K! ~- o, o1 N; H) I
  12. #include "w25qxx.h"    3 u& _" r7 @7 R, K
  13. #include "ff.h"  
    + S8 Y0 S& I% _) L" y
  14. #include "exfuns.h"      U" e4 J; B8 j* p8 d, K
  15. #include "fontupd.h". ], v5 t$ @: [: r) j: {
  16. #include "text.h"         
    , v% _. S  v) R) f
  17. #include "piclib.h"        
    4 ]" i& |* M: |% ^. C
  18. #include "string.h"          G8 B- \  w/ d# D3 I( S4 f
  19. #include "math.h"        
    8 P& N  f' G8 M! W4 N' p3 }
  20. #include "touch.h") y' m' v: r& X& z- R; e1 g- ?  k! z

  21. 4 b, C  w) K. r8 E
  22. u8 menu_num;//当前主菜单页数: ]2 k6 h, d  L% d
  23. u32 page;//当前页数* S3 H' g3 }8 \  [2 \2 j; x
  24. //char chapter_name[50];//当前章节名; W7 _# Q! q1 c9 L
  25. u32 page_offset[1000];//保存页数偏移! R3 Y3 T( E+ H7 w  u1 M" ~# J
  26. //u32 page_off_mult;//页数偏移倍数
    & X' h6 T" n2 b0 {
  27. u8 txt_num;//当前书架图书数量
    0 ^+ P3 b' A. W+ Z' S
  28. u8 txt_path_name[30][60];//导入图书路径1 c' c; o& C! Y" S/ K
  29. u32 bookmark[30];                                //保存对应书签 也就是页数 下次进入直接偏移页数& ?$ S; Q. ~6 K6 \8 i
  30. char txt_name[4][30]={"","","",""};//显示4本图书名字% k+ \/ t5 `0 P. E# N1 @
  31. u8 pname[60];                        //正在打开的文件名路径
    . q) c4 g  e* e
  32. int SIZE=24;                        //初始化字体' i) X/ V% s( T8 o1 Z
  33. char buff[2500];//一页数据 缓冲文档
    2 H* v1 O# C+ U* t# x$ W( H- j
  34. int page_mul_cnt=0;//存取次数 一次1000页2 e5 f- S8 p1 O8 R+ R2 C% q
  35. int now_page_mul;//当前1000页的倍数9 s; |: e4 @+ g" \2 N/ F7 {
  36. u32 data_offset;//读取偏移  读写flash用6 Q% f9 R) J) x! [
  37. / t0 T/ ~- ?" S) q, J* ]
  38. ; a1 N& ]. ]" S1 L3 U
  39. //显示主界面
    4 ~' J% ?9 a& Y) H& e, C3 b
  40. void menu(void);! _- F( E0 t5 d  m- ]
  41. //获取触摸键值
    ! z4 H& A: u. @
  42. u16 get_ts_val(int key);( \( V5 O* K# n: I- [) a/ f" v( w
  43. //读取文件数据到LCD4 l7 f( k9 @( Q) S- I' [0 y6 y% m, W
  44. int read_to_lcd(void);0 i0 B. k4 ]  f% p3 _
  45. //更新小说名# ], L) Y" W& w8 t; X6 n% \9 L3 Y
  46. u8 lcd_dis_files(u8 * path);
    . Z2 Q; m- L& Y& }( I
  47. //阅读模式1 Y) j. [0 u% X6 r9 q2 r
  48. void read_mode(void);
      T: _; ?+ C4 p- \7 |: D0 e3 z% u
  49. //设置字体格式& e4 W6 [* V" T* |4 f% l  N
  50. int setting(void);
    7 I- c7 g- h/ }1 A( k
  51. //设置界面% a7 u& d4 c: n4 q
  52. void show_setting(void);* K0 n4 k( f5 \. h; ~% Q& C  M. l
  53. //目录功能3 D& N9 c9 q8 @. |+ j
  54. u32 txt_dir_scan(void);% V9 w* I( u1 {4 ~. P3 W/ h
  55. //文件系统功能 导入小说
    6 _4 C. l5 q3 _7 j  z4 Z; l
  56. void fatfs_choose(void);
    9 n0 A3 [: e5 Z
  57. //读取数据到flash
    # \8 C2 X) i6 `6 z& O4 ]8 g! Q# C
  58. void file_data_to_w25q(void);
    3 S, p' u& k- Z& b) r' ~( J
  59. //根据页码得到页数4 }$ F4 H+ \$ o/ V  F( A3 T
  60. u32 ident_get_page(u32 page_offset);
    8 y; ^) \3 D! L8 e% u
  61. //遍历文件 显示到屏幕$ W( q% P( Y9 b
  62. u8 mf_scan_file(u8 * path);
    ( S1 j) i8 I  Y$ q4 q& \
  63. //刷新显示书架名字
    : Z! y9 t) {. r" h
  64. void re_dis_txtname(int i);
    ! r; N- r5 Q; b% ~" Q
  65. //带路径的文件名 转 不带路径文件名
    ( u  ]0 a& f: \6 e
  66. char* path_change(char *oldpath);/ t. v  {- j5 ]( q/ W- @
  67. //根据页数得到页码
    6 N/ g2 X$ |. E. [/ i" U
  68. u32 ident_get_offset(u32 page);: z( f3 X' q* Y3 t+ C
  69. //更新内存1000页页码0 j7 z) t# |* i: u( f: C) @+ h
  70. void update_page_offset(void);
    ! d- E) H8 K) \# K) p
  71. //读出书签数据
    # F9 X$ D. G& q1 h. ], _
  72. void read_bookmark(void);' A' @; m9 p' z5 x- [( ?
  73. //保存书签数据到flash
    . x6 L9 f& f, R
  74. void save_bookmark(void);
    " R/ N# R. e6 q) ]& R* M8 {# ~9 n
  75. //保存书名数据到flash4 s) ~* h' l6 S, }
  76. void save_bookinfo(void);- ]5 c2 b4 Z9 e3 Q  F6 |6 P2 u
  77. //删除小说3 l# J0 s0 s& ~+ y- O
  78. void del_txt(u8 *path);
    9 d  i" C/ u! ^" D
  79. //删除小说控制界面
    9 D; Q- x- y8 W! K& i+ v
  80. void del_txt_ctrl(void);
    2 J/ \2 i) j( Z& v$ R
  81.         
    1 d- }/ C0 p" s: ^3 g0 F( S
  82. % V* Q) Z+ b7 P$ [+ L8 s) |' B
  83. , D7 P. C6 j+ f

  84. ( d( v0 I  }+ G7 o
  85. int main(void)
    2 ^# C; I' r" w% N" T2 k9 u5 m8 o
  86. {          w- O$ X9 G4 u* b) E8 l' W% C  Z
  87.          DIR picdir;                         //图片目录' a0 s+ u/ R6 U( _/ [8 C
  88.          
    4 e9 c5 {4 x" k" |2 k6 c; H5 \
  89.         u8 key;  n. e% L' g4 ]
  90.         NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置系统中断优先级分组2
    4 J! Q+ k! M- ~3 f" J2 C  \
  91.         delay_init(168);  //初始化延时函数, k9 N' ^) k6 e5 g- _
  92.         uart_init(115200);                //初始化串口波特率为115200
    , Q$ x! y# N& x  ^% ^6 w- P4 U( \
  93.         LED_Init();                                        //初始化LED  ) V# P" |2 {' d, \
  94.          LCD_Init();                                        //LCD初始化  
    8 X2 y- r' ~( u0 Z0 t4 B2 h
  95.          KEY_Init();                                        //按键初始化
    * e: F  b7 G1 n  F' K1 C  o
  96.         tp_dev.init();                        //触摸初始化        0 `0 f% r  p/ U+ {, _
  97.         W25QXX_Init();                                //初始化W25Q128" y8 h. g3 m1 I: A0 e2 {* J6 A
  98.         usmart_dev.init(168);                //初始化USMART
    ) e8 E' ?) j) Z- x
  99.         my_mem_init(SRAMIN);                //初始化内部内存池 5 `, W( {" L8 ~$ k1 G, P
  100.         my_mem_init(SRAMCCM);                //初始化CCM内存池 7 C% ]: G2 B4 h4 Z
  101.         exfuns_init();                                //为fatfs相关变量申请内存  
    ' H) h6 t, h( C: \/ Z" |/ l
  102.          f_mount(fs[0],"0:",1);                 //挂载SD卡
    4 {) J  L) }( y, L
  103.          f_mount(fs[1],"1:",1);                 //挂载FLASH.) A( h; F! Z: ~- W" G0 Q
  104. % C& X7 J5 W- C4 Q. O' ^! B1 e
  105.         while(font_init());                        //检查字库; _. c" y2 d/ A) Y4 X: }4 B0 ?
  106.         
    " `$ Q4 h9 X1 O% H4 U  |. ]
  107.         delay_ms(150);
    $ t1 L4 F1 R$ X3 l1 H7 m% l& N
  108.         piclib_init();                                                                                //初始化画图         
    ( u- l8 C. `9 M0 Z4 H9 P$ q6 V# s4 ~
  109.         delay_ms(150);
    ; }8 {. C1 f4 L$ j# P9 }/ P; R
  110.         LCD_Clear(GBLUE);//清屏5 b" n3 H' w; n4 _
  111.         ai_load_picfile("0:/SYSTEM/PICTURE/logo.gif",0,0,lcddev.width,lcddev.height,1);//显示图- Z, ]) w3 y$ a  F+ a8 O
  112.         read_bookmark();//读出图书 书签数据
    6 W" D5 [/ O3 c
  113.         memset(page_offset,0,1000*4);//清空页码数组
    ' x$ L2 `  V4 P' Q0 m
  114.         menu_num=1;//显示第一页" ~( ]; X2 Y8 v' j$ S9 f( t
  115.         //lcd_dis_files("0:/TXT");//更新系统书名& u) a7 h" k" R! X3 M: {5 U
  116.         menu();//显示主界面
    + B: W& m; c7 J" L2 K$ c+ V% _( Q6 ]# y
  117.         while(1)
    3 b3 A' }% B, y2 E1 k9 r
  118.         {
    * f* O8 o& `# z8 J
  119.                 key = get_ts_val(1);7 o0 n+ t) c" g0 Z8 k
  120.                 if(key!=0)6 c+ w& y9 R+ \
  121.                 {
    * W/ V% x' F5 F& _0 T
  122.                         printf("key=%d\n",key);4 U" ^, R! u/ P
  123.                         switch(key)//选择要打开的图书! i" @; p8 w0 l6 [2 K( g) b
  124.                         {
    # O) G7 [' Y+ C- I6 Y; ?- f+ l
  125.                                 case 1: if(txt_num-4*(menu_num-1)>=1){4 @9 Y* S1 e: z  R- V0 D
  126.                                                                         strcpy((char *)pname,(char *)txt_path_name[0+(menu_num-1)*4]);//把要打开的书籍名称赋值
      N0 u( u$ y4 @6 E: Y
  127.                                        
    4 ^! s" ]! i6 Y; M" L
  128.                                                                         page = bookmark[0+(menu_num-1)*4];//根据flash保存的书签初始化进入的页数  d, |; l; z; t/ l! F. N
  129.                                                                         if(page >= 0xffff)page=0;
    # l' P, j) w& f0 s
  130.                                                                                 read_mode();//进入阅读模式* l0 \7 Y" w, ]
  131.                                                                         bookmark[0+(menu_num-1)*4] = page;//退出保存书签: [, Q' Z6 W+ ]" U. J: [
  132.                                                                         save_bookmark();
    1 D" Y) F8 c: A$ n3 i% T1 J
  133.                                                                         }break;- p, n4 Q* f3 v5 }; B6 F
  134.                                 * z7 A+ L$ i+ n' b; v% s1 ]
  135.                                 case 2:        if(txt_num-4*(menu_num-1)>=2){& e$ t" I% o* ?
  136.                                                                         strcpy((char *)pname,(char *)txt_path_name[1+(menu_num-1)*4]);* @2 N6 K8 X; l2 V5 c; \
  137.                                         " E0 r* b4 T3 x8 h
  138.                                                                         page = bookmark[1+(menu_num-1)*4];
    + k9 G, Q/ w* k
  139.                                                                         if(page >= 0xffff)page=0;1 R' I" v6 m( v5 l2 O
  140.                                                                         read_mode();//进入阅读模式
    1 O1 j% B9 p5 ~+ F* \
  141.                                                                         bookmark[1+(menu_num-1)*4] = page;
    2 z2 M- f/ A7 b! n: |" z/ u
  142.                                                                         save_bookmark();
    , ^) {  N6 k3 N( h, _* \
  143.                                                                         }break;
    1 J  t+ k' @$ n9 {7 |
  144.                                                                         
    * F" }0 S8 m( J
  145.                                                                         
    2 V6 z* `0 }& v$ S7 Q! F
  146.                                 case 3: if(txt_num-4*(menu_num-1)>=3){
    8 {$ k! P# u1 _  _2 M' Z9 B
  147.                                                                         strcpy((char *)pname,(char *)txt_path_name[2+(menu_num-1)*4]);
    ! o! w2 U) n+ E1 _% g
  148.                                         % w8 D( E1 g+ t  _9 ?, H/ N! x; ~9 v2 D
  149.                                                                         page = bookmark[2+(menu_num-1)*4];( w' f' }: C. s1 y
  150.                                                                         if(page >= 0xffff)page=0;
    ; J. G2 ?$ [9 [  h% p" p+ e' A
  151.                                                                         read_mode();//进入阅读模式
    ' n% |# G! t+ H# s7 @( V: C
  152.                                                                         bookmark[2+(menu_num-1)*4] = page;) |) c  e1 f  ^- ]2 k, l. m
  153.                                                                         save_bookmark();  F. V4 p; A, M& R% E
  154.                                                                         }break;7 {8 z' E- t" Q1 C1 b% S* ^
  155.                                                                         
    5 z8 Z5 |0 a( y9 Y1 q; J8 i$ c
  156.                                 case 4: if(txt_num-4*(menu_num-1)>=4){
    + o% ?* g5 T9 m
  157.                                                                         strcpy((char *)pname,(char *)txt_path_name[3+(menu_num-1)*4]);
    ! p6 W9 y8 f6 {) W1 j
  158.                                         , Y( l' L+ T3 N& i
  159.                                                                         page = bookmark[3+(menu_num-1)*4];
    ) c3 ^2 `; ^+ o8 ]5 k' v
  160.                                                                         if(page >= 0xffff)page=0;
    6 O1 k$ g) ^) M5 f! T- i' q
  161.                                                                         read_mode();//进入阅读模式  p& N! h+ Y3 @' e) v
  162.                                                                         bookmark[3+(menu_num-1)*4] = page;2 x) c' V+ ^6 y# {, _) r* n% l: ]1 f
  163.                                                                         save_bookmark();; y% K8 H: T& y. J' F! k" b" r0 f
  164.                                                                         }break;  o/ I/ t3 l3 B6 J$ q) v

  165. ! n5 g5 ^+ ?3 t
  166.                                 case 5:                //导入图书/ x; ?8 R: g% c
  167.                                                                         fatfs_choose();//文件系统选择文件导入
    3 ?1 V; C7 @/ Q
  168.                                                                         save_bookinfo();//保存书籍数据到flash7 U( Z) s8 ]. |( z  I
  169.                                                                         printf("当前图书数量:%d\r",txt_num);0 f9 Y6 j+ k$ q
  170.                                                                         break;9 z# P/ Q  f" h! Y' H
  171.                                 
    & x. B- Z1 g5 |4 H: T
  172.                                 case 6:                del_txt_ctrl();//删除图书
    , Z  Y2 q) h  Z
  173.                                                                         break;! j8 @5 I& g* p/ {. z0 u7 z; ?
  174.                                 
    0 }. r/ c- x% N  B- R' w
  175.                                 case 111: if((txt_num-1)/4+1>menu_num)menu_num++;& a2 ~; I( }# V& y7 }9 J7 h
  176.                                                                                 printf("menu_num = %d\n",menu_num);//上一页! C! |$ J$ [" y% V/ G  ]4 Q
  177.                                                                         break;
    . P+ q) ]( w1 z! Q5 ]
  178.                                 
    / f; e7 x2 k9 u
  179.                                 case 222: if(1<menu_num)menu_num--;. s7 B1 V% R! }' _
  180.                                                                                 printf("menu_num = %d\n",menu_num);//下一页
    ' u3 G- Y$ P( S9 v
  181.                                                                         break;        7 r3 k" \' C1 j
  182.                         }
    8 d" }5 {0 w, E/ T) V6 Z
  183.                         
    ( z- A; Y5 U: `
  184.                         menu();//显示主界面
    ) H% H- u! Y. W* I% T- j  I
  185.                         data_offset=0;//偏移清零" k9 B+ h0 m5 E) k; U8 L7 ?5 l9 _
  186.                         page_mul_cnt=0;//1000页倍数清零( t) Q2 U* ]! e. E
  187.                 }! O3 |: t% u5 p& |6 I; B5 r  t
  188.                 delay_ms(10);# P. w9 ^, U1 |0 {/ W
  189.         }
    1 R0 [2 \7 D9 o  ]# V  ]5 x+ R
  190. }
    ) h0 A1 D/ b$ q  }$ x4 W
复制代码
- ^$ U3 i  A; r2 s; K0 T$ v
六、硬件框图; {/ W2 I4 w8 s* V1 @
$ @2 ^$ {. y0 J
f4eb57ecfb5a4b5283e54dddf8c1c3be.png $ P. j8 ?( P8 J" ^$ n& _
单片机通过SPI与外部FLASH进行连接通信,使用SDIO与SD卡连接,第一次上电的时候,程序会把SD卡中的字库文件数据读取并写入到外部FLASH中,使液晶屏可以用函数显示32、24、16、12号字体的汉字
3 ~$ r6 H) A6 \触摸屏作为人机交互输入,程序通过识别用户点击的屏幕坐标,控制液晶屏的各种显示
" y  p/ Q% C" Y6 D3 h& c( v8 K( c& z+ i- {6 {
七、程序框图
5 }7 J+ A" P& s1 B: m5 p
, |% J( Q# Y5 }; `( U9 J
ce916629c9dc436fbf5cec5c7c084e3d.png
# R! o6 o1 Q" H+ o$ J# v5 Y) y  Q
: r: B4 ~/ C& x! B开机单片机会初始化各种接口,SDIO、SPI等,用于控制SD卡、FLASH,显示屏,第一次上电会识别外部FLASH中的字库是否完整,不完整会进行更新字库的操作,然后初始化图片库,配合SD卡驱动、显示SD卡中的图片,开机显示SD卡中的一张GIF格式的图片作为LOGO,然后进入主循环显示主界面,书架界面会显示4本书的位置,还有删除图书、导入图书等操作,系统会识别用户按下触摸屏的坐标进入相对应的函数,例如点击导入图书,会进入导入图书的函数,会调用程序的文件系统,读取SD卡中的文件,导入TXT文件就可以显示图片与书名到书架,删除图书会显示一个X的图片到已添加到书架的书籍上,点
击即可删除内存中保存的书籍信息,从而在书架删除图书,然后点击书籍会进入读取书籍信息的函数中,程序根据书籍在SD卡中的文件路径,通过文件系统读取这个TXT文档的数据,并显示到屏幕。进入阅读模式后可以设置字体、背景颜色等,目录功能。- R) L" U- y8 K! ^7 j2 I, c
, d) X8 t% |: J" a7 k  C
# b! d. E( S  Y/ d4 i, P

) S! z8 v4 w+ @9 o# v. f8 X
赞 收藏 评论0 发布时间:2022-8-15 19:42

举报

0个回答

所属标签

相似技术帖

官网相关资源

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