stm32使用查表法将utf8转gbk,编码表数组存放在外部flash中

学习笔记 :2019-07-13   XZJ

在使用stm32获取服务器下发的json数据时,解析出来的数据编码是utf8格式的,在串口或者LCD上显示都是乱码,为了解决这个问题,百度了一下,发现在stm32上转码的几乎没有,最后有一个用stm32+esp8266获取知心天气的例程中发现了这个转码,这是原文地址http://www.openedv.com/forum.php?mod=viewthread&tid=229818&highlight=%CD%F8%C2%E7%CC%EC%C6%F8感谢开源精神。可惜的是我使用的单片机没那么大的容量,里面转码的编码表是一个特别大的数组,单片机的flash根本存不下,还好我的板子上有外部flash,25Q64,参考了下原子的例程,移植了文件系统,吧数组保存到25q64中。

第一步、将数组转换为bin文件,使用原子提供的c2B软件。

第二步、将bin文件放到SD卡上,

第三步、使用文件系将SD卡上的bin文件存入外部flash。

下面是存储和转码的源代码,其他的文件系统等源码就不贴出来了,基本使用的都是正点原子的例程。

将结构体utf8info中的编码表信息也存入外部flash中,上电的时候可以检测信息头来判断编码表有没有被更改,一旦被更改就可以及时发现并且更新。

                                                                                                                                                                 

                                                                                                                                                                     

#include "sys.h"
#include 
#include "string.h"
#include "fontupd.h"
#include "LCD.h"	  
#include "flash.h"   
#include "ff.h"	 
#include "malloc.h"
#include "utf8togbk.h"
#define FONTUTFTUBGK   (4916)*1024//bin编码表文件存放起始地址
const u8 *UTF8TOGBK="0:/SYSTEM/FONT/utf8togbk.BIN";//bin文件在SD卡的储存路径
//编码表信息结构体. 
//用来保存信息基本信息,地址,大小等
utf8info utf8_info;
//==================================================================
//函数名:fupd_prog1 
//作者:  徐参考正点原子例程 
//日期:   2019-7-12
//功能:   显示当前文件更新进度
//输入参数:x,y:坐标,size:字体大小,fsize:整个文件大小,pos:当前文件指针位置
//返回值: 0
//修改记录:2019-7-13
//==================================================================
u32 fupd_prog1(u16 x,u16 y,u8 size,u32 fsize,u32 pos)
{
	float prog;
	u8 t=0XFF;
	prog=(float)pos/fsize;
	prog*=100;
	if(t!=prog)
	{
		LCD_ShowString(x+3*size/2,y,240,320,size,"%");		
		t=prog;
		if(t>100)t=100;
		LCD_ShowNum(x,y,t,3,size);//显示数值
	}
	return 0;					    
} 

//==================================================================
//函数名: updata_fontx1
//作者:   徐
//日期:   2019-7-12
//功能:   更新某一个bin文件
//输入参数:x,y:LCD显示坐标,size:LCD显示字体大小,fxpath:路径
//返回值: 0,成功;其他,失败.
//修改记录:2019-7-13
//==================================================================
u8 updata_fontx1(u16 x,u16 y,u8 size,u8 *fxpath)
{
	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)	 
	{
		utf8_info.utf8togbkddr=FONTUTFTUBGK+sizeof(utf8_info);	//信息头之后,紧utf8togbk转换码表
		utf8_info.utf8togbksize=fftemp->fsize;					//UNIGBK大小
		flashaddr=utf8_info.utf8togbkddr;
		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_prog1(x,y,size,fftemp->fsize,offx);	 			//进度显示
			if(bread!=4096)break;								//读完了.
	 	} 	
		f_close(fftemp);		
	}			 
	myfree(fftemp);	//释放内存
	myfree(tempbuf);	//释放内存
	return res;
}
//==================================================================
//函数名: update_font1
//作者:   徐
//日期:   2019-7-12
//功能:   更新bin数组文件和结构体信息头
//输入参数:x,y:提示信息的显示地址,size:字体大小
//返回值: 0,更新成功; 其他,错误.	
//修改记录:2019-7-13
//==================================================================
u8 update_font1(u16 x,u16 y,u8 size)
{	
	u8 *utf8togbk_path=(u8*)UTF8TOGBK;
	u8 res;		   
	res=updata_fontx1(x+20*size/2,y,size,utf8togbk_path);			//更新UNIGBK.BIN
	if(res)return 1;
	//全部更新好了 
	utf8_info.utf8_gbk=0XBB;//信息头用来检测编码表是否被修改
  	SPI_Flash_Write((u8*)&utf8_info,FONTUTFTUBGK,sizeof(utf8_info));	//保存字库信息
	return 0;//无错误.		 
}
//==================================================================
//函数名: utf8_gbk_init
//作者:   徐
//日期:   2019-7-12
//功能:   初始化编码表,检测表是否被修改
//输入参数:无
//返回值: 0完好,其他,损坏
//修改记录:2019-7-13
//==================================================================
u8 utf8_gbk_init(void)
{			  												 
	SPI_Flash_Init(); 
 	SPI_Flash_Read((u8*)&utf8_info,FONTUTFTUBGK,sizeof(utf8_info));//读出ftinfo结构体数据
//	printf("转码表:%x\r\n",utf8_info.utf8_gbk);
	if(utf8_info.utf8_gbk!=0XBB)return 1;			//字库错误. 
	return 0;		    
}
//==================================================================
//函数名: SwitchToGbk
//作者:   徐
//日期:   2019-7-12
//功能:   utf8转gbk
//输入参数:pszBufI:需要转换的nutf8,nBufInLen:需要转换的nutf8的长度,
//          pszBufOut:转换后的gbk,pnBufOutLen:转换后的gbk地址
//返回值:
//修改记录:2019-7-12将大数组存放在外部flash中,
//					2019-7-13获取unicode的地址偏移量,查表
//==================================================================
int SwitchToGbk(const unsigned char* pszBufIn, int nBufInLen, unsigned char* pszBufOut, int* pnBufOutLen)
{
	int i = 0;
	int j = 0;
	unsigned short unicode;
	u8 gbk[50];
	for(; i < nBufInLen; i++, j++)
	{
		if((pszBufIn[i] & 0x80) == 0x00)		// 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); 
			SPI_Flash_Read(gbk,utf8_info.utf8togbkddr+(2*(unicode-0x4e00)),2);
			pszBufOut[j]= gbk[1];//gbk%256;
			pszBufOut[j+1] = gbk[0];//gbk/256;
			j++;
			i+=2;
		}
		else
		{
			return -1;
		}
	}
	*pnBufOutLen = j;
	return 0;
}





.h文件中就是函数的声明和结构体的定义,源码如下

#ifndef __utf8togbk_h
#define __utf8togbk_h
#include "sys.h"
__packed typedef struct 
{
	u8 utf8_gbk;				//字库存在标志,0XBB,字库正常;其他,字库不存在
	u32 utf8togbkddr; 			//utf8togbk的地址
	u32 utf8togbksize;			//utf8togbk的大小	
}utf8info; 

extern utf8info utf8_info;
u8 utf8_gbk_init(void);
u8 update_font1(u16 x,u16 y,u8 size);
u8 updata_fontx1(u16 x,u16 y,u8 size,u8 *fxpath);
int SwitchToGbk( const unsigned char* pszBufIn, int nBufInLen, unsigned char* pszBufOut, int* pnBufOutLen);



#endif










 

你可能感兴趣的:(电子技术,嵌入式开发,程序)