资深版主
- 积分
- 10541
- 金钱
- 10541
- 注册时间
- 2017-2-18
- 在线时间
- 1908 小时
|
本帖最后由 peng1554 于 2018-9-13 09:16 编辑
程序基于MINIV3 汉字显示实验例程修改。32号字库可使用点阵字库生成器来制作,具体方法请参考“STM32不完全手册_库函数版本_V3.1.pdf”的483页
图1
测试程序需要FAT32格式的SD卡(大卡。小卡对SPI兼容性不好)接读卡器且读卡器接电脑。在电脑端将本帖子"SD卡所需字库文件"解压并将其中的“SYSTEM”文件夹复制到SD卡的根目录,
该文件夹下有个"FONT"文件夹存放了所需的字库文件,这几个字库文件6.01M字节大小,当SD卡接板子的时候,在板子上电之后会自动更新这些文件到板子的W25Q64芯片中,更新过程需要几分钟时间
更新完成后液晶如图
整个程序主要修改这4个文件:text.c ,fontupd.c,fontupd.h,diskio.c
text.c中修改了Get_HzMa()和Show_Font(),在这2个函数里头增加了对32号字库中字符的查找功能
[mw_shl_code=c,true]//code 字符指针开始
//从字库中查找出字模
//code 字符串的开始地址,GBK码
//mat 数据存放地址 (size/8+((size%8)?1:0))*(size) bytes大小
//size:字体大小
void Get_HzMat(unsigned char *code,unsigned char *mat,u8 size)
{
unsigned char qh,ql;
unsigned char i;
unsigned long foffset;
u8 csize=(size/8+((size%8)?1:0))*(size);//得到字体一个字符对应点阵集所占的字节数
qh=*code;
ql=*(++code);
if(qh<0x81||ql<0x40||ql==0xff||qh==0xff)//非 常用汉字
{
for(i=0;i<csize;i++)*mat++=0x00;//填充满格
return; //结束访问
}
if(ql<0x7f)ql-=0x40;//注意!
else ql-=0x41;
qh-=0x81;
foffset=((unsigned long)190*qh+ql)*csize; //得到字库中的字节偏移量
switch(size)
{
case 12:
SPI_Flash_Read(mat,foffset+ftinfo.f12addr,24);
break;
case 16:
SPI_Flash_Read(mat,foffset+ftinfo.f16addr,32);
break;
case 24:
SPI_Flash_Read(mat,foffset+ftinfo.f24addr,72);
break;
case 32:
SPI_Flash_Read(mat,foffset+ftinfo.f32addr,128);
break;
}
}
//显示一个指定大小的汉字
//x,y :汉字的坐标
//font:汉字GBK码
//size:字体大小
//mode:0,正常显示,1,叠加显示
void Show_Font(u16 x,u16 y,u8 *font,u8 size,u8 mode)
{
u8 temp,t,t1;
u16 y0=y;
u8 dzk[128];
u8 csize=(size/8+((size%8)?1:0))*(size);//得到字体一个字符对应点阵集所占的字节数
if(size!=12&&size!=16&&size!=24&&size!=32)return; //不支持的size
Get_HzMat(font,dzk,size); //得到相应大小的点阵数据
for(t=0;t<csize;t++)
{
temp=dzk[t]; //得到点阵数据
for(t1=0;t1<8;t1++)
{
if(temp&0x80)LCD_Fast_DrawPoint(x,y,POINT_COLOR);
else if(mode==0)LCD_Fast_DrawPoint(x,y,BACK_COLOR);
temp<<=1;
y++;
if((y-y0)==size)
{
y=y0;
x++;
break;
}
}
}
}[/mw_shl_code]
fontupd.c中修改了SPI FLASH字库存储地址,添加了32号字库在SD卡中的路径
[mw_shl_code=c,true]//字库存放起始地址
#define FONTINFOADDR 1024*1024*1 //MiniSTM32是从1M地址开始的
//字库存放在sd卡中的路径
const u8 *GBK32_PATH="0:/SYSTEM/FONT/GBK32.FON"; //GBK32的存放位置[/mw_shl_code]
并修改了updata_fontx()和update_font()以支持对32号库的更新
[mw_shl_code=c,true]//更新某一个
//x,y:坐标
//size:字体大小
//fxpath:路径
//fx:更新的内容 0,ungbk;1,gbk12;2,gbk16;3,gbk24;4,gbk32
//返回值: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(sizeof(FIL)); //分配内存
if(fftemp==NULL)rval=1;
tempbuf=mymalloc(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.gbk24size=fftemp->fsize; //GBK24字库大小
flashaddr=ftinfo.f24addr; //GBK24的起始地址
break;
case 4:
ftinfo.f32addr=ftinfo.f24addr+ftinfo.gbk24size; //GBK24之后,紧跟GBK32字库
ftinfo.gbk32size=fftemp->fsize; //GBK32字库大小
flashaddr=ftinfo.f32addr; //GBK32的起始地址
}
while(res==FR_OK)//死循环执行
{
res=f_read(fftemp,tempbuf,4096,(UINT *)&bread); //读取数据
if(res!=FR_OK)break; //执行错误
SPI_Flash_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(fftemp); //释放内存
myfree(tempbuf); //释放内存
return res;
}
//更新字体文件,UNIGBK,GBK12,GBK16,GBK24,GBK32一起更新
//x,y:提示信息的显示地址
//size:字体大小
//提示信息字体大小
//返回值:0,更新成功;
//其他,错误代码.
u8 update_font(u16 x,u16 y,u8 size)
{
u8 *gbk32_path=(u8*)GBK32_PATH;
u8 *gbk24_path=(u8*)GBK24_PATH;
u8 *gbk16_path=(u8*)GBK16_PATH;
u8 *gbk12_path=(u8*)GBK12_PATH;
u8 *unigbk_path=(u8*)UNIGBK_PATH;
u8 res;
res=0XFF;
ftinfo.fontok=0XFF;
SPI_Flash_Write((u8*)&ftinfo,FONTINFOADDR,sizeof(ftinfo)); //清除之前字库成功的标志.防止更新到一半重启,导致的字库部分数据丢失.
SPI_Flash_Read((u8*)&ftinfo,FONTINFOADDR,sizeof(ftinfo)); //重新读出ftinfo结构体数据
LCD_ShowString(x,y,240,320,size,"Updating UNIGBK.BIN");
res=updata_fontx(x+20*size/2,y,size,unigbk_path,0); //更新UNIGBK.BIN
if(res)return 1;
LCD_ShowString(x,y,240,320,size,"Updating GBK12.BIN ");
res=updata_fontx(x+20*size/2,y,size,gbk12_path,1); //更新GBK12.FON
if(res)return 2;
LCD_ShowString(x,y,240,320,size,"Updating GBK16.BIN ");
res=updata_fontx(x+20*size/2,y,size,gbk16_path,2); //更新GBK16.FON
if(res)return 3;
LCD_ShowString(x,y,240,320,size,"Updating GBK24.BIN ");
res=updata_fontx(x+20*size/2,y,size,gbk24_path,3); //更新GBK24.FON
if(res)return 4;
LCD_ShowString(x,y,240,320,size,"Updating GBK32.BIN ");
res=updata_fontx(x+20*size/2,y,size,gbk32_path,4); //更新GBK32.FON
if(res)return 5;
//全部更新好了
ftinfo.fontok=0XAA;
SPI_Flash_Write((u8*)&ftinfo,FONTINFOADDR,sizeof(ftinfo)); //保存字库信息
return 0;//无错误.
} [/mw_shl_code]
fontupd.h对字库信息结构体添加了32字库成员变量
[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 gbk24size; //gbk24的大小
u32 f32addr; //gbk32地址
u32 gbk32size; //gbk32的大小
}_font_info;[/mw_shl_code]
diskio.c中修改了FLASH_SECTOR_COUNT的大小来支持FATFS对W25Q64的前1M字节进行管理
[mw_shl_code=c,true]//对于W25Q64
//前1M字节给fatfs用,字库占用6.01M.
u16 FLASH_SECTOR_COUNT= 2048; //1M字节,默认为W25Q64
//初始化磁盘
DSTATUS disk_initialize (
BYTE pdrv /* Physical drive nmuber (0..) */
)
{
u8 res=0;
switch(pdrv)
{
case SD_CARD://SD卡
res = SD_Initialize();//SD_Initialize()
if(res)//STM32 SPI的bug,在sd卡操作失败的时候如果不执行下面的语句,可能导致SPI读写异常
{
SD_SPI_SpeedLow();
SD_SPI_ReadWriteByte(0xff);//提供额外的8个时钟
SD_SPI_SpeedHigh();
}
break;
case EX_FLASH://外部flash
SPI_Flash_Init();
if(SPI_FLASH_TYPE==W25Q64)FLASH_SECTOR_COUNT=2048; //W25Q64
else FLASH_SECTOR_COUNT=0; //其他
break;
default:
res=1;
}
if(res)return STA_NOINIT;
else return 0; //初始化成功
}[/mw_shl_code]
main.c的代码就不表了,功能与汉字显示实验例程类似
|
|