#ifndef __FONTUPD_H__
#define __FONTUPD_H__
#include "sys.h"
//字库信息结构体定义33字节
__packed typedef struct
{
u8 fontok; //字库存在标志,0XAA,字库正常;其他,字库不存在
u32 ugbkaddr; //unigbk的地址
u32 ugbksize; //unigbk的大小
u32 f12addr; //gbk12地址
u32 gbk12size; //gbk12的大小
u32 f16addr; //gbk16地址
u32 gbk16size; //gbk16的大小
u32 f24addr; //gbk24地址
u32 gkb24size; //gbk24的大小
}_font_info;
extern _font_info ftinfo; //汉字库信息结构体
//字库信息结构体定义 25字节
//第1个字节用于标记字库是否存在.后续分别保存起始地址和文件大小
__packed typedef struct
{
u8 fontflag; //字库存在标志,0XAA,字库正常;其他,字库不存在
u32 asc1206_addr; //asc1206的地址
u32 asc1206_size; //asc1206的大小
u32 asc1608_addr; //asc1608地址
u32 asc1608_size; //asc1608的大小
u32 asc2412_addr; //asc2412地址
u32 asc2412_size; //asc2412的大小
} _ascii_font;
extern _ascii_font ascii_font; //ascii字库信息结构体
u8 updata_HZ_fontx(u8 *fxpath,u8 fx); //更新指定字库
u8 update_HZ_font(u8* src); //更新全部字库
u8 HZ_font_init(void); //初始化字库
u8 updata_ascii_fontx(u8 *fxpath,u8 fx); //更新指定字库
u8 update_ascii_font(u8* src); //更新全部字库
u8 ascii_font_init(void); //初始化字库
u8 font_init(void);
void updateHZfont(void);
void updateasciifont(void);
#endif
#include "fontupd.h"
#include "malloc.h"
#include "ff.h"
#include "w25qxx.h"
#include "string.h"
#include "delay.h"
#include "usart.h"
/* ascii字库在flash中的地址及大小(字节)
fontflagaddr=15831040 ascii_font_size=25
asc1206_addr=15831065 asc1206_size=1140
asc1608_addr=15832205 asc1608_size=1520
asc2412_addr=15833725 asc2412_size=3420
*/
//W25Q128FVFIG容量有128Mbit = 16MB
//前面12M被fatfs占用了,从12M地址以后存放字库结构体、UNIGBK.bin、和三个字库
//地址: (1024*12)*1024 字节处,大小约 3.09M,不能动!
//15.10M以后,存放ASCII三个字库
//首地址: 1024*1024*15 + 1024*100 =15831040字节处 字库总大小25+ 6080字节,也不能动 !
//15.20M以后剩余0.8M字节空间,用户可以使用。
//汉字库区域占用的总扇区数大小(3个字库+unigbk表+字库信息=3238700字节,3238700/512=791)
//ascii字库区域占用的总扇区数大小 //(字库信息结构体+字库 = 25+ 6080字节,占12个W25QXX扇区)
#define ASCII_FONT_SECSIZE 12 //ascii字库占用扇区
#define ASCIIFONTINFOADDR 1024*1024*15 + 1024*100 //ascii字库起始地址
#define FONTSECSIZE 791 //汉字库占用扇区
#define FONTINFOADDR 1024*1024*12 //汉字库起始地址
_font_info ftinfo; //用来保存字库基本信息,地址,大小等
_ascii_font ascii_font; //用来保存字库基本信息,地址,大小等
//汉字库存放在磁盘中的路径
u8*const GBK24_PATH="/SYSTEM/FONT/GBK24.FON"; //GBK24的存放位置
u8*const GBK16_PATH="/SYSTEM/FONT/GBK16.FON"; //GBK16的存放位置
u8*const GBK12_PATH="/SYSTEM/FONT/GBK12.FON"; //GBK12的存放位置
u8*const UNIGBK_PATH="/SYSTEM/FONT/UNIGBK.BIN"; //UNIGBK.BIN的存放位置
//ascii字库存放在磁盘中的路径
u8*const ASC1206_PATH="/SYSTEM/FONT/ASC1206.dat"; //asc1206的存放位置
u8*const ASC1608_PATH="/SYSTEM/FONT/ASC1608.dat"; //asc1608的存放位置
u8*const ASC2412_PATH="/SYSTEM/FONT/ASC2412.dat"; //asc2412的存放位置
//更新某一个
//fxpath:路径
//fx:更新的内容 0,ungbk;1,gbk12;2,gbk16;3,gbk24;
//返回值:0,成功;其他,失败.
u8 updata_HZ_fontx(u8 *fxpath,u8 fx)
{
u32 flashaddr=0;
FIL * fftemp;
u8 *tempbuf;
u8 res;
u16 bread;
u32 offx=0;
u8 rval=0;
fftemp=(FIL*)mymalloc(SRAMIN,sizeof(FIL)); //分配内存
if(fftemp==NULL)rval=1;
tempbuf=mymalloc(SRAMIN,4096); //分配4096个字节空间
if(tempbuf==NULL)rval=1;
res=f_open(fftemp,(const TCHAR*)fxpath,FA_READ);
if(res)rval=2;//打开文件失败
if(rval==0)
{
switch(fx)
{
case 0:
ftinfo.ugbkaddr=FONTINFOADDR+sizeof(ftinfo); //信息头之后,紧跟UNIGBK转换码表
ftinfo.ugbksize=fftemp->fsize; //UNIGBK大小
flashaddr=ftinfo.ugbkaddr;
break;
case 1:
ftinfo.f12addr=ftinfo.ugbkaddr+ftinfo.ugbksize; //UNIGBK之后,紧跟GBK12字库
ftinfo.gbk12size=fftemp->fsize; //GBK12字库大小
flashaddr=ftinfo.f12addr; //GBK12的起始地址
break;
case 2:
ftinfo.f16addr=ftinfo.f12addr+ftinfo.gbk12size; //GBK12之后,紧跟GBK16字库
ftinfo.gbk16size=fftemp->fsize; //GBK16字库大小
flashaddr=ftinfo.f16addr; //GBK16的起始地址
break;
case 3:
ftinfo.f24addr=ftinfo.f16addr+ftinfo.gbk16size; //GBK16之后,紧跟GBK24字库
ftinfo.gkb24size=fftemp->fsize; //GBK24字库大小
flashaddr=ftinfo.f24addr; //GBK24的起始地址
break;
}
while(res==FR_OK)//死循环执行
{
res=f_read(fftemp,tempbuf,4096,(UINT *)&bread); //读取数据
if(res!=FR_OK)break; //执行错误
W25QXX_Write(tempbuf,offx+flashaddr,4096); //从0开始写入4096个数据
offx+=bread;
if(bread!=4096)break; //读完了.
}
f_close(fftemp);
}
myfree(SRAMIN,fftemp); //释放内存
myfree(SRAMIN,tempbuf); //释放内存
return res;
}
//更新字体文件,UNIGBK,GBK12,GBK16,GBK24一起更新
//src:字库来源磁盘."0:",SD卡;"1:",FLASH盘,"2:",U盘.
//提示信息字体大小
//返回值:0,更新成功;
// 其他,错误代码.
u8 update_HZ_font(u8* src)
{
u8 *pname;
u32 *buf;
u8 res=0;
u16 i,j;
FIL *fftemp;
u8 rval=0;
res=0XFF;
ftinfo.fontok=0XFF;
pname=mymalloc(SRAMIN,100); //申请100字节内存
buf=mymalloc(SRAMIN,4096); //申请4K字节内存
fftemp=(FIL*)mymalloc(SRAMIN,sizeof(FIL)); //分配内存
if(buf==NULL||pname==NULL||fftemp==NULL)
{
myfree(SRAMIN,fftemp);
myfree(SRAMIN,pname);
myfree(SRAMIN,buf);
return 5; //内存申请失败
}
//先查找文件是否正常
strcpy((char*)pname,(char*)src); //copy src内容到pname
strcat((char*)pname,(char*)UNIGBK_PATH); //文件路径放到pname后
res=f_open(fftemp,(const TCHAR*)pname,FA_READ);
if(res)rval|=1<<4;//打开文件失败
strcpy((char*)pname,(char*)src); //copy src内容到pname
strcat((char*)pname,(char*)GBK12_PATH);
res=f_open(fftemp,(const TCHAR*)pname,FA_READ);
if(res)rval|=1<<5;//打开文件失败
strcpy((char*)pname,(char*)src); //copy src内容到pname
strcat((char*)pname,(char*)GBK16_PATH);
res=f_open(fftemp,(const TCHAR*)pname,FA_READ);
if(res)rval|=1<<6;//打开文件失败
strcpy((char*)pname,(char*)src); //copy src内容到pname
strcat((char*)pname,(char*)GBK24_PATH);
res=f_open(fftemp,(const TCHAR*)pname,FA_READ);
if(res)rval|=1<<7;//打开文件失败
myfree(SRAMIN,fftemp);//释放内存
if(rval==0)//字库文件都存在.
{
for(i=0;i { W25QXX_Read((u8*)buf,((FONTINFOADDR/4096)+i)*4096,4096);//读出整个扇区的内容 for(j=0;j<1024;j++)//校验数据 { if(buf[j]!=0XFFFFFFFF)break;//需要擦除 } if(j!=1024)W25QXX_Erase_Sector((FONTINFOADDR/4096)+i); //需要擦除的扇区 } myfree(SRAMIN,buf); printf("began to Update HZ font!\r\n"); strcpy((char*)pname,(char*)src); //copy src内容到pname strcat((char*)pname,(char*)UNIGBK_PATH); //文件路径放到pname后 res=updata_HZ_fontx(pname,0); //更新UNIGBK.BIN if(res){myfree(SRAMIN,pname);return 1;} printf("UNIGBK.BIN Update Success!\r\n"); strcpy((char*)pname,(char*)src); //copy src内容到pname strcat((char*)pname,(char*)GBK12_PATH); res=updata_HZ_fontx(pname,1); //更新GBK12.FON if(res){myfree(SRAMIN,pname);return 2;} printf("GBK12.FON Update Success!\r\n"); strcpy((char*)pname,(char*)src); //copy src内容到pname strcat((char*)pname,(char*)GBK16_PATH); res=updata_HZ_fontx(pname,2); //更新GBK16.FON if(res){myfree(SRAMIN,pname);return 3;} printf("GBK16.FON Update Success!\r\n"); strcpy((char*)pname,(char*)src); //copy src内容到pname strcat((char*)pname,(char*)GBK24_PATH); res=updata_HZ_fontx(pname,3); //更新GBK24.FON if(res){myfree(SRAMIN,pname);return 4;} printf("GBK24.FON Update Success!\r\n"); //全部更新好了 ftinfo.fontok=0XAA; W25QXX_Write((u8*)&ftinfo,FONTINFOADDR,sizeof(ftinfo)); //保存字库信息 } else printf("HZ file error!\r\n"); myfree(SRAMIN,pname);//释放内存 myfree(SRAMIN,buf); return rval;//无错误. } //初始化字体 //返回值:0,字库完好. //其他,字库丢失 u8 HZ_font_init(void) { u8 t=0; W25QXX_Init(); while(t<10)//连续读取10次,都是错误,说明确实是有问题,得更新字库了 { t++; W25QXX_Read((u8*)&ftinfo,FONTINFOADDR,sizeof(ftinfo));//读出ftinfo结构体数据 if(ftinfo.fontok==0XAA)break; delay_ms(20); } if(ftinfo.fontok!=0XAA)return 1; return 0; } //更新某一个 //fxpath:路径 //fx:要更新的内容 0asc1206;1,asc1608;2,asc2412; //返回值:0,成功;其他,失败. u8 updata_ascii_fontx(u8 *fxpath,u8 fx) { u32 flashaddr=0; FIL * fftemp; u8 *tempbuf; u8 res; u16 bread; u32 offx=0; u8 rval=0; fftemp=(FIL*)mymalloc(SRAMIN,sizeof(FIL)); //分配内存 if(fftemp==NULL)rval=1; tempbuf=mymalloc(SRAMIN,4096);//分配4096个字节空间 if(tempbuf==NULL)rval=1; res=f_open(fftemp,(const TCHAR*)fxpath,FA_READ); //打开文件 if(res)rval=2;//打开文件失败 if(rval==0) { switch(fx) { case 0: ascii_font.asc1206_addr=ASCIIFONTINFOADDR+sizeof(ascii_font);//信息头之后,紧跟asc1206字库 15831040+25 ascii_font.asc1206_size=fftemp->fsize; //asc1206字库大小(文件大小) flashaddr=ascii_font.asc1206_addr; //asc1206字库的起始地址 break; case 1: ascii_font.asc1608_addr=ascii_font.asc1206_addr+ascii_font.asc1206_size; //asc1206之后,紧跟asc1608字库 ascii_font.asc1608_size=fftemp->fsize; //asc1608字库大小(文件大小) flashaddr=ascii_font.asc1608_addr; //asc1608字库的起始地址 break; case 2: ascii_font.asc2412_addr=ascii_font.asc1608_addr+ascii_font.asc1608_size; //asc1608之后,紧跟asc2412字库 ascii_font.asc2412_size=fftemp->fsize; //asc2412字库大小(文件大小) flashaddr=ascii_font.asc2412_addr; //asc2412的起始地址 break; } res=f_read(fftemp,tempbuf,4096,(UINT *)&bread); //读取4096个数据 if(res!=FR_OK)//执行错误 { myfree(SRAMIN,fftemp); //释放内存 myfree(SRAMIN,tempbuf);//释放内存 f_close(fftemp); return 1; } W25QXX_Write(tempbuf,flashaddr,bread);//从0开始写入bread个数据 f_close(fftemp); } else printf("ascii file error!\r\n"); myfree(SRAMIN,fftemp); //释放内存 myfree(SRAMIN,tempbuf);//释放内存 return res; } //更新字体文件,asc1206 asc1608 asc2412一起更新 //src:字库来源磁盘."0:",SD卡;"1:",FLASH盘,"2:",U盘. //提示信息字体大小 //返回值:0,更新成功; //其他,错误代码. u8 update_ascii_font(u8* src) { u8 *pname; u32 *buf; u8 res=0; u16 i,j; FIL *fftemp; u8 rval=0; res=0XFF; ascii_font.fontflag=0XFF; //先将字库标记为未更新 pname=mymalloc(SRAMIN,100); //申请100字节内存 buf=mymalloc(SRAMIN,4096); //申请4K字节内存 fftemp=(FIL*)mymalloc(SRAMIN,sizeof(FIL)); //分配内存 if(buf==NULL||pname==NULL||fftemp==NULL) { myfree(SRAMIN,fftemp); myfree(SRAMIN,pname); myfree(SRAMIN,buf); return 5; //内存申请失败 } //先查找文件是否正常 strcpy((char*)pname,(char*)src); //copy src内容到pname strcat((char*)pname,(char*)ASC1206_PATH); //文件路径添加到pname结尾处 res=f_open(fftemp,(const TCHAR*)pname,FA_READ); if(res)rval|=1<<4;//打开文件失败 strcpy((char*)pname,(char*)src); //copy src内容到pname strcat((char*)pname,(char*)ASC1608_PATH); res=f_open(fftemp,(const TCHAR*)pname,FA_READ); if(res)rval|=1<<5;//打开文件失败 strcpy((char*)pname,(char*)src); //copy src内容到pname strcat((char*)pname,(char*)ASC2412_PATH); res=f_open(fftemp,(const TCHAR*)pname,FA_READ); if(res)rval|=1<<6;//打开文件失败 myfree(SRAMIN,fftemp);//释放内存 if(rval==0)//字库文件都存在,更新字库 { //先擦除扇区,提高后面的写入速度 for(i=0;i { W25QXX_Read((u8*)buf,((ASCIIFONTINFOADDR/4096)+i)*4096,4096);//读出整个扇区的内容 for(j=0;j<1024;j++)//校验数据 { if(buf[j]!=0XFFFFFFFF)break;//需要擦除 } if(j!=1024)W25QXX_Erase_Sector((ASCIIFONTINFOADDR/4096)+i); //需要擦除的扇区 } myfree(SRAMIN,buf); printf("began to Update ascii font!\r\n"); //开始更新ascii字库 strcpy((char*)pname,(char*)src);//copy src内容到pname strcat((char*)pname,(char*)ASC1206_PATH); //ASC1206路径接到pname后 res=updata_ascii_fontx(pname,0); //更新ASC1206 if(res){myfree(SRAMIN,pname);return 1;} printf("1206 Update Success!\r\n"); strcpy((char*)pname,(char*)src); //copy src内容到pname strcat((char*)pname,(char*)ASC1608_PATH); res=updata_ascii_fontx(pname,1); //更新ASC1608 if(res){myfree(SRAMIN,pname);return 2;} printf("1608 Update Success!\r\n"); strcpy((char*)pname,(char*)src); //copy src内容到pname strcat((char*)pname,(char*)ASC2412_PATH); res=updata_ascii_fontx(pname,2); //更新ASC2412 if(res){myfree(SRAMIN,pname);return 3;} printf("2412 Update Success!\r\n"); //全部更新好了 ascii_font.fontflag=0XAA; //标记字库存在 W25QXX_Write((u8*)&ascii_font,ASCIIFONTINFOADDR,sizeof(ascii_font)); //保存字库信息 } myfree(SRAMIN,pname);//释放内存 myfree(SRAMIN,buf); return rval;//无错误. } //初始化ascii字库 //返回值:0,字库完好. // 其他,字库丢失 u8 ascii_font_init(void) { u8 t=0; W25QXX_Init(); while(t<10)//连续读取10次,都是错误,说明确实是有问题,得更新字库了 { t++; W25QXX_Read((u8*)&ascii_font,ASCIIFONTINFOADDR,sizeof(ascii_font));//读出ftinfo结构体数据 if(ascii_font.fontflag==0XAA)break; delay_ms(20); } if(ascii_font.fontflag!=0XAA)return 1; return 0; } //字库初始化 u8 font_init(void) { u8 res=0; if(ascii_font_init()) res|=1<<0; if(ascii_font_init()) res|=1<<1; return res; } //更新汉字库 void updateHZfont(void) { u8 key; printf("ASCII Font Updating...\r\n"); while(ascii_font_init()) //检查ascii字库 { key=update_ascii_font("0:");//更新ascii库 if(key)//更新失败 { printf("ASCII Font Update Failed!\r\n"); delay_ms(1500); } } printf("ASCII Font Update Success!\r\n"); } //更新ascii字库 void updateasciifont(void) { u8 key; printf("HZ Font Updating\r\n"); while(font_init()) //检查汉字库 { key=update_HZ_font("0:");//更新汉字库 if(key)//更新失败 { printf("HZ Font Update Failed!\r\n"); delay_ms(1500); } } printf("HZ Font Update Success!\r\n"); } ////////////////////////////////////////////////////////////////////////////////////////////// /* int main(void) { u8 key,t,res; NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);// 设置中断优先级分组2 delay_init(); //延时函数初始化 uart1_init(115200); //串口初始化为115200 LCD_Init(); //初始化液晶 LED_Init(); //LED初始化 KEY_Init(); //按键初始化 mem_init(SRAMIN); //初始化内存池 exfuns_init(); //为fatfs相关变量申请内存 f_mount(fs[0],"0:",1); //挂载SD卡 顺便初始化SD f_mount(fs[1],"1:",1); //挂载FLASH.顺便初始化flash LCD_Clear(WHITE); //清屏 POINT_COLOR=RED; //设置字体为红色 res=font_init(); //检查字库,顺便初始化W25Q128 if(res) { switch(res) { case 0x01: updateHZfont(); break; case 0x02: updateasciifont(); break; case 0x03: updateHZfont(); updateasciifont(); break; } } LCD_ShowStr(60,50,200,16,"字库 OK",16,0); while(1) { while(t--)//延时,同时扫描按键 { delay_ms(1); key=KEY_Scan(0); if(key==KEY0_PRES) goto UPD; if(key==KEY1_PRES) goto UPD2; } LED0=!LED0; } } */ ///////////////////////////////////////////////////////////////////////////////////////////////////// 创建ascii字库文件 /* u8*const asc1206name="0:/ASCII/ASC1206.dat"; //asc1206的生成位置 u8*const asc1608name="0:/ASCII/ASC1608.dat"; //asc1608的生成位置 u8*const asc2412name="0:/ASCII/ASC2412.dat"; //asc2412的生成位置 int main(void) { FIL* f_rec=0; //文件 DIR recdir; //目录 u8 res; delay_init(); //延时函数初始化 NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); uart1_init(115200); //串口初始化为115200 LED_Init(); //初始化与LED连接的硬件接口 KEY_Init(); //初始化按键 LCD_Init(); //初始化LCD mem_init(SRAMIN); //初始化内部内存池 exfuns_init(); //为fatfs相关变量申请内存 f_mount(fs[0],"0:",1); //挂载SD卡(diskio.c里指定了SD卷标为0) 初始化SD f_mount(fs[1],"1:",1); //挂载FLASH(diskio.c里指定了FLASH卷标为1)初始FLASH POINT_COLOR=RED; f_rec=(FIL *)mymalloc(SRAMIN,sizeof(FIL)); //开辟FIL字节的内存区域 while(f_opendir(&recdir,"0:/ASCII"))//打开/创建ascii字库文件夹 { f_mkdir("0:/ASCII");//创建该目录 LED1=!LED1; delay_ms(1000); } //创建一个新文件。(如果文件已存在,则创建失败 | 指定写访问对象,可以向文件写入数据 res=f_open(f_rec,(const TCHAR*)asc1206name, FA_CREATE_NEW | FA_WRITE); f_write(f_rec,asc2_1206,sizeof(asc2_1206),&bw); f_close(f_rec);//关闭文件 //创建一个新文件。(如果文件已存在,则创建失败 | 指定写访问对象,可以向文件写入数据) res=f_open(f_rec,(const TCHAR*)asc1608name, FA_CREATE_NEW | FA_WRITE); f_write(f_rec,asc2_1608,sizeof(asc2_1608),&bw); f_close(f_rec);//关闭文件 //创建一个新文件。(如果文件已存在,则创建失败 | 指定写访问对象,可以向文件写入数据) res=f_open(f_rec,(const TCHAR*)asc2412name, FA_CREATE_NEW | FA_WRITE); f_write(f_rec,asc2_2412,sizeof(asc2_2412),&bw); f_close(f_rec);//关闭文件 */