LCD显示GBK字库里面的汉字

1 篇文章 1 订阅
1 篇文章 0 订阅

LCD显示GBK字库里面的汉字


前言

本文介绍如何把字库文件写入单片机的flash后,在单片机程序中添加代码直接显示汉字;或者显示接收上位机发送过来的UTF_8编码规则的信息。


提示:以下是本篇文章正文内容,下面案例可供参考

一、编码规则

从网上引来一段从UNICODE到UTF8的转换规则:

UTF-8: 1~3字节可变
UNICODE: 2字节一个字符
GB2312: 2字节一个字符
例子: “你”字的UTF-8编码: E4 BD A0      11100100 10111101 10100000
“你 ”的 Unicode 编码 :    4F 60           01001111 01100000
按照UTF-8的编码规则,分解如下:xxxx0100 xx111101 xx100000
把除了x之外的数字拼接在一起,就变成“你”的Unicode编码了。
注意UTF-8的最前面3个1,表示整个UTF-8串是由3个字节构成的。
经过UTF-8编码之后,再也不会出现敏感字符了,因为最高位始终为1。
GBK与Unicode之间并没有很明确的对应关系,因此就实用性而言还是查表法为主,另外表格平时可保存在Flash中。

二、使用步骤

1.需烧录的字库

这里不讨论怎样把字库烧录到单片机外部Flash

需要烧录单片机外部Flash的文件有GBK.FON,Unicode.bin
![在这里插入图片描述](https://img-blog.csdnimg.cn/20201029142603152.png#pic_center

2.转码

把UTF_8编码转换成Unicode编码,之后根据转换成的Unicode编码查找Flash中Unicode编码与GBK编码对应表格获得GBK编码。得到显示字库中的字节偏移量即可实现单片机显示中文字符的功能。

/*
*pszBufIn:需要转换的UTF_8内码
*nBufInLen:转换长度
*pszBufOut:转换后的Unicode内码
*pnBufOutLen:转换后的Unicode内码长度
*/
int UTF_8ToUnicode(const unsigned char* pszBufIn, int nBufInLen, unsigned char* pszBufOut, int* pnBufOutLen)
{
	int i = 0;
	int j = 0;
	unsigned short unicode;
	unsigned short gbk;
	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); 

			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.函数体

//在指定位置开始显示一个字符串	    
//支持自动换行
//(x,y):起始坐标
//width,height:区域
//str  :字符串
//size :字体大小
//mode:0,非叠加方式;1,叠加方式    	   		   
void Show_Str_font(uint16_t x,uint16_t y,uint16_t width,uint16_t height,uint8_t*str,uint16_t fc)
{		
	uint16_t x0=x;
	uint16_t y0=y;							  	  
  uint8_t bHz=0;     //字符或者中文  
	
  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;//下一个汉字偏移	    
        }						 
   }
	 if(*str>0x80)  
	 lcd_full_black(0,0,240,8);	
	 
}  	
//显示一个指定大小的汉字
//x,y :汉字的坐标
//font:汉字GBK码
//size:字体大小
//mode:0,正常显示,1,叠加显示	   
void Show_Font(uint16_t x,uint16_t y,uint8_t *font,uint16_t fc)
{
//	uint8_t size = 24;
	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);	//得到相应大小的点阵数据 	
	//输出
  GPIO_Pin_Clear(U32BIT(LCD_CS));
	for(t=0;t<csize;t++)
	{   												   
		temp=dzk[t];			//得到点阵数据
		for(t1=0;t1<8;t1++)
		{		
			if(temp&0x80)
				Gui_DrawPoint(x,y,fc);
			temp<<=1;
			y++;
			if((y-y0)==size)
			{
				y=y0;
				x++;
				break;
			}
		}  	 
	} 
  GPIO_Pin_Set(U32BIT(LCD_CS));	
}

3.显示汉字

...........
#define Color_White 	0xFFFF //白 
#define Color_Red 		0xF800 //红
............
int main()
{
Show_St_font(0,0,240,240,“你好”,Color_White);
Show_St_font(0,40,240,240,“你好”,Color_red);

while(1)
}

!在这里插入图片描述


  • 0
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

.伊恩.

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值