STM32项目设计:基于STM32F4的电子阅读器制作教程_stm32f4设计-程序员宅基地

技术标签: stm32  毕业设计  单片机教程  嵌入式  单片机  


QQ交流群1:981140834
QQ交流群2:473982062
QQ交流群3:718245727
QQ交流群4:598455837

基于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
取走记得点赞

实物链接: https://m.tb.cn/h.5hxriuv?tk=YVImWYHgXXF CZ3457

一、项目功能要求

项目说明:

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

用到的主要技术:

  • 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);//设置系统中断优先级分组2
	delay_init(168);  //初始化延时函数
	uart_init(115200);		//初始化串口波特率为115200
	LED_Init();					//初始化LED  
 	LCD_Init();					//LCD初始化  
 	KEY_Init();					//按键初始化 
	tp_dev.init();			//触摸初始化	
	W25QXX_Init();				//初始化W25Q128
	usmart_dev.init(168);		//初始化USMART
	my_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();//保存书籍数据到flash
									printf("当前图书数量:%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通讯录管理系统(暂无博客)

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/mbs520/article/details/110817173

智能推荐

874计算机科学基础综合,2018年四川大学874计算机科学专业基础综合之计算机操作系统考研仿真模拟五套题...-程序员宅基地

文章浏览阅读1.1k次。一、选择题1. 串行接口是指( )。A. 接口与系统总线之间串行传送,接口与I/0设备之间串行传送B. 接口与系统总线之间串行传送,接口与1/0设备之间并行传送C. 接口与系统总线之间并行传送,接口与I/0设备之间串行传送D. 接口与系统总线之间并行传送,接口与I/0设备之间并行传送【答案】C2. 最容易造成很多小碎片的可变分区分配算法是( )。A. 首次适应算法B. 最佳适应算法..._874 计算机科学专业基础综合题型

XShell连接失败:Could not connect to '192.168.191.128' (port 22): Connection failed._could not connect to '192.168.17.128' (port 22): c-程序员宅基地

文章浏览阅读9.7k次,点赞5次,收藏15次。连接xshell失败,报错如下图,怎么解决呢。1、通过ps -e|grep ssh命令判断是否安装ssh服务2、如果只有客户端安装了,服务器没有安装,则需要安装ssh服务器,命令:apt-get install openssh-server3、安装成功之后,启动ssh服务,命令:/etc/init.d/ssh start4、通过ps -e|grep ssh命令再次判断是否正确启动..._could not connect to '192.168.17.128' (port 22): connection failed.

杰理之KeyPage【篇】_杰理 空白芯片 烧入key文件-程序员宅基地

文章浏览阅读209次。00000000_杰理 空白芯片 烧入key文件

一文读懂ChatGPT,满足你对chatGPT的好奇心_引发对chatgpt兴趣的表述-程序员宅基地

文章浏览阅读475次。2023年初,“ChatGPT”一词在社交媒体上引起了热议,人们纷纷探讨它的本质和对社会的影响。就连央视新闻也对此进行了报道。作为新传专业的前沿人士,我们当然不能忽视这一热点。本文将全面解析ChatGPT,打开“技术黑箱”,探讨它对新闻与传播领域的影响。_引发对chatgpt兴趣的表述

中文字符频率统计python_用Python数据分析方法进行汉字声调频率统计分析-程序员宅基地

文章浏览阅读259次。用Python数据分析方法进行汉字声调频率统计分析木合塔尔·沙地克;布合力齐姑丽·瓦斯力【期刊名称】《电脑知识与技术》【年(卷),期】2017(013)035【摘要】该文首先用Python程序,自动获取基本汉字字符集中的所有汉字,然后用汉字拼音转换工具pypinyin把所有汉字转换成拼音,最后根据所有汉字的拼音声调,统计并可视化拼音声调的占比.【总页数】2页(13-14)【关键词】数据分析;数据可..._汉字声调频率统计

linux输出信息调试信息重定向-程序员宅基地

文章浏览阅读64次。最近在做一个android系统移植的项目,所使用的开发板com1是调试串口,就是说会有uboot和kernel的调试信息打印在com1上(ttySAC0)。因为后期要使用ttySAC0作为上层应用通信串口,所以要把所有的调试信息都给去掉。参考网上的几篇文章,自己做了如下修改,终于把调试信息重定向到ttySAC1上了,在这做下记录。参考文章有:http://blog.csdn.net/longt..._嵌入式rootfs 输出重定向到/dev/console

随便推点

uniapp 引入iconfont图标库彩色symbol教程_uniapp symbol图标-程序员宅基地

文章浏览阅读1.2k次,点赞4次,收藏12次。1,先去iconfont登录,然后选择图标加入购物车 2,点击又上角车车添加进入项目我的项目中就会出现选择的图标 3,点击下载至本地,然后解压文件夹,然后切换到uniapp打开终端运行注:要保证自己电脑有安装node(没有安装node可以去官网下载Node.js 中文网)npm i -g iconfont-tools(mac用户失败的话在前面加个sudo,password就是自己的开机密码吧)4,终端切换到上面解压的文件夹里面,运行iconfont-tools 这些可以默认也可以自己命名(我是自己命名的_uniapp symbol图标

C、C++ 对于char*和char[]的理解_c++ char*-程序员宅基地

文章浏览阅读1.2w次,点赞25次,收藏192次。char*和char[]都是指针,指向第一个字符所在的地址,但char*是常量的指针,char[]是指针的常量_c++ char*

Sublime Text2 使用教程-程序员宅基地

文章浏览阅读930次。代码编辑器或者文本编辑器,对于程序员来说,就像剑与战士一样,谁都想拥有一把可以随心驾驭且锋利无比的宝剑,而每一位程序员,同样会去追求最适合自己的强大、灵活的编辑器,相信你和我一样,都不会例外。我用过的编辑器不少,真不少~ 但却没有哪款让我特别心仪的,直到我遇到了 Sublime Text 2 !如果说“神器”是我能给予一款软件最高的评价,那么我很乐意为它封上这么一个称号。它小巧绿色且速度非

对10个整数进行按照从小到大的顺序排序用选择法和冒泡排序_对十个数进行大小排序java-程序员宅基地

文章浏览阅读4.1k次。一、选择法这是每一个数出来跟后面所有的进行比较。2.冒泡排序法,是两个相邻的进行对比。_对十个数进行大小排序java

物联网开发笔记——使用网络调试助手连接阿里云物联网平台(基于MQTT协议)_网络调试助手连接阿里云连不上-程序员宅基地

文章浏览阅读2.9k次。物联网开发笔记——使用网络调试助手连接阿里云物联网平台(基于MQTT协议)其实作者本意是使用4G模块来实现与阿里云物联网平台的连接过程,但是由于自己用的4G模块自身的限制,使得阿里云连接总是无法建立,已经联系客服返厂检修了,于是我在此使用网络调试助手来演示如何与阿里云物联网平台建立连接。一.准备工作1.MQTT协议说明文档(3.1.1版本)2.网络调试助手(可使用域名与服务器建立连接)PS:与阿里云建立连解释,最好使用域名来完成连接过程,而不是使用IP号。这里我跟阿里云的售后工程师咨询过,表示对应_网络调试助手连接阿里云连不上

<<<零基础C++速成>>>_无c语言基础c++期末速成-程序员宅基地

文章浏览阅读544次,点赞5次,收藏6次。运算符与表达式任何高级程序设计语言中,表达式都是最基本的组成部分,可以说C++中的大部分语句都是由表达式构成的。_无c语言基础c++期末速成