嵌入式小字库索引


前提

最近开发需要增加中文显示模式,但由于使用的字不多,所以不打算使用字库,但提出的需求是使用中文字符来进行索引,而且后期要方便新的文字增加,使用的平台是STM32F303RCT6

使用的方法

方法一,switch选择:

通过获取中文字符对应的GBK码,使用switch在不同的GBK码之间进行对应的字库获取,

void OLED_VRAM_ShowSingleChinese(int16_t Logic_x,int16_t Logic_y,unsigned char *code)
{		    
	uint16_t GBK_Code=0;                     //定义GBK
    uint16_t Position;                       //定义字库偏移位置
	GBK_Code=(*code)<<8;                     //获取GBK高位编码                                                                  
    GBK_Code+=*(++code);                     //获取GBK低位编码
    switch(GBK_Code)
    {
        case Code1:对应的操作;break;
        case Code2:对应的操作;break;
        ......
        default:break;   
    }
}

优点:获取编码后查询方便,且不需占用额外的空间,查询速度快

缺点:后期文字添加不方便,且过多的文字会造成switch结构过长

方法二,中文序列表:

使用一个序列来存储使用的中文字符,将其GBK码转换位对应的整型数据,每个字符在序列中所对应的位置是其在字库中对应的偏移位置,每次获取文字的GBK码后通过遍历序列来获取字符的偏移位置,用于获取对应的字库;

unsigned char ChineseUsed[]={"一二三四五六七八九十中国"};//使用的文字及顺序
uint16_t ChineseUsedGBK[];                                                                   
uint16_t ChineseUsedNum=12;//使用的文字数 
uint16_t GBK_Get(unsigned char *code)
{
 	uint16_t GBK_Code=0;//定义GBK
	GBK_Code=(*code)<<8;//获取GBK高位编码                                                                   
    GBK_Code+=*(++code);//获取GBK低位编码   
    return GBK_Code;
}
void OLED_GBK_Init()
{
    unsigned char* Code=&ChineseUsed[0];
    uint16_t GBKCode=0;
    for(uint16_t i=0;i<ChineseUsedNum;i++)
    {
        ChineseUsedGBK[]=GBK_Get((Code+2*i));//记录对应的GBK值,由于一个中文对应两个字符所以增                            
                                             //量*2
    }
}
void OLED_VRAM_ShowSingleChinese(unsigned char* code)
{
 	uint16_t GBK_Code=0;//定义GBK
    uint16_t sequence=ChineseUsedNum;
	GBK_Code=(*code)<<8;//获取GBK高位编码                                                                   
    GBK_Code+=*(++code);//获取GBK低位编码 
    for(uint16_t i=0;i<ChineseUsedNum;i++)
    {
       if(GBK_Code==ChineseUsedGBK[i])
        {
            sequence=i;
        } 
    }
    if(sequence==ChineseUsedNum)
    {
        //非法文字处理
    }
    else
    {
        //显示sequence对应位置的字库
    }
}

优点:不耗费额外空间,便于后期文字添加

缺点:每次查询需要遍历,每次查找的时间不同

方法三,中文区位码:

建立码表,建立一个常用的文字矩阵,有区位码来查找相对的偏移位置

uint16_t GBK_CodeSaveAddr[40][94]={0};//中文表
unsigned char ChineseUsed[]={"一二三四五六七八九十中国"};//使用的文字及顺序
uint32_t ChineseUsedNum=12;//使用的文字数
uint8_t  HighPos=0;//中文表查询地址高位 = GBK码高八位 - 0xB0
uint8_t  LowPos=0;//中文表查询地址低位 = GBK码低八位 - 0xA1
uint16_t GBK_Get(unsigned char *code)
{
 	uint16_t GBK_Code=0;//定义GBK
	GBK_Code=(*code)<<8;//获取GBK高位编码                                                                   
    GBK_Code+=*(++code);//获取GBK低位编码   
    return GBK_Code;
}
void OLED_GBK_Init()
{
    unsigned char* Code=&ChineseUsed[0];
    uint16_t GBKCode=0;
    for(uint32_t i=0;i<ChineseUsedNum;i++)//遍历使用文字
    {
        GBKCode=GBK_Get(Code);//获取当前使用字的GBK码
        HighPos=((GBKCode&0xFF00)>>8)-0xA0-16;//获取区码
        LowPos=(GBKCode&0xFF)-0xA1;//获取位码
        GBK_CodeSaveAddr[HighPos][LowPos]=i;//记录当前文字的偏移量
        Code+=2;//切换下一个文字
    }
}
uint16_t MatPosGet(uint16_t GBKCode)
{
    HighPos=((GBKCode&0xFF00)>>8)-0xA0-16;
    LowPos=(GBKCode&0xFF)-0xA1;
    return  GBK_CodeSaveAddr[HighPos][LowPos];
}
void OLED_VRAM_ShowSingleChinese(int16_t Logic_x,int16_t Logic_y,unsigned char *code)
{		    
	uint16_t GBK_Code=0;//定义GBK
    uint16_t Position;//定义字库偏移位置
	GBK_Code=(*code)<<8;//获取GBK高位编码                                                                  
    GBK_Code+=*(++code);//获取GBK低位编码					    
    Position=MatPosGet(GBK_Code);//获取偏移位置                                         
    OLED_VRAM_SymbolWrite(Logic_x,Logic_y,Position*2,Symbol_TEXT_16x16);//显示对应文字
}

优点:查找速度快,便于后期文字添加

缺点:文字表占用空间大,字数超过256时存储空间翻倍

方法四:分块查找

方法三使用区位码查找在字数超过256之后,从8位变为16位就需要加倍的空间来存储顺序,在这种情况下,空间换时间得不偿失,但使用方法二也会耗费大量时间去遍历,故将方法二和方法三结合,完成方法四:当使用字数小于256时,仍然使用方法三;当使用字数大于256时,将文字序列分为256块,区位表仅存储其对应的块的顺序,然后在对应的块中进行遍历,由于使用是小字库,若使用的字数为2048个,遍历16个字符便能查找到对应顺序;

uint8_t GBK_CodeSaveAddr[40][94]={0};//区位码表,默认未定义为0;
unsigned char ChineseUsed[]={"一二三四五六七八九十中国"};//使用的文字                                                                            
uint16_t ChineseUsedNum=12;//使用的文字数                                                                                
uint16_t ChineseUsedGBKCodeSequence[12];//文字GBK码序列
uint8_t  HighPos=0;//中文表查询地址高位 = GBK码高八位 - 0xB0
uint8_t  LowPos=0;//中文表查询地址低位 = GBK码低八位 - 0xA1
uint16_t GBK_Get(unsigned char *code)
{
 	uint16_t GBK_Code=0;//定义GBK
	GBK_Code=(*code)<<8;//获取GBK高位编码                                                                   
    GBK_Code+=*(++code);//获取GBK低位编码   
    return GBK_Code;
}
/*
    字库初始化,初始化使用汉字,查询表
*/
void OLED_GBK_Init(void)
{
    unsigned char* Code=&ChineseUsed[0];//获取使用的中文字符存储地址
    uint16_t GBKCode=0;//定义GBK码存储器
    for(uint32_t i=0;i<ChineseUsedNum;i++)//遍历使用的中文字符
    {
        GBKCode=GBK_Get(Code);//获取当前字符GBK码
        HighPos=((GBKCode&0xFF00)>>8)-0xA0-16;//区码获取
        LowPos=(GBKCode&0xFF)-0xA1;//位码获取
        ChineseUsedGBKCodeSequence[i]=GBKCode;//GBK码压入序列
        if(ChineseUsedNum>256)//使用字数大于256时
        {
            GBK_CodeSaveAddr[HighPos][LowPos]=((float)i/ChineseUsedNum)*256;//存储段位
        }
        else//使用字数小于256时
        {
            GBK_CodeSaveAddr[HighPos][LowPos]=i;//存储顺序位
        }
        Code+=2;//切换下一个文字
    }
}
uint16_t MatPosGet(uint16_t GBKCode)
{
    uint16_t Sequence,Pos;
    HighPos=((GBKCode&0xFF00)>>8)-0xA0-16;//区码获取
    LowPos=(GBKCode&0xFF)-0xA1;//位码获取
    Pos=GBK_CodeSaveAddr[HighPos][LowPos];//获取存储序列
    if(ChineseUsedNum<256)//使用字数小于256时,
    {
        Sequence=Pos;//序列直接赋值
    }
    else//使用字数大于256时
    {
        Pos=(ChineseUsedNum/256)*Pos;//获取段位
        for(uint16_t i=Pos;i<Pos+ChineseUsedNum/256+1;i++)//遍历段内所有数据
        {
            if(ChineseUsedGBKCodeSequence[i]==GBKCode)//获取到对应的数据时
            {
                Sequence=i;//位置赋值
                break;//退出遍历
            }
            else
            {
                Sequence=0;//无此字符,一般为段位为0时,最后返回0
            }
        }
    }
    return  Sequence;//返回序列
}
void OLED_VRAM_ShowSingleChinese(int16_t Logic_x,int16_t Logic_y,unsigned char *code)
{		    
	uint16_t GBK_Code=0;//定义GBK
    uint16_t Position;//定义字库偏移位置
	GBK_Code=(*code)<<8;//获取GBK高位编码                                                                  
    GBK_Code+=*(++code);//获取GBK低位编码					    
    Position=MatPosGet(GBK_Code);//获取偏移位置                                         
    OLED_VRAM_SymbolWrite(Logic_x,Logic_y,Position*2,Symbol_TEXT_16x16);//显示对应文字
}

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值