UTF-8与GBK字符之间的转换

一、本文提纲

在嵌入式产品中,难免会遇到由服务器或者APP端推送的消息内容,而大多数推送消息内容的字符编码都为UTF-8,底层硬件需要将推送的消息送到LCD或者OLED等屏幕上进行显示,此时就涉及到一个编码转换的内容,因为硬件不能直接将UTF-8编码的字符进行显示,必须经过算法将UTF-8编码对照Unicode编码转换为GBK汉字编码之后才能显示,而本文介绍从外部FLASH中读取Unicode编码和GBK字符编码,将UTF-8字符转换为GBK字符。

二、UTF-8转换为GBK字符的原理

1.UTF-8转换为Unicode编码

UTF-8编码不能直接转换为GBK汉字编码,中间需要先转换为Unicode编码,在由Unicode编码转换为GBK汉字编码

2.Unicode编码转换为GBK汉字编码

Unicode汉字编码与GBK汉字编码的对照关系为,两个Unicode编码对应一个汉字,并且在Unicode编码中,汉字编码的起始位置是0x4e00,也就是说将UTF-8汉字编码转换为Unicode编码时需要偏移0x4e00去读取数据。

三、UTF-8转换为GBK字符的C代码实现过程

1.从flash读取Unicode编码

unsigned short  mb_uni2gb_table[]={0};
uint16_t Read_flash_unicode(uint16_t* unicode,uint32_t ReadAddr,uint16_t num_len)
{
	  uint8_t buff[10];//缓冲区 
	  ReadAddr=ReadAddr+Offset_addr;//为存储在flash 中的偏移地址
	  SPI_Flash_Read_2(buff,ReadAddr,num_len);
	  unicode[0]=(buff[1]<<8)|buff[0];
	  return 1;
}

2.UTF-8转换为Unicode编码

int SwitchToGbk(const unsigned char* pszBufIn, int nBufInLen, unsigned char* pszBufOut, int* pnBufOutLen)
{
	int i = 0;
	int j = 0;
	int nLen;
	unsigned short unicode;
	unsigned short gbk;
	for(; i < nBufInLen; i++, j++)
	{
		if((pszBufIn[i] & 0x80) == 0x00)		// 1位
		{
			nLen = 1;
			pszBufOut[j]= pszBufIn[i];
		}
		
		else if((pszBufIn[i] & 0xE0) == 0xC0)// 2位
		{
			nLen = 2;
			unicode = (pszBufIn[i] & 0x1F << 6) | (pszBufIn[i+1]& 0x3F);
		}
		else if ((pszBufIn[i] & 0xF0) == 0xE0) // 3位 
		{

			if (i+ 2 >= nBufInLen) return -1; 
			unicode = (((int)(pszBufIn[i] & 0x0F)) << 12) | (((int)(pszBufIn[i+1] &  0x3F)) << 6) | (pszBufIn[i+2]  & 0x3F); 
                        //从flash读取Unicode编码
			Read_flash_unicode(mb_uni2gb_table,(unicode-0x4e00)*2,2);
			gbk = *mb_uni2gb_table;
			pszBufOut[j]= gbk/256;
			pszBufOut[j+1] = gbk%256;
			j++;
			i+=2;
		}
		else
		{
			return -1;
		}
	}
	*pnBufOutLen = j;
	return 0;
}

3.Unicode编码转换为GBK汉字编码

void Get_HzMat(unsigned char *code,unsigned char *mat)
{		    
	unsigned char qh,ql;
	unsigned char i;					  
	unsigned long foffset; 
	uint8_t size = 16;
	uint8_t 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

四、ST7735s显示屏应用案例

1.lcd显示单个汉字的应用案例

/***************************************************************************************
** 函数名称 **:void Show_Font(uint16_t x,uint16_t y,uint8_t *font,uint16_t fc)
** 函数功能 **:lcd显示单个汉字
** 输入参数 **:uint16_t x,uint16_t y,uint8_t *font(汉字内容),uint16_t fc(汉字颜色)
** 输出参数 **:无
** 返 回 值 **:无
****************************************************************************************/
void Show_Font(uint16_t x,uint16_t y,uint8_t *font,uint16_t fc)
{
	uint8_t size = 16;//固定显示16号字体
	uint8_t temp,t,t1;
	uint16_t y0=y;
	uint8_t dzk[72];   
	uint8_t csize=(size/8+((size%8)?1:0))*(size);//得到字体一个字符对应点阵集所占的字节数	 
	if(size!=12&&size!=16&&size!=24)return;	//不支持的size
	Get_HzMat(font,dzk);	//得到相应大小的点阵数据 	
	for(t=0;t

2.在指定区域内自动换行显示多个汉字

void Show_Str(uint16_t x,uint16_t y,uint16_t width,uint16_t height,uint8_t*str,uint16_t fc)
{		
  uint8_t size = 16;	
  uint16_t x0=x;
  uint16_t y0=y;							  	  
  uint8_t bHz=0;     //字符或者中文  
  GPIO_Pin_Clear(U32BIT(LCD_CS));
  while(*str!=0)//数据未结束
  { 
            if(!bHz)
            {
	            if(*str>0x80)bHz=1;//中文 
	            else              //字符
	            {      
		            if(x>(x0+width-size/2))//换行
		            {				   
                            y+=size;
                            x=x0;	   
		            }							    
		            if(y>(y0+height-size))break;//越界返回      
		            if(*str==13)//换行符号
		            {         
                            y+=size;
                            x=x0;
                            str++; 
		            }  
		            else 
                            LCD_ShowChar(x,y,*str,fc);//有效部分写入 	
					
                            str++; 
                            x+=size/2; //字符,为全字的一半            
                }
            }
        else//中文 
        {     
            bHz=0;//有汉字库    
            if(x>(x0+width-size))//换行
            {	    
                y+=size;
                x=x0;		  
            }
            if(y>(y0+height-size))break;//越界返回  						     
                Show_Font(x,y,str,fc); //显示这个汉字,空心显示 
                str+=2; 
                x+=size;//下一个汉字偏移	    
        }						 
   }  
	 GPIO_Pin_Set(U32BIT(LCD_CS));
}   

你可能感兴趣的:(应用,嵌入式,c语言)