基于STM32的小说阅读器

1.硬件平台

  • CPU:STM32F103ZE
  • 屏幕:3.5寸TFTLCD屏
  • 触控:电阻式触摸屏xpt2046
  • SD卡

2.实现功能

  1.SD卡设备检测,文件系统移植,用户存储小说和字库文件;
  2.字库信息加载检测,自动完成字库信息加载与更新。本次采用GBK字库,字体大小有16*16、24*24、32*32三个字库;
  3.触摸屏校准,上电检测触摸屏校准信息;手动进入触摸屏校准模式
  4.小说文件索引,小说文本切换;
  5.小说翻页,字体大小选择,颜色选择,返回主目录;

3.示例效果

 SD卡检测和触摸屏校准

 字库检测与更新

 目录和小说显示界面

 颜色切换

 字体选择

4.软件设计

 1.SD卡字库更新加载

/***********************SD卡字库更新***********************/
u8 SDcard_DownFont(const TCHAR* path,u32 addr,u16 font_size)
{FIL fp;u8 res;UINT br;u32 size;u32 cnt=0;u16 y=0;float load=0,load2=0;u8 buff[1024];char buff2[20];/*1.读取文件大小*/FILINFO file_info;f_stat(path,&file_info);size=file_info.fsize;if(size==0)return 1;//printf("文件大小:%u byte\r\n",size);/*2.打开文件*/res=f_open(&fp,path,FA_READ);if(res){// printf("文件打开失败res=%d\r\n",res);return 2;}W25Q64_WriteData(addr-10,(u8 *)"        ",9);//清除标志位if(font_size==16)y=100;else if(font_size==24)y=140;else if(font_size==32)y=180;LCD_Display_Str2(20,y,16,(u8 *)"更新进度:",BLACK,WHITE);LCD_Refresh();while(1){f_read(&fp,buff,1024,&br);W25Q64_WriteData(addr+cnt,buff,br);cnt+=br;load=(cnt*1.0/size)*100;if(load!=load2){load2=load;LCD_Display_Str2(30+strlen("更新进度")/2*16,y,16,(u8 *)"        ",WHITE,WHITE);snprintf(buff2,sizeof(buff2),"%.1f %%",load2);LCD_Display_Str2(30+strlen("更新进度")/2*16,y,16,(u8 *)buff2,RED,WHITE);LCD_Refresh();}//printf("更新进度:%d\r\n",cnt);if(br!=1024)break;}/*写入标志位*/if(font_size==16){strcpy((char *)buff,"GBK16_OK");}else if(font_size==24){strcpy((char *)buff,"GBK24_OK");}else if(font_size==32){strcpy((char *)buff,"GBK32_OK");}W25Q64_WriteData(addr-10,buff,9);//GBK16_OKf_close(&fp);//关闭文件return 0;
}

 2.获取小说文件信息

/*SD卡操作函数*/
typedef struct FILE_info
{char file_name[100];u32 file_size;u16 y;/*在屏幕位置*/struct FILE_info *next;struct FILE_info *pre;
}FILE_INFO;
FILE_INFO *story_head=NULL;
/*创建链表*/
FILE_INFO *List_CreateHead(FILE_INFO *head)
{if(head!=NULL)return head;head=malloc(sizeof(FILE_INFO));head->next=NULL;head->pre=NULL;return head;
}
/*添加节点*/
FILE_INFO *List_AddNode(FILE_INFO *head)
{if(head==NULL)return NULL;//链表头不存在FILE_INFO *phead=head;while(phead->next!=NULL){phead=phead->next;}FILE_INFO *new_node=malloc(sizeof(FILE_INFO));new_node->pre=phead;phead->next=new_node;new_node->next=NULL;return new_node;
}
/*遍历节点*/
void List_PrintNode(FILE_INFO *head)
{u16 x=20,y=50;LCD_Display_Str2(LCD_WIDTH/2-24,10,16,(u8 *)"书 架",BLACK,WHITE);if(head==NULL)return ;//链表头不存在FILE_INFO *phead=head;while(phead->next!=NULL){phead=phead->next;phead->y=y;LCD_Display_Str2(x,phead->y,16,(u8 *)phead->file_name,DARKBLUE,WHITE);//显示字符串y+=35;//printf("%s,%d\r\n",phead->file_name,phead->file_size);}LCD_Refresh();
}
u16 List_CheckNode(FILE_INFO *head,u16 y,u8 *file_name)
{if(head==NULL)return 0;//链表头不存在FILE_INFO *phead=head;while(phead->next!=NULL){phead=phead->next;if(y<=phead->y+26 && y>=phead->y-5){strcpy((char *)file_name,phead->file_name);return phead->y;}}return 0;//未找到
}
/*************************************目录遍历(读取小说文件信息)************************/
u8 FATFS_printDir(const TCHAR* path)
{DIR dp;u8 res;u8 stat=0;story_head=List_CreateHead(story_head);//创建链表头res=f_opendir(&dp,path);FILINFO file_info;if(res){printf("打开目录失败res=%d\r\n",res);free(story_head);//释放链表头return 1;}FILE_INFO *temp=NULL;while(1){res=f_readdir(&dp,&file_info);if(res!=FR_OK || file_info.fname[0]==0)break;if(strstr(file_info.fname,".txt")){temp=List_AddNode(story_head);if(temp==NULL){stat=2;//动态分配空间失败goto AA;}//printf("文件名:%s,",file_info.fname);strcpy(temp->file_name,file_info.fname);//文件名if(file_info.fattrib == AM_ARC)//普通文件{temp->file_size=file_info.fsize;//文件大小//printf("文件大小:%u byte\r\n",file_info.fsize);}}}
AA:f_closedir(&dp);//关闭目录List_PrintNode(story_head);return stat;
}

 3.读取小说内容,翻页,字体选择、颜色切换

/*打开小说*/
u8 buff_read[4098];
const u16 font_corlour[]={BLACK,BLUE,RED,LIGHTGREEN};
void FATFS_ReadFile(const char *file_name)
{FIL fp;//文件指针u8 res=0;UINT br;u32 font_buff[20];//保存每页字节数据u16 font_cnt=0;u16 font_len=0;u16 font_size=16;//字体大小u16 x=0,y=20;u8 corlour=0;char name[100];snprintf(name,sizeof(name),"0:/Text/%s",file_name);res=f_open(&fp,name,FA_READ);//打开文件if(res){printf("文件打开失败res=%d\r\n",res);return ;}u8 *p;u16 x1,y1;u8 stat=0;while(1){    if(stat){buff_read[0]=stat;stat=0;res=f_read(&fp,&buff_read[1],4095,&br);br++;buff_read[br]='\0';}else{res=f_read(&fp,buff_read,4096,&br);buff_read[br]='\0';}p=buff_read;while(*p){font_len=LCD_Display_Str(x,y,font_size,p,font_corlour[corlour]);//显示字符串LCD_Refresh();while(1){res=XPT2046_ReadXY();//触摸屏检测if(res){x1=xpt2046_info.x;y1=xpt2046_info.y; while(T_PEN==0){}//等待松开//printf("x1=%d,y1=%d\r\n",x1,y1);if((x1>=212 && x1<=320) && (y1>=416 && y1<=480))//返回{LcdFill(0,0,320,480,WHITE);List_PrintNode(story_head);return ;}else if((x1>=106 && x1<=210) && (y1>=416 && y1<=480))//字体颜色{corlour++;if(corlour>=4)corlour=0;LcdFill(0,0,320,410,WHITE);break;}else if((x1>=1 && x1<=105) && (y1>=416 && y1<=480))//字体大小调节{if(font_size==16)font_size=24;else if(font_size==24)font_size=32;else if(font_size==32)font_size=16;LcdFill(0,0,320,410,WHITE);break;}else if(x1>160 && y1<=380){p+=font_len&0x7fff;if(*p!='\0'){font_buff[font_cnt++]=font_len&0x7fff;LcdFill(0,0,320,410,WHITE);break;}else {if(font_len&0x8000){stat=*(p-1);}LcdFill(0,0,320,410,WHITE);break;}}else if(x1<160 && y1<=380){if(p!=buff_read && font_cnt>0){font_cnt--;p-=font_buff[font_cnt];LcdFill(0,0,320,410,WHITE);break;}}}}}font_cnt=0;memset(buff_read,0,sizeof(buff_read));if(br!=4096)break;}
}

 4.主函数main.c,硬件初始化,触摸屏校准,字体检测与更新,主界面显示

#include "stm32f10x.h"
#include "beep.h"
#include "led.h"
#include "key.h"
#include "delay.h"
#include "usart.h"
#include "w25q64.h"
#include "at24c08.h"
#include "timer.h"
#include <string.h>
#include "xpt2046.h"
#include "nt35310.h"
#include "sram.h"
#include <stdlib.h>
#include "ff.h"//文件系统头文件
#include "sdcard.h"
u8 SDcard_DownFont(const TCHAR* path,u32 addr,u16 font_size);//字库更新
u8 FATFS_printDir(const TCHAR* path);//遍历目录
u16 List_CheckNode(FILE_INFO *head,u16 y,u8 *file_name);//查找文件
void FATFS_ReadFile(const char *file_name);//读文件
FATFS fs;
int main()
{u16 y=0;char buff[30];u8 res=0;Beep_Init();Led_Init();Key_Init();Usartx_Init(USART1,115200,72);printf("串口初始化完成\r\n");W25Q64_Init();IIC_Init();LCD_Init();Sram_Init();XPT2046_Init();//初始化Touch_Calibration();
AA:LCD_Clear(WHITE);//清屏函数LCD_Refresh();LCD_Display_Str2(20,20,16,(u8 *)"SD卡状态",RED,WHITE);res=f_mount(&fs,"0:",1);//磁盘挂载if(res){printf("SD卡挂载失败ERR=%d\r\n",res);snprintf(buff,sizeof(buff),"err%d",res);LCD_Display_Str2(20+strlen("SD卡状态")*12+20,20,16,(u8 *)buff,RED,WHITE);LCD_Display_Str2(20,50,16,(u8 *)"请检查SD卡是否插入!",RED,WHITE);LCD_Refresh();Delay_Ms(500);goto AA;}else LCD_Display_Str2(20+strlen("SD卡状态")*12+20,20,16,(u8 *)"OK",RED,WHITE);/*字库检测*/LCD_Display_Str2(LCD_WIDTH/2-strlen("字库检测")/2*16,40,16,(u8 *)"字库检测",RED,WHITE);LCD_Refresh();GBK_16:W25Q64_ReadData(GBK_16_ADDR-10,(u8*)buff,9);//GBK16_OKif(strstr(buff,"GBK16_OK")){LCD_Display_Str2(20,60,16,(u8 *)"GBK16    OK",RED,WHITE);LCD_Refresh();}else {LCD_Display_Str2(20,60,16,(u8 *)"GBK16    NO",RED,WHITE);LCD_Display_Str2(LCD_WIDTH/2-strlen("更新GBK16字库")/2*16,80,16,(u8 *)"更新GBK16字库",RED,WHITE);LCD_Refresh();if(SDcard_DownFont("0:/font/GBK_16.DZK",GBK_16_ADDR,16))//字库更新{LCD_Display_Str2(LCD_WIDTH/2-strlen("                 ")/2*16,80,16,(u8 *)"                 ",WHITE,WHITE);LCD_Display_Str2(10,80,16,(u8 *)"请将GBK_16.DZK放到/font/目录下,重启!",BLACK,WHITE);LCD_Refresh();}else {LCD_Display_Str2(LCD_WIDTH/2-strlen("                 ")/2*16,80,16,(u8 *)"                 ",WHITE,WHITE);LCD_Display_Str2(20,100,16,(u8 *)"                   ",WHITE,WHITE);LCD_Refresh();goto GBK_16;}}/*GBK24_OK*/
GBK_24:W25Q64_ReadData(GBK_24_ADDR-10,(u8*)buff,9);if(strstr(buff,"GBK24_OK")){LCD_Display_Str2(20,100,16,(u8 *)"GBK24    OK",RED,WHITE);LCD_Refresh();}else {LCD_Display_Str2(20,100,16,(u8 *)"GBK24    NO",RED,WHITE);LCD_Display_Str2(LCD_WIDTH/2-strlen("更新GBK24字库")/2*16,120,16,(u8 *)"更新GBK24字库",RED,WHITE);LCD_Refresh();if(SDcard_DownFont("0:/font/GBK_24.DZK",GBK_24_ADDR,24))//字库更新{LCD_Display_Str2(LCD_WIDTH/2-strlen("                 ")/2*16,120,16,(u8 *)"                 ",WHITE,WHITE);LCD_Display_Str2(10,120,16,(u8 *)"请将GBK_24.DZK放到/font/目录下,重启!",BLACK,WHITE);LCD_Refresh();}else {LCD_Display_Str2(LCD_WIDTH/2-strlen("                 ")/2*16,120,16,(u8 *)"                 ",WHITE,WHITE);LCD_Display_Str2(20,140,16,(u8 *)"                   ",WHITE,WHITE);LCD_Refresh();goto GBK_24;}}/*GBK32_OK*/
GBK_32:W25Q64_ReadData(GBK_32_ADDR-10,(u8*)buff,9);if(strstr(buff,"GBK32_OK")){LCD_Display_Str2(20,140,16,(u8 *)"GBK32    OK",RED,WHITE);LCD_Refresh();}else {LCD_Display_Str2(20,140,16,(u8 *)"GBK32    NO",RED,WHITE);LCD_Refresh();LCD_Display_Str2(LCD_WIDTH/2-strlen("更新GBK32字库")/2*16,160,16,(u8 *)"更新GBK32字库",RED,WHITE);LCD_Refresh();if(SDcard_DownFont("0:/font/GBK_32.DZK",GBK_32_ADDR,32))//字库更新{LCD_Display_Str2(LCD_WIDTH/2-strlen("                 ")/2*16,160,16,(u8 *)"                 ",WHITE,WHITE);LCD_Display_Str2(10,160,16,(u8 *)"请将GBK_32.DZK放到/font/目录下,重启!",BLACK,WHITE);LCD_Refresh();}else {LCD_Display_Str2(LCD_WIDTH/2-strlen("                 ")/2*16,160,16,(u8 *)"                 ",WHITE,WHITE);LCD_Display_Str2(20,180,16,(u8 *)"                   ",WHITE,WHITE);LCD_Refresh();goto GBK_32;}}Delay_Ms(1000);Delay_Ms(1000);Delay_Ms(1000);LCD_Clear(WHITE);//清屏函数LCD_Refresh();FATFS_printDir("0:/Text/");while(1){  res=XPT2046_ReadXY();if(res){//printf("x,y=%d,%d\r\n",xpt2046_info.x,xpt2046_info.y);y=List_CheckNode(story_head,xpt2046_info.y,(u8 *)buff);if(y){LcdFill(0,y-8,320,y+24,LIGHTGREEN);LCD_Display_Str2(20,y,16,(u8 *)buff,DARKBLUE,LIGHTGREEN);//显示字符串LCD_Refresh();while(T_PEN==0){}//等待松开LcdFill(0,0,320,480,WHITE);OLED_DrawRectangle(1, 415, 319,479,BLACK);//绘制矩形OLED_DrawRectangle(2, 416, 318,478,BLACK);//绘制矩形LCD_DrawLine(105, 415, 105, 479,BLACK);LCD_DrawLine(106, 415, 106, 479,BLACK);LCD_DrawLine(211, 415, 211, 479,BLACK);LCD_DrawLine(212, 415, 212, 479,BLACK);LCD_Display_Str2(5,415+20,24,(u8 *)"字体大小",BLACK,WHITE);//显示字符串LCD_Display_Str2(106+5,415+20,24,(u8 *)"字体颜色",BLACK,WHITE);//显示字符串LCD_Display_Str2(212+29,415+20,24,(u8 *)"返回",BLACK,WHITE);//显示字符串LCD_Refresh();FATFS_ReadFile(buff);}}}
}

5.完整示例

https://download.csdn.net/download/weixin_44453694/84997777

基于STM32的小说阅读器相关推荐

  1. 基于python简易小说阅读器(一)

    基于python简易小说阅读器(一) 实现功能:界面显示小说内容,界面的最下方有按键实现章节切换   后台需要有小说内容的数据,针对这一块,python的爬虫模块requests可以满足项目需求,前端 ...

  2. 基于python简易小说阅读器(二)

    基于python简易小说阅读器(二)   在基于python简易小说阅读器(一)中,用requests模块和beautifulsoup模块完成了阅读器的后台,实现了下载小说内容的功能,现在用tkint ...

  3. 基于STM32设计的小说阅读器(翻页、字体切换、颜色切换、语音播报)

    一.环境介绍 小车主控MCU: STM32F103ZET6 STM32程序开发IDE: keil5 STM32程序风格:  采用寄存器方式开发,注释齐全,执行效率高,方便移植 硬件包含:  一块STM ...

  4. 基于Android的看小说APP源码Android本科毕业设计Android小说阅读器、小说APP源码

    基于kotlin + 协程 + MVVM 模式来编写的看小说APP. 完整代码下载地址:基于Android的看小说APP源码Android本科毕业设计Android小说阅读器.小说APP源码 主要框架 ...

  5. 基于Python(Tkinter)实现(图形界面)小说阅读器【100010450】

    计算机网络 Project-小说阅读器 一.概述 本文为 2019 秋计算机网络课程 Socket 编程实验报告,我选择了小说阅读器作为实现对象.本节主要阐述任务要求.项目概述及文章框架. 1.1 任 ...

  6. android 上下滚动文字_计算机毕设项目004之Android系统在线小说阅读器

    计算机毕设项目004之Android系统在线小说阅读器 一. 项目名称 基于Android系统的在线小说阅读器 二. 项目简介 项目中的角色功能: 支持翻页动画:仿真翻页.覆盖翻页.上下滚动翻页等翻页 ...

  7. ios 分段 判断 小说阅读器_还在用别的小说阅读器?今天教你用Python制作简易小说阅读器!...

    本文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理 以下文章来源于腾讯云 作者:Python进阶者 /前言/ 不知从什么时候开始.小说 ...

  8. 免费小说阅读器(Android版本)全站开源

    此小说阅读器只追求两项 极简(无广告,无添加) 丰富(内容丰富,只有你想不到的,没有它没有的) 漫品客户端 全站开源 开源地址: https://github.com/AnyMarvel/ManPin ...

  9. python写小说阅读器_手把手教你用Python制作简易小说阅读器

    /前言/ 不知从什么时候开始.小说开始掀起了一股浪潮,它让我们平日里的生活不在枯燥乏味,很多我们做不到的事情在小说里都能轻易实现. 今天我们要做的就是一个小说阅读器了,一个可以将你的文章中的字每隔多少 ...

  10. 套路继续, .txt 小说阅读器功能开发

    1, 解决一个 bug 正文结尾 (最后一行最后一个字)跟右边界, 有多余的空白间隔 Core Text 的渲染流程,就是富文本绘制 从流程上看, 感觉这一页的文字分配少了,给他加点字,就满了 // ...

最新文章

  1. Python pandas
  2. MySQL 优化实战记录 1
  3. C语言枚举类型(enum)的各种用法
  4. Python地理数据处理相关模块的安装方法
  5. 2020-8-5 Codeforces摸鱼报告
  6. 洗地机之滚刷电机分析:关于电机转矩.功率.转速之间的关系及计算公式
  7. Qt拖拽实现绘制流程图
  8. linux usb有线网卡驱动_Linux下安装USB网卡驱动 | 学步园
  9. 联想主板怎么进入bios
  10. 微信小程序获取用户微信绑定手机号
  11. 【LEACH协议】基于matlab实现无线传感器网络LEACH与DEEC协议
  12. java代理模式教你中间商赚差价
  13. php函数参数中括号,thinkphp手册中函数的可选参数的中括号为什么是包含的关系?...
  14. Android 实现浏览器打开app
  15. 如何在基于vue-cli的项目中,使用精灵图 css sprite
  16. Comet OJ - Contest #10 沉鱼落雁
  17. 江苏电信服务器托管/1U托管/4G硬防
  18. python爬虫-多线程小说批量下载
  19. 西密歇根大学计算机科学专业排名,西密歇根大学有哪些专业_专业排名(USNEWS美国大学排名)...
  20. java判断折扣价格

热门文章

  1. 需求文档(PRD)撰写指南
  2. SQL server增删改查
  3. rv1126+imx307/335/415公板使用总结
  4. 前端实现成绩管理系统
  5. 各种loading加载中gif图标
  6. python爬虫之cookie和session介绍——以12306验证码破解和浏览车次为例
  7. C语言编程 开方,c编程中开方怎么表示
  8. Win11如何给系统盘瘦身?Win11系统盘瘦身方法
  9. 网站建设的一般原则及网站推广技巧
  10. UE4_BIM替换材质处理流程