文章目录

  • 基于STM32F4的电子阅读器
    • 一、项目功能要求
    • 二、材料准备
    • 二、硬件连接
    • 三、相关知识点
    • 四、下载调试
    • 五、程序设计
  • 六、硬件框图
  • 七、程序框图
    • 化作尘其它开源项目:
    • 单片机项目:
    • Linux项目:

基于STM32F4的电子阅读器


哔哩哔哩视频链接:https://www.bilibili.com/video/BV1Y64y1f7Ji/代码资料链接:https://download.csdn.net/download/mbs520/13510169
百度网盘资料链接:https://pan.baidu.com/s/1NHRFNa8Qn7M286kv4WnHKA
提取码:abcd
电子小说阅读器v1.2版本:修复闪屏,导入图书失败等BUG
https://download.csdn.net/download/mbs520/85055345
取走记得点赞

一、项目功能要求

项目说明:

  • 项目偏软件,但是要依赖于自己对硬件的熟悉和驱动才能完成

用到的主要技术:

  • SD卡驱动(难–不过可移植 SD卡驱动细节可在用完再了解其驱动协议)
  • FatFs文件系统移植使用
  • LCD屏驱动(加载字库文件 做字库在LCD上的显示)

功能要求:

  • 开机Logo

  • 电子书列表扫描

  • 电子书列表显示及小说选择菜单

  • 阅读功能:

    • 字体选择
    • 字体大小选择
    • 字体颜色设置
    • 阅读背景设置
    • 书签设置
      • 能够记录每本电子书的退出时处于什么阅读位置 下次进入从该位置继续阅读
    • 目录生成功能(字符匹配)
    • 章节跳转功能(基于目录生成功能)
    • 阅读翻页设置(滚动/切换)

二、材料准备

1、普中STM32F4ZGT6最小系统板一块(或者其他STM32F4板子)
(注意要买能插LCD屏的)
作用:主控芯片、处理各种数据

2、800*480 4.3寸电容触摸LCD屏(我用的正点原子的屏)
作用:显示与触摸控制

3、一张32G以下的SD卡和一个读卡器

作用:存储小说文件与图片文件

二、硬件连接

1、把屏幕插到开发板上即可

三、相关知识点

(一)、txt文件数据的读取

1、谈谈txt文件

学过C语言的文件IO都知道,用open函数打开后,用read函数读取的第一个字节开始就是文本内容,txt文件是文档文件,对于我们程序员来说文档文件是最容易操作的文件类型之一,因为它不像图片那样还需要考虑头部的一大堆信息

2、读取txt文件数据

利用FATFS文件系统提供的函数f_open 、f_read即可对数据进行读取出来,当然读取出来的都是文字的编码,可以先用串口函数打印出来看看数据对不对 printf("%s\r\n",buf);

(二)汉字的显示(具体代码参考正点原子“汉字显示实验”)

1、汉字的显示原理

1)学习过屏幕驱动的应该都知道,屏幕的显示无非就是在屏幕上打相应颜色的点,比如要显示一个字符 ‘A’ 那么我只需要知道 ‘A’ 相应的点阵数据就可以把它显示出来,汉字也一样。

2、汉字库的存储

2)但是汉字与字符不同的是,汉字有1万多个,字符却只有100多个,并且汉字的显示明显比字符的点阵复杂程度高,比如说字体是12的字符占用点阵是12x6,每个字符需要12x6/8=9个字节的存储空间。字体是12 的汉字占用12x12的点阵,每个汉字需要12x12/8=18个字节存储空间,这还是最小字体,大的字体所需要的存储空间只会成倍增加

3)一般12号字体的汉字库需要500K字节、16号字体700K、24号字体1.6M、32号字体3M,这对于单片机来说数据量太大了,内部FLASH512K~1M表示压力很大

4)需要把汉字库通过SD卡再保存到外部FILASH才行,w25q128无疑是个好选择,它拥有16M的存储空间,SPI通信协议,读写速度也是相当快。

(三)txt文件数据显示到MCU屏

1、数据编码格式的问题

有关显示汉字就必然会涉及编码格式的问题,不同的编码格式对应的汉字编码是不同的,比如UTF-8编码的文件用GB2312编码打开就会乱码。
同理,比如文档的格式是UTF-8编码,但是我的字库是GBK编码,读出来的数据直接显示到屏幕就必然会乱码

四、下载调试

1、SD卡根目录文件拷贝

  • 下载好本博客配套资料,把下面两个文件夹拷贝到SD卡根目录下
    ()一定要是根目录,不然不能正常运行
    2、初始化外部FLASH -W25Q128
  • 用keil打开代码工程,编译通过后下载
  • 下载完成等待外部FLASH -W25Q128初始化完成,一开始会黑屏一段时间,是在擦除FLASH,然后会提示字库加载进度,直到LCD显示阅读界面为止

  • 如果下载代码后运行不正常:
    1)注释掉这些代码,编译下载
    2)不要断电,取消注释这段代码,编译下载,下载完成后W25Q128初始化完成,应该就可以运行

3、化作尘动态logo

4、进入主界面
啥都没有,先导入图书
图书要从SD卡中导入,txt文件在资料里已经打包好了,直接导入

5、导入图书
找到0:/TXT目录下的.txt文件,选择导入

导入“斗罗大陆.txt”,主界面开始显示
图片是系统自动匹配,检测是否有与小说同名图片文件,比如“斗罗大陆.txt” 对应 “斗罗大陆.jpg”

如果没有匹配图片会显示默认图片

6、删除图书
点击左下角删除图书,再点击 X 即可移除图书操作,只是移除,并不是真正删除。

7、阅读界面
阅读界面都是根据页数匹配相应文字,因为读写速度问题加上需要算法识别加载,翻页加载过程都会有一段时间

8、目录功能
自动检测目录,通过检测“第” 与 “章”加上相应算法就可以检测显示目录,并记录偏移,可以跳转,上划可以显示下一页目录

9、设置字体、背景
可以设置显示背景,字体颜色,字体大小来适应自己喜欢的阅读方式
1)24号字体 、白天

2)24号字体、护眼

3)12号字体、护眼

3)24号字体、夜间

五、程序设计

代码过长,只展示部分代码:

#include "sys.h"
#include "delay.h"
#include "usart.h"
#include "led.h"
#include "lcd.h"
#include "key.h"
#include "sram.h"
#include "malloc.h"
#include "usmart.h"
#include "sdio_sdcard.h"
#include "malloc.h"
#include "w25qxx.h"
#include "ff.h"
#include "exfuns.h"
#include "fontupd.h"
#include "text.h"
#include "piclib.h"
#include "string.h"
#include "math.h"
#include "touch.h"u8 menu_num;//当前主菜单页数
u32 page;//当前页数
//char chapter_name[50];//当前章节名
u32 page_offset[1000];//保存页数偏移
//u32 page_off_mult;//页数偏移倍数
u8 txt_num;//当前书架图书数量
u8 txt_path_name[30][60];//导入图书路径
u32 bookmark[30];               //保存对应书签 也就是页数 下次进入直接偏移页数
char txt_name[4][30]={"","","",""};//显示4本图书名字
u8 pname[60];           //正在打开的文件名路径
int SIZE=24;           //初始化字体
char buff[2500];//一页数据 缓冲文档
int page_mul_cnt=0;//存取次数 一次1000页
int now_page_mul;//当前1000页的倍数
u32 data_offset;//读取偏移  读写flash用//显示主界面
void menu(void);
//获取触摸键值
u16 get_ts_val(int key);
//读取文件数据到LCD
int read_to_lcd(void);
//更新小说名
u8 lcd_dis_files(u8 * path);
//阅读模式
void read_mode(void);
//设置字体格式
int setting(void);
//设置界面
void show_setting(void);
//目录功能
u32 txt_dir_scan(void);
//文件系统功能 导入小说
void fatfs_choose(void);
//读取数据到flash
void file_data_to_w25q(void);
//根据页码得到页数
u32 ident_get_page(u32 page_offset);
//遍历文件 显示到屏幕
u8 mf_scan_file(u8 * path);
//刷新显示书架名字
void re_dis_txtname(int i);
//带路径的文件名 转 不带路径文件名
char* path_change(char *oldpath);
//根据页数得到页码
u32 ident_get_offset(u32 page);
//更新内存1000页页码
void update_page_offset(void);
//读出书签数据
void read_bookmark(void);
//保存书签数据到flash
void save_bookmark(void);
//保存书名数据到flash
void save_bookinfo(void);
//删除小说
void del_txt(u8 *path);
//删除小说控制界面
void del_txt_ctrl(void);int main(void)
{        DIR picdir;            //图片目录u8 key;NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置系统中断优先级分组2delay_init(168);  //初始化延时函数uart_init(115200);     //初始化串口波特率为115200LED_Init();                    //初始化LED  LCD_Init();                   //LCD初始化  KEY_Init();                   //按键初始化 tp_dev.init();          //触摸初始化 W25QXX_Init();              //初始化W25Q128usmart_dev.init(168);       //初始化USMARTmy_mem_init(SRAMIN);     //初始化内部内存池 my_mem_init(SRAMCCM);        //初始化CCM内存池 exfuns_init();              //为fatfs相关变量申请内存  f_mount(fs[0],"0:",1);      //挂载SD卡 f_mount(fs[1],"1:",1);        //挂载FLASH.while(font_init());           //检查字库delay_ms(150);piclib_init();                                      //初始化画图   delay_ms(150);LCD_Clear(GBLUE);//清屏ai_load_picfile("0:/SYSTEM/PICTURE/logo.gif",0,0,lcddev.width,lcddev.height,1);//显示图read_bookmark();//读出图书 书签数据memset(page_offset,0,1000*4);//清空页码数组menu_num=1;//显示第一页//lcd_dis_files("0:/TXT");//更新系统书名menu();//显示主界面while(1){key = get_ts_val(1);if(key!=0){printf("key=%d\n",key);switch(key)//选择要打开的图书{case 1: if(txt_num-4*(menu_num-1)>=1){strcpy((char *)pname,(char *)txt_path_name[0+(menu_num-1)*4]);//把要打开的书籍名称赋值page = bookmark[0+(menu_num-1)*4];//根据flash保存的书签初始化进入的页数if(page >= 0xffff)page=0;read_mode();//进入阅读模式bookmark[0+(menu_num-1)*4] = page;//退出保存书签save_bookmark();}break;case 2:  if(txt_num-4*(menu_num-1)>=2){strcpy((char *)pname,(char *)txt_path_name[1+(menu_num-1)*4]);page = bookmark[1+(menu_num-1)*4];if(page >= 0xffff)page=0;read_mode();//进入阅读模式bookmark[1+(menu_num-1)*4] = page;save_bookmark();}break;case 3: if(txt_num-4*(menu_num-1)>=3){strcpy((char *)pname,(char *)txt_path_name[2+(menu_num-1)*4]);page = bookmark[2+(menu_num-1)*4];if(page >= 0xffff)page=0;read_mode();//进入阅读模式bookmark[2+(menu_num-1)*4] = page;save_bookmark();}break;case 4: if(txt_num-4*(menu_num-1)>=4){strcpy((char *)pname,(char *)txt_path_name[3+(menu_num-1)*4]);page = bookmark[3+(menu_num-1)*4];if(page >= 0xffff)page=0;read_mode();//进入阅读模式bookmark[3+(menu_num-1)*4] = page;save_bookmark();}break;case 5:       //导入图书fatfs_choose();//文件系统选择文件导入save_bookinfo();//保存书籍数据到flashprintf("当前图书数量:%d\r",txt_num);break;case 6:     del_txt_ctrl();//删除图书break;case 111: if((txt_num-1)/4+1>menu_num)menu_num++;printf("menu_num = %d\n",menu_num);//上一页break;case 222: if(1<menu_num)menu_num--;printf("menu_num = %d\n",menu_num);//下一页break;  }menu();//显示主界面data_offset=0;//偏移清零page_mul_cnt=0;//1000页倍数清零}delay_ms(10);}
}

六、硬件框图


单片机通过SPI与外部FLASH进行连接通信,使用SDIO与SD卡连接,第一次上电的时候,程序会把SD卡中的字库文件数据读取并写入到外部FLASH中,使液晶屏可以用函数显示32、24、16、12号字体的汉字
触摸屏作为人机交互输入,程序通过识别用户点击的屏幕坐标,控制液晶屏的各种显示

七、程序框图


开机单片机会初始化各种接口,SDIO、SPI等,用于控制SD卡、FLASH,显示屏,第一次上电会识别外部FLASH中的字库是否完整,不完整会进行更新字库的操作,然后初始化图片库,配合SD卡驱动、显示SD卡中的图片,开机显示SD卡中的一张GIF格式的图片作为LOGO,然后进入主循环显示主界面,书架界面会显示4本书的位置,还有删除图书、导入图书等操作,系统会识别用户按下触摸屏的坐标进入相对应的函数,例如点击导入图书,会进入导入图书的函数,会调用程序的文件系统,读取SD卡中的文件,导入TXT文件就可以显示图片与书名到书架,删除图书会显示一个X的图片到已添加到书架的书籍上,点击即可删除内存中保存的书籍信息,从而在书架删除图书,然后点击书籍会进入读取书籍信息的函数中,程序根据书籍在SD卡中的文件路径,通过文件系统读取这个TXT文档的数据,并显示到屏幕。进入阅读模式后可以设置字体、背景颜色等,目录功能。

化作尘其它开源项目:

单片机项目:

基于stm32c8t6的坡道行驶巡线小车(2020年TI杯大学生电子设计竞赛 C题)https://blog.csdn.net/mbs520/article/details/115438122

基于STM32F4的音乐播放器
https://blog.csdn.net/mbs520/article/details/111313042

基于STM32F4的电子阅读器(首创)
https://blog.csdn.net/mbs520/article/details/110817173

基于51单片机WiFi视频小车(首创)
https://blog.csdn.net/mbs520/article/details/109843972

基于51单片机蓝牙小车
https://blog.csdn.net/mbs520/article/details/109775964
基于MSP430 坡道行驶电动小车(2020年TI杯大学生电子设计竞赛 C题)
https://blog.csdn.net/mbs520/article/details/109090072

基于stm32f4的智能门锁系统
https://blog.csdn.net/mbs520/article/details/106987758

基于51单片机超声波测距小车
https://blog.csdn.net/mbs520/article/details/106599219

基于51单片机定时宠物喂食系统
https://blog.csdn.net/mbs520/article/details/108292187

Linux项目:

基于QT5 Linux平台 停车场管理系统
https://blog.csdn.net/mbs520/article/details/113481824

基于QT5 Linux平台 车载系统
https://blog.csdn.net/mbs520/article/details/112873809

基于Linux系统 媒体播放器
https://blog.csdn.net/mbs520/article/details/107880118

基于Linux系统 语音识别、人机对话
https://blog.csdn.net/mbs520/article/details/113179224

基于Linux系统小钢琴程序(暂无博客)
https://download.csdn.net/download/mbs520/12798287

基于Linux系统 QQ通讯录管理系统(暂无博客)

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

  1. Linux项目设计:基于ARM平台的停车场管理系统制作教程

    文章目录 一.功能要求 二.项目笔记 (一)网络问题:Ubuntu同时与开发板.WiFi连接 (二)图片文字识别 (三)文字转语音 (四)摄像头拍摄 化作尘其它开源项目: 单片机项目: Linux项目 ...

  2. 基于飞桨的“小书虫”儿童电子阅读器

    项目背景 教育学和心理学的研究表明,幼儿的阅读能力对认知能力的发展影响最大,尤其是0-6岁阶段的早期阅读能力,是影响幼儿未来学习能力和水平的关键. 可是如今,快餐式媒体信息的爆发,导致儿童的精神世界日 ...

  3. 基于智能手机的报纸阅读器-论文

    源码下载 http://www.byamd.xyz/hui-zong-1/ 摘要 近几年来,智能手机的迅猛发展给人们的生活带来了极大的改变,移动互联网时代的来临使得人手拥有一台配置强悍的智能手机已不再 ...

  4. 基于android的电子书阅读器app

    基于android的电子书阅读器app 基于Android平台的电子书阅读器的设计与实现主要通过Eclipse开发工具, Java语言与Sqlite数据库来完成的.本阅读器实现了本地阅读,手动翻页,书 ...

  5. 基于sopc的计算机系统的设计与实现,基于SOPC的RFID阅读器设计与实现-计算机系统结构专业论文.docx...

    基于SOPC的RFID阅读器设计与实现-计算机系统结构专业论文 摘要 电子标识系统作为一种快速发展的定位技术,在地下管线定位技术领域占有 重要的地位.基于射频识别技术的电子标识系统代替传统的地下管线探 ...

  6. 产品分享:Qt鸿途电子智慧白板(适合会议机、电子黑板、电子笔记、电子阅读器等场景),当前版本v1.0.0

    ​若该文为原创文章,转载请注明原文出处 本文章博客地址:https://hpzwl.blog.csdn.net/article/details/128313385 红胖子(红模仿)的博文大全:开发技术 ...

  7. 用JSP实现基于Web的RSS阅读器

    2019独角兽企业重金招聘Python工程师标准>>> 一 RSS介绍 根据维基百科(http://zh.wikipedia.org/wiki/RSS)的定义,"RSS是一 ...

  8. 开发的一款IDEA电子阅读器功能介绍

    开发的一款IDEA电子阅读器功能介绍 一.背景介绍 心血来潮想开发一款idea看电子书的插件,能够支持收藏当前阅读位置,根据目录查看,能够按关键字搜索.将电子书阅读器隐藏在idea插件里如下图所示 同 ...

  9. 清茶一杯-手机、电子阅读器和生活

    和很多人一样,手机阅读早已融入了我的日常生活,等车ing.坐车ing.睡觉前和无聊的报告的时候,真感觉手机拯救了我的时间.记的我第一本手机电子书是<新概念英语>,Java的电子书,那时候我 ...

  10. node.js毕业设计安卓电子阅读器APP(程序+APP+LW)

    该项目含有源码.文档.程序.数据库.配套开发软件.软件安装教程.欢迎交流 项目运行 环境配置: Node.js+ Vscode + Mysql5.7 + HBuilderX+Navicat11+Vue ...

最新文章

  1. java遍历给定目录,树形结构输出所有文件,包括子目录中的文件
  2. 关于Silverlight_Tools.exe安装不上的问题
  3. 策略模式(封装一系列的功能,使之可以相互替换)
  4. 机器学习(MACHINE LEARNING) 【周志华版-”西瓜书“-笔记】 DAY3-线性模型
  5. day1-Python擅长的领域+学习内容
  6. 完整的Ubuntu18.04深度学习GPU环境配置,英伟达显卡驱动安装、cuda9.0安装、cudnn的安装、anaconda安装
  7. routing zuul_尚学堂0131之zuul的相关概念及如何性能调优
  8. dom技术解析xml下jaxp解析器详细代码
  9. squid 的配置详解 (转)--SeriesIII
  10. 实体类在set字段时报空指针异常
  11. sql server 安装时提示要重启
  12. 中计算均方误差_为什么分类问题不使用均方误差作为代价函数
  13. (转)利用Eclipse创建maven项目并生成META-INF和WEB-INF目录
  14. 单片机应用系统设计技术——单片机出租车计费器
  15. c语言 结构体数组嵌套另一个结构体数组怎么初始化?,如何初始化结构体数组(内嵌结构体)...
  16. CSS 小技巧:如何保留 hover 的状态?
  17. AppScan-Authentication Bypass Using HTTP Verb Tampering
  18. 工业界中NLP(自然语言处理)算法工程师的核心竞争力是什么?
  19. 红色警戒2修改器原理百科(二)
  20. maven项目报error in opening zip file.

热门文章

  1. SPQuery 的若干.....小问题.......
  2. INDEX函数与MATCH函数嵌套使用技巧
  3. 无线网DNS服务器有错误,关于dns错误的原因和解决办法
  4. Centos Linux破解开机密码
  5. 设置 Scite编辑器的默认编辑为 UTF-8 ,及其他一些参数配置
  6. 该用哪些方式来提高自己的开发效率?
  7. OpenCV与图像算法笔记
  8. GPU显卡服务器有什么作用,可应用哪些方面呢
  9. Python3 将本地时间转换成指定时区时间
  10. 高盛:79页区块链报告-《从理论到实践》(附下载)