一、电路设计
此电路由STM32最小系统板、800*480 4.3寸电容触摸LCD屏、一张32G以下的SD卡和一个读卡器组成。
项目偏软件,但是要依赖于自己对硬件的熟悉和驱动才能完成,用到的主要技术:
1)SD卡驱动(难–不过可移植 SD卡驱动细节可在用完再了解其驱动协议)
2)FatFs文件系统移植使用
3)LCD屏驱动(加载字库文件 做字库在LCD上的显示)
二、原理图
三、部分代码
#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; //图片目录
u32 recode=0;
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.
/******************防止二次烧入****************************/
W25QXX_Read((u8 *)&recode,1024*1024*4-4,4);//读出到内存
if(recode != 0xffaaffaa)
{
recode = 0xffaaffaa;
W25QXX_Write((u8 *)&recode,1024*1024*4-4,4);//写入flash
//W25QXX_Erase_Chip();//擦除整片
txt_num=0;//初始化小说本数0 不然程序无法运行
save_bookinfo();//保存到flash
}
/******************防止二次烧入****************************/
while(font_init()) //检查字库
{
LCD_Clear(WHITE); //清屏
POINT_COLOR=RED; //设置字体为红色
LCD_ShowString(30,50,200,16,16,"Explorer STM32F4");
while(SD_Init()) //检测SD卡
{
LCD_ShowString(30,70,200,16,16,"SD Card Failed!");
delay_ms(200);
LCD_Fill(30,70,200+30,70+16,WHITE);
delay_ms(200);
}
LCD_ShowString(30,70,200,16,16,"SD Card OK");
LCD_ShowString(30,90,200,16,16,"Font Updating...");
key=update_font(20,110,16,"0:");//更新字库
while(key)//更新失败
{
LCD_ShowString(30,110,200,16,16,"Font Update Failed!");
delay_ms(200);
LCD_Fill(20,110,200+20,110+16,WHITE);
delay_ms(200);
}
LCD_ShowString(30,110,200,16,16,"Font Update Success! ");
delay_ms(1500);
LCD_Clear(WHITE);//清屏
}
//f_opendir(&picdir;,"0:/SYSTEM/PICTURE"); //打开目录
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);
}
}
//阅读模式 进入阅读
void read_mode(void)
{
int key;
u8 res,n;
char spr_name[30];
sprintf((char *)spr_name,"%s",pname);
res=mf_open((char *)spr_name,FA_READ);//只读打开
if(res==FR_OK)printf("打开:%s\n",(char *)spr_name);
else return;//打开失败
LCD_Clear(WHITE);//清屏
n=page/1000+1;//计算要更新几次
while(n--)
{
LCD_ShowNum(200,376,page/1000+1-n,2,24);//显示进度条
LCD_ShowChar(234,376,'/',24,0);
LCD_ShowNum(250,376,page/1000+1,2,24);
file_data_to_w25q(); //更新页数 一次1000页
}
mf_lseek(page_offset[page%1000]);//得到初始偏移
read_to_lcd();//读取文档数据到屏幕
Show_Str(420,770,200,24,"返回",24,0);
Show_Str(5,770,50,24,"设置",24,0);
Show_Str(218,770,50,24,"目录",24,0);
LCD_ShowNum(400,0,page,5,16);
while(1)
{
key = get_ts_val(2);
if(key != 0)
{
// printf("key == %d\n",key);
switch(key)//操作选择
{
case 101:
page++;
if(page%1000==0 && page>0)
{
//更新缓冲页码数组
file_data_to_w25q();//先写入页码到flash
update_page_offset();//更新内存1000页页码
}
res=mf_lseek(page_offset[page%100]);
if(res==0)read_to_lcd();
break;//下一页
case 202:
if(page==0)
{
Show_Str(180,730,200,24,(u8*)"已经是第一页",24,0);
break;
}
page--;
if(page%999==0 && page>0)
{
update_page_offset();//更新内存1000页页码
}
res=mf_lseek(page_offset[page%1000]);
if(res==0)read_to_lcd();
break;//上一页
case 303:
case 404:break;
case 5:
return;//保存数据到flash//返回
case 6:
res=setting();
if(res) //修改设置退出
{
res=0;
LCD_Clear(BACK_COLOR);//设置完还原界面
Show_Str(50,50,400,700,(u8 *)buff,SIZE,0);
}else //返回退出
{
LCD_Fill(0,570,480,800,BACK_COLOR);
Show_Str(50,50,400,700,(u8 *)buff,SIZE,0);
}
break;
case 7:page=txt_dir_scan();//目录扫描 返回页数
update_page_offset();//更新内存1000页页码
res=mf_lseek(page_offset[page%1000]);//偏移到页码
if(res==0)read_to_lcd();
break;
}
Show_Str(420,770,200,24,"返回",24,0);
Show_Str(5,770,50,24,"设置",24,0);
Show_Str(218,770,50,24,"目录",24,0);
LCD_ShowNum(400,0,page,5,16);
//printf("lseek=%ld\n",offset);
}
}
}
🔥 项目分享:
https://gitee.com/feifei1122/simulation-project