OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 4292|回复: 5

[miniF103] MINIV3 32号字体显示测试程序(从SPI FLASH读取汉字字库)

[复制链接]

109

主题

5562

帖子

0

精华

资深版主

Rank: 8Rank: 8

积分
10541
金钱
10541
注册时间
2017-2-18
在线时间
1908 小时
发表于 2018-9-12 18:41:13 | 显示全部楼层 |阅读模式
本帖最后由 peng1554 于 2018-9-13 09:16 编辑

程序基于MINIV3 汉字显示实验例程修改。32号字库可使用点阵字库生成器来制作,具体方法请参考“STM32不完全手册_库函数版本_V3.1.pdf”的483页

图1

图1


测试程序需要FAT32格式的SD卡(大卡。小卡对SPI兼容性不好)接读卡器且读卡器接电脑。在电脑端将本帖子"SD卡所需字库文件"解压并将其中的“SYSTEM”文件夹复制到SD卡的根目录,
该文件夹下有个"FONT"文件夹存放了所需的字库文件,这几个字库文件6.01M字节大小,当SD卡接板子的时候,在板子上电之后会自动更新这些文件到板子的W25Q64芯片中,更新过程需要几分钟时间
更新完成后液晶如图 IMG_1002.JPG

整个程序主要修改这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的代码就不表了,功能与汉字显示实验例程类似




MINIV332号字体显示测试程序.rar

5.18 MB, 下载次数: 149

SD卡所需字库文件.rar

3.56 MB, 下载次数: 820

字库制作软件.rar

3.69 MB, 下载次数: 108

正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

17

主题

465

帖子

1

精华

金牌会员

Rank: 6Rank: 6

积分
2142
金钱
2142
注册时间
2013-1-11
在线时间
504 小时
发表于 2018-9-18 11:51:35 | 显示全部楼层
知识是你最好的财富
回复 支持 反对

使用道具 举报

160

主题

966

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
2095
金钱
2095
注册时间
2014-3-7
在线时间
490 小时
发表于 2018-9-18 13:42:54 | 显示全部楼层
谢谢分享
回复 支持 反对

使用道具 举报

0

主题

15

帖子

0

精华

高级会员

Rank: 4

积分
789
金钱
789
注册时间
2019-6-16
在线时间
130 小时
发表于 2019-7-16 22:16:54 | 显示全部楼层
多谢分享学习一下
回复 支持 反对

使用道具 举报

1

主题

10

帖子

0

精华

初级会员

Rank: 2

积分
59
金钱
59
注册时间
2019-6-6
在线时间
18 小时
发表于 2019-8-31 18:18:33 | 显示全部楼层
我按你的方法添加字库,屏幕显示乱码
回复 支持 反对

使用道具 举报

109

主题

5562

帖子

0

精华

资深版主

Rank: 8Rank: 8

积分
10541
金钱
10541
注册时间
2017-2-18
在线时间
1908 小时
 楼主| 发表于 2019-9-2 18:07:59 | 显示全部楼层
科安达AA 发表于 2019-8-31 18:18
我按你的方法添加字库,屏幕显示乱码

看下是不是软件取模的设置不对
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2024-11-24 22:55

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表