3.在W25Q128中,字库区域占用的总扇区大小:字库信息+unigbk表+3个字库=3238700字节,约占791个扇区。
4.字库在W25Q128中管理相关参数
占用总扇区数
[mw_shl_code=c,true]//字库区域占用的总扇区数大小(3个字库+unigbk表+字库信息=3238700字节,约占791个W25QXX扇区)
#define FONTSECSIZE 791[/mw_shl_code]
起始地址
[mw_shl_code=c,true]#define FONTINFOADDR 1024*1024*12 //Explorer STM32F4是从12M地址以后开始存放字库
//前面12M被fatfs占用了.
//12M以后紧跟3个字库+UNIGBK.BIN,总大小3.09M,被字库占用了,不能动!
//15.10M以后,用户可以自由使用.建议用最后的100K字节比较好.[/mw_shl_code]
字库信息结构体
[mw_shl_code=c,true]//字库信息结构体定义
//用来保存字库基本信息,地址,大小等
__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; [/mw_shl_code]
5.字库在SD卡中位置:将学习光盘中\5,SD卡根目录文件 文件夹下面的SYSTEM文件夹拷贝到SD卡根目录,即完成字库在SD卡的存入。
6.字库在磁盘路径
[mw_shl_code=c,true]//字库存放在磁盘中的路径
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的存放位置[/mw_shl_code]
7.更新字库过程
①主函数中按键等触发更新字库函数
[mw_shl_code=c,true]update_font(20,110,16,"0:");//更新字库[/mw_shl_code]
其中
[mw_shl_code=c,true]f_mount(fs[0],"0:",1); //挂载SD卡[/mw_shl_code]
②执行更新字库函数
[mw_shl_code=c,true]//更新字体文件,UNIGBK,GBK12,GBK16,GBK24一起更新
//x,y:提示信息的显示地址
//size:字体大小
//src:字库来源磁盘."0:",SD卡;"1:",FLASH盘,"2:",U盘.
//提示信息字体大小
//返回值:0,更新成功;
// 其他,错误代码.
u8 update_font(u16 x,u16 y,u8 size,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);
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)//字库文件都存在.
{
LCD_ShowString(x,y,240,320,size,"Erasing sectors... ");//提示正在擦除扇区
for(i=0;i<FONTSECSIZE;i++) //先擦除字库区域,提高写入速度
{
fupd_prog(x+20*size/2,y,size,FONTSECSIZE,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);
LCD_ShowString(x,y,240,320,size,"Updating UNIGBK.BIN");
strcpy((char*)pname,(char*)src); //copy src内容到pname
strcat((char*)pname,(char*)UNIGBK_PATH);
res=updata_fontx(x+20*size/2,y,size,pname,0); //更新UNIGBK.BIN
if(res){myfree(SRAMIN,pname);return 1;}
LCD_ShowString(x,y,240,320,size,"Updating GBK12.BIN ");
strcpy((char*)pname,(char*)src); //copy src内容到pname
strcat((char*)pname,(char*)GBK12_PATH);
res=updata_fontx(x+20*size/2,y,size,pname,1); //更新GBK12.FON
if(res){myfree(SRAMIN,pname);return 2;}
LCD_ShowString(x,y,240,320,size,"Updating GBK16.BIN ");
strcpy((char*)pname,(char*)src); //copy src内容到pname
strcat((char*)pname,(char*)GBK16_PATH);
res=updata_fontx(x+20*size/2,y,size,pname,2); //更新GBK16.FON
if(res){myfree(SRAMIN,pname);return 3;}
LCD_ShowString(x,y,240,320,size,"Updating GBK24.BIN ");
strcpy((char*)pname,(char*)src); //copy src内容到pname
strcat((char*)pname,(char*)GBK24_PATH);
res=updata_fontx(x+20*size/2,y,size,pname,3); //更新GBK24.FON
if(res){myfree(SRAMIN,pname);return 4;}
//全部更新好了
ftinfo.fontok=0XAA;
W25QXX_Write((u8*)&ftinfo,FONTINFOADDR,sizeof(ftinfo)); //保存字库信息
}
myfree(SRAMIN,pname);//释放内存*****
myfree(SRAMIN,buf);//*****
return rval;//无错误.
} [/mw_shl_code]
③更新字库依据更新内容分为四个阶段,每个阶段都调用同一个更新内容函数
[mw_shl_code=c,true]//更新某一个
//x,y:坐标
//size:字体大小
//fxpath:路径
//fx:更新的内容 0,ungbk;1,gbk12;2,gbk16;3,gbk24;
//返回值:0,成功;其他,失败.
u8 updata_fontx(u16 x,u16 y,u8 size,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: //更新UNIGBK.BIN
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;
fupd_prog(x,y,size,fftemp->fsize,offx); //进度显示
if(bread!=4096)break; //读完了.
}
f_close(fftemp);
}
myfree(SRAMIN,fftemp); //释放内存*****
myfree(SRAMIN,tempbuf); //释放内存*****
return res;
} [/mw_shl_code]
9.更新字库主要过程点
①确定更新内容SD卡路径
[mw_shl_code=c,true]strcpy((char*)pname,(char*)src); //copy src内容到pname
strcat((char*)pname,(char*)UNIGBK_PATH); [/mw_shl_code]
②确定更新内容在W25Q128中数据信息
[mw_shl_code=c,true]ftinfo.ugbkaddr=FONTINFOADDR+sizeof(ftinfo); //信息头之后,紧跟UNIGBK转换码表
ftinfo.ugbksize=fftemp->fsize; //UNIGBK大小
flashaddr=ftinfo.ugbkaddr;[/mw_shl_code]
③读取SD卡数据(每次4K字节)
[mw_shl_code=c,true]res=f_read(fftemp,tempbuf,4096,(UINT *)&bread); //读取数据[/mw_shl_code]
其中,fftemp中存储路径信息
④将读出数据写入W25Q128(每次4K字节)
[mw_shl_code=c,true]W25QXX_Write(tempbuf,offx+flashaddr,4096); //从0开始写入4096个数据 [/mw_shl_code]
10.内存分配总结
①在update_font函数中
[mw_shl_code=c,true]pname=mymalloc(SRAMIN,100); //申请100字节内存 存放路径信息
buf=mymalloc(SRAMIN,4096); //申请4K字节内存 用于辅助扇区擦除
fftemp=(FIL*)mymalloc(SRAMIN,sizeof(FIL)); //分配内存 存放相关文件的FIL结构体数据 [/mw_shl_code]
使用完以后分别释放内存
[mw_shl_code=c,true]myfree(SRAMIN,fftemp);
myfree(SRAMIN,pname);
myfree(SRAMIN,buf);[/mw_shl_code]
②在updata_fontx函数中
[mw_shl_code=c,true]fftemp=(FIL*)mymalloc(SRAMIN,sizeof(FIL)); //分配内存 同上
tempbuf=mymalloc(SRAMIN,4096); //分配4096个字节空间 拷贝数据缓冲区(4K)[/mw_shl_code]
使用完以后分别释放内存
[mw_shl_code=c,true] myfree(SRAMIN,fftemp); //释放内存
myfree(SRAMIN,tempbuf); //释放内存[/mw_shl_code]
总结:可见,在使用过程中,根据我们的需要内存量调用mymalloc(SRAMIN, XX);进行内存申请即可,调用完以后记得通过myfree(SRAMIN, XX);释放。
ps:本来主要想总结的内容在第10点,前面部分都是一些相关知识点引子,结果引子越写越多,计划今天更新汉字+图片内存方面总结,由于时间原因,只更新了汉字。