TFT-LCD显示中英文

TFT-LCD显示中英文

在前面编写了屏幕显示ASCII字符和字符串后,本次实现屏幕显示中文字符和中文字符串

中文字符取模

阴码,逐行式,逆向,十六进制数,C51格式,

在这里插入图片描述

输入要显示的中文字符,字体选择宋体,字宽x字高为16x16,也可以选择其他大一点的格式,字体大小不同,后续代码中要进行相应的修改

在这里插入图片描述

代码

font_CHN.h

用一个头文件存放字模数据,因为中文数据不同于ASCII码,ASCII码字符是有规律的,在代码中减去首个字符就能得到想要的ASCII码字符,但中文没有,所以要解决的就是当参数传入要显示的中文字符指针时,该怎么去字模数组中找到对应中文字符的字模数据

方法:定义一个结构体类型,里面有两个数组,第一个数组是中文字符的索引,后续代码中就通过这个索引查找中文字符的位置,第二个数组就是对应中文字符的字模数据,这个数组的大小要根据中文字符的字模数据的个数来定,比如16x16大小的字符的字模数据有32个(一个一个数),所以该数组大小就为32,如果是24x24的大小,则该数组大小要为72

用该结构体类型定义一个数组,存放字符索引和字模数据,用const修饰,放到芯片的内部Flash区

/**
 * 16号中文字符集
 * 宽x高:16x16
 * 字体:宋体
 * 逐行式(从第一行开始向右每取8个点作为一个字节,不足8个点就补0)
 * 逆向(取模顺序从低到高,即第一个点作为最低位)
 */
typedef struct
{
    uint8_t ucIndex[2];
    uint8_t ucCHN_Code[32];		//该数组要根据一个中文字符的字模数据有多少个,来定义大小
}FONT_CHN16_t;

const FONT_CHN16_t ucCHN_CHN16[] = {

{{"时"},{0x00,0x10,0x00,0x10,0x3E,0x10,0x22,0x10,0xA2,0x7F,0x22,0x10,0x22,0x10,0x3E,0x10,0x22,0x11,0x22,0x12,0x22,0x12,0x22,0x10,0x3E,0x10,0x22,0x10,0x00,0x14,0x00,0x08}},/*"时",0*/
{{"间"},{0x04,0x00,0xC8,0x3F,0x08,0x20,0x02,0x20,0xE2,0x23,0x22,0x22,0x22,0x22,0x22,0x22,0xE2,0x23,0x22,0x22,0x22,0x22,0x22,0x22,0xE2,0x23,0x02,0x20,0x02,0x28,0x02,0x10}},/*"间",1*/
{{"不"},{0x00,0x00,0xFE,0x3F,0x00,0x01,0x00,0x01,0x80,0x00,0x80,0x00,0xC0,0x02,0xA0,0x04,0x90,0x08,0x88,0x10,0x84,0x20,0x82,0x20,0x81,0x00,0x80,0x00,0x80,0x00,0x80,0x00}},/*"不",2*/
{{"在"},{0x40,0x00,0x40,0x00,0x20,0x00,0xFF,0x7F,0x10,0x00,0x10,0x02,0x08,0x02,0x0C,0x02,0xEA,0x3F,0x09,0x02,0x08,0x02,0x08,0x02,0x08,0x02,0x08,0x02,0xF8,0x7F,0x08,0x00}},/*"在",3*/
{{"于"},{0x00,0x00,0xFC,0x1F,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0xFF,0x7F,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0xA0,0x00,0x40,0x00}},/*"于",4*/
{{"你"},{0x10,0x01,0x10,0x01,0x10,0x01,0x88,0x7F,0x88,0x40,0x4C,0x20,0x2C,0x04,0x0A,0x04,0x89,0x14,0x88,0x24,0x48,0x24,0x48,0x44,0x28,0x44,0x08,0x04,0x08,0x05,0x08,0x02}},/*"你",5*/
{{"拥"},{0x04,0x00,0xE4,0x3F,0x24,0x22,0x24,0x22,0x3F,0x22,0xE4,0x3F,0x24,0x22,0x34,0x22,0x2C,0x22,0xE7,0x3F,0x24,0x22,0x24,0x22,0x24,0x22,0x14,0x22,0x15,0x2A,0x0A,0x10}},/*"拥",6*/
{{"有"},{0x40,0x00,0x40,0x00,0xFF,0x7F,0x20,0x00,0x20,0x00,0xF0,0x0F,0x10,0x08,0x18,0x08,0xF4,0x0F,0x12,0x08,0x11,0x08,0xF0,0x0F,0x10,0x08,0x10,0x08,0x10,0x0A,0x10,0x04}},/*"有",7*/
{{"多"},{0x40,0x00,0x40,0x00,0xE0,0x0F,0x10,0x04,0x1C,0x02,0x20,0x01,0xC0,0x02,0x30,0x01,0x8E,0x1F,0x40,0x10,0x30,0x08,0x4C,0x04,0x80,0x02,0x80,0x01,0x70,0x00,0x0E,0x00}},/*"多",8*/
{{"少"},{0x80,0x00,0x80,0x00,0x80,0x00,0x90,0x04,0x90,0x08,0x88,0x10,0x88,0x20,0x84,0x28,0x82,0x08,0x80,0x04,0x00,0x02,0x00,0x01,0x80,0x00,0x40,0x00,0x30,0x00,0x0E,0x00}},/*"少",9*/
{{"而"},{0x00,0x00,0xFE,0x3F,0x80,0x00,0x80,0x00,0x40,0x00,0xFC,0x1F,0x24,0x11,0x24,0x11,0x24,0x11,0x24,0x11,0x24,0x11,0x24,0x11,0x24,0x11,0x24,0x11,0x04,0x14,0x04,0x08}},/*"而",10*/
{{"怎"},{0x10,0x00,0x10,0x00,0xF0,0x3F,0x28,0x00,0x24,0x00,0xE2,0x0F,0x20,0x00,0x20,0x00,0xE0,0x1F,0x20,0x00,0x80,0x00,0x10,0x21,0x12,0x49,0x12,0x48,0xE1,0x0F,0x00,0x00}},/*"怎",11*/
{{"么"},{0x80,0x00,0x80,0x00,0x40,0x00,0x40,0x00,0x20,0x02,0x10,0x02,0x08,0x01,0x04,0x01,0x82,0x00,0x40,0x00,0x20,0x04,0x10,0x08,0x08,0x10,0xFC,0x3F,0x08,0x20,0x00,0x00}},/*"么",12*/
{{"使"},{0x08,0x02,0x08,0x02,0xF8,0x7F,0x04,0x02,0x04,0x02,0xE6,0x3F,0x26,0x22,0x25,0x22,0xE4,0x3F,0x04,0x02,0x44,0x02,0x84,0x02,0x04,0x01,0x84,0x02,0x44,0x0C,0x34,0x70}},/*"使",13*/
{{"用"},{0x00,0x00,0xFC,0x1F,0x84,0x10,0x84,0x10,0x84,0x10,0xFC,0x1F,0x84,0x10,0x84,0x10,0x84,0x10,0xFC,0x1F,0x84,0x10,0x84,0x10,0x84,0x10,0x82,0x10,0x82,0x14,0x01,0x08}}/*"用",14*/
};
TFT_LCD.h

在LCD的头文件中定义中文字符大小的枚举类型

//定义汉字字体枚举类型
typedef enum
{
    CHN_font_16 = 16,
    CHN_font_24 = 24
}CHN_font_t;

//断言宏定义
#define IS_CHN_FONT(font)   (((font) == CHN_font_16) || ((font) == CHN_font_24))
TFT_LCD.c

编写显示一个中文字符的函数,原理与显示一个ASCII码字符一样,都是找到对应的字符,然后遍历该字符的字模数据,为1则显示字体颜色,为0则显示背景颜色

/**
 * @name   LCD_SetWindows
 * @brief  设置LCD显示窗口
 * @param  usXstar:窗口起点x轴坐标
 * 			usYstar:窗口起点y轴坐标
 * 			usXwidth:窗口宽度
 * 			usYheight:窗口高度
 * @retval None  
 */
static void LCD_SetWindows(uint16_t ususXstar,uint16_t usYstar,uint16_t usXwidth,uint16_t usYheight)
{
	LCD_WRITE_CMD(LCD_CMD_SET_X_ORGIN);		//发送设置X轴坐标的命令0x2A
	//参数SC[15:0]	->	设置起始列地址,也就是设置X轴起始坐标
	LCD_WRITE_DATA(ususXstar>>8);				//先写高8位
	LCD_WRITE_DATA(ususXstar&0x00FF);			//再写低8位
	//参数EC[15:0]	->	设置窗口X轴结束的列地址,因为参数usXwidth是窗口长度,所以要转为列地址再发送
	LCD_WRITE_DATA((ususXstar+usXwidth-1)>>8);				//先写高8位
	LCD_WRITE_DATA((ususXstar+usXwidth-1)&0x00FF);			//再写低8位

	LCD_WRITE_CMD(LCD_CMD_SET_Y_ORGIN);		//发送设置Y轴坐标的命令0x2B
	//参数SP[15:0]	->	设置起始行地址,也就是设置Y轴起始坐标
	LCD_WRITE_DATA(usYstar>>8);				//先写高8位
	LCD_WRITE_DATA(usYstar&0x00FF);			//再写低8位
	//参数EP[15:0]	->	设置窗口Y轴结束的列地址,因为参数usYheight是窗口高度,所以要转为行地址再发送
	LCD_WRITE_DATA((usYstar+usYheight-1)>>8);				//先写高8位
	LCD_WRITE_DATA((usYstar+usYheight-1)&0x00FF);			//再写低8位

	LCD_WRITE_CMD(LCD_CMD_WRGRAM);			//开始往GRAM里写数据
}
/**
 * @name   LCD_ShowCHN
 * @brief  LCD屏幕显示一个中文字符
 * @param  usXstar:窗口起点x轴坐标
 * 			usYstar:窗口起点y轴坐标
 * 			pcStr:要显示的英文字符串
 * 			usColor_Background:选择英文字符的背景色
 * 			usColor_Foreground:选择英文字符的前景色
 * 			font:字体选择		参数:CHN_font_16 :16号字体;CHN_font_24 :24号字体 
 * @retval None  
 */
static void LCD_ShowCHN(uint16_t usXstar,
						uint16_t usYstar,
						const char* pcStr,
						uint16_t usColor_Background,
						uint16_t usColor_Foreground,
						CHN_font_t font)
{
	uint8_t ucTemp,ucPage,ucColumn;
	uint16_t usIndex;		//字库中汉字的索引
	uint16_t usCHN_Num;		//字库中汉字数量

	//检查参数是否合法
	assert_param(IS_CHN_FONT(font));

	//判断字体-16号字体
	if(font == CHN_font_16)
	{
		//统计汉字数量
		usCHN_Num = sizeof(ucCHN_CHN16)/sizeof(FONT_CHN16_t);		//字模数组大小除以结构体大小,得到汉字的个数
		//for循环判断汉字位置
		for(usIndex=0;usIndex<usCHN_Num;usIndex++)
		{
		//判断结构体数组的汉字索引数组是否与要显示的中文字符一致,中文字符占两个字节,先判断第一个字符,再判断第二个字符
			if((ucCHN_CHN16[usIndex].ucIndex[0] == *pcStr)&&(ucCHN_CHN16[usIndex].ucIndex[1] == *(pcStr+1)))
			{
				//设置窗口,大小为16x16
				LCD_SetWindows(usXstar,usYstar,16,16);
				//逐行写入数据,共16行,每行16个像素点
				for(ucPage=0;ucPage<32;ucPage++)
				{
					//从ASCII字符集数组获取像素数据	
					//像素点数据为1时,写入字符颜色,为0时,写入背景颜色
					ucTemp = ucCHN_CHN16[usIndex].ucCHN_Code[ucPage];
					for(ucColumn=0;ucColumn<8;ucColumn++)
					{
						if((ucTemp & BIT0) == BIT0)
						{
							LCD_WRITE_DATA(usColor_Foreground);
						}
						else
						{
							LCD_WRITE_DATA(usColor_Background);
						}
						ucTemp >>= 1;
					}
				}
				break;		//已经找到并显示了字符,退出循环
			}
		}
	}

	//判断字体-24号字体
	if(font == CHN_font_24)
	{
		//统计汉字数量
		usCHN_Num = sizeof(ucCHN_CHN24)/sizeof(FONT_CHN24_t);		//字模数组大小除以结构体大小,得到汉字的个数
		//for循环判断汉字位置
		for(usIndex=0;usIndex<usCHN_Num;usIndex++)
		{
		//判断结构体数组的汉字索引数组是否与要显示的中文字符一致,中文字符占两个字节,先判断第一个字符,再判断第二个字符
			if((ucCHN_CHN24[usIndex].ucIndex[0] == *pcStr)&&(ucCHN_CHN24[usIndex].ucIndex[1] == *(pcStr+1)))
			{
				//设置窗口,大小为24x24
				LCD_SetWindows(usXstar,usYstar,24,24);
				//逐行写入数据,共24行,每行72个像素点
				for(ucPage=0;ucPage<72;ucPage++)
				{
					//从ASCII字符集数组获取像素数据	
					//像素点数据为1时,写入字符颜色,为0时,写入背景颜色
					ucTemp = ucCHN_CHN24[usIndex].ucCHN_Code[ucPage];
					for(ucColumn=0;ucColumn<8;ucColumn++)
					{
						if((ucTemp & BIT0) == BIT0)
						{
							LCD_WRITE_DATA(usColor_Foreground);
						}
						else
						{
							LCD_WRITE_DATA(usColor_Background);
						}
						ucTemp >>= 1;
					}
				}
				break;		//已经找到并显示了字符,退出循环
			}
		}
	}
}

通过结构体类型的第一个索引数组找到对应的中文字符就是下面这一条语句

//判断结构体数组的汉字索引数组是否与要显示的中文字符一致,中文字符占两个字节,先判断第一个字符,再判断第二个字符
if((ucCHN_CHN24[usIndex].ucIndex[0] == *pcStr)&&(ucCHN_CHN24[usIndex].ucIndex[1] == *(pcStr+1)))

编写一个显示中英文字符串的函数

如何区分ASCII码字符和中文字符?

ASCII码取模范围一般是32 - 126,即空格到~,最后一个ASCII码字符为del,其十进制为127,所以编码在127之前的都属于ASCII码字符,汉字占两个字节,而汉字为了与ASCII码区分开,第一个字节的最高位是为1的,十进制肯定大于127,所以区分ASCII码和汉字就可以判断字符是否小于0x80,小于的就为ASCII码,大于或等于的就为汉字

/**
 * @name   LCD_ShowCHNandENGString
 * @brief  LCD屏幕显示中英文字符串
 * @param  usXstar:窗口起点x轴坐标
 * 			usYstar:窗口起点y轴坐标
 * 			pcStr:要显示的英文字符串
 * 			usColor_Background:选择英文字符的背景色
 * 			usColor_Foreground:选择英文字符的前景色
 * 			CHN_font:中文字体		参数:CHN_font_16 :16号字体;CHN_font_24 :24号字体 
 * 			ASCII_font:英文字体	参数:ASCII_font_16 :16号字体;ASCII_font_24 :24号字体 
 * @retval None  
 */
static void LCD_ShowCHNandENGString(uint16_t usXstar,
									uint16_t usYstar,
									const char* pcStr,
									uint16_t usColor_Background,
									uint16_t usColor_Foreground,
									CHN_font_t CHN_font,
									ASCII_font_t ASCII_font)
{
	while(*pcStr != '\0')
	{
		//中文字符
		if(*(pcStr) > 127)
		{
			//自动换行
			if((usXstar+CHN_font) > LCD_WIGHT)
			{
				usXstar = 0;
				usYstar += CHN_font;
			}
			//自动换页
			if((usYstar+CHN_font) > LCD_HIGHT)
			{
				usXstar = 0;
				usYstar = 0;
			}
			//显示中文字符
			TFT_LCD.LCD_ShowCHN(usXstar,usYstar,pcStr,usColor_Background,usColor_Foreground,CHN_font);
			//更新位置
			pcStr += 2;					//下一个中文字符
			usXstar += CHN_font;		//坐标位置加上一个字符间隔
		}
		//英文字符
		else
		{
			if((*pcStr == '\r') || (*pcStr == '\n'))
			{
				//前面的字符为中文
				if(*(pcStr-1) > 127)
				{
					//换行
					usXstar = 0;
					usYstar += CHN_font;
				}
				//前面的字符为英文
				else
				{
					//换行
					usXstar = 0;
					usYstar += ASCII_font;
				}
			}
			else
			{
				//自动换行
				if((usXstar+ASCII_font/2) > LCD_WIGHT)
				{
					usXstar = 0;
					usYstar += ASCII_font;
				}
				//自动换页
				if((usYstar+ASCII_font) > LCD_HIGHT)
				{
					usXstar = 0;
					usYstar = 0;
				}
				//显示英文字符
				TFT_LCD.LCD_ShowChar(usXstar,usYstar,*pcStr,usColor_Background,usColor_Foreground,ASCII_font);
				//更新位置
				usXstar += ASCII_font/2;		//坐标位置加上一个字符间隔
			}
			pcStr++;		//指向下一个字符
		}
	}
}

System.c

系统运行函数中调用显示中英文字符串显示中文,这次并没有显示英文,而且中文字体大小为24x24

/*
* @name   Run
* @brief  系统运行
* @param  None
* @retval None   
*/
static void Run()
{
  TFT_LCD.LCD_ShowCHNandENGString(25,70,"时间",Color_BLACK,Color_WHITE,CHN_font_24,ASCII_font_16);
  TFT_LCD.LCD_ShowCHNandENGString(25,120,"不在于你拥有多少",Color_BLACK,Color_WHITE,CHN_font_24,ASCII_font_16);
  TFT_LCD.LCD_ShowCHNandENGString(25,170,"而在于你怎么使用",Color_BLACK,Color_WHITE,CHN_font_24,ASCII_font_16);
}

显示效果

在这里插入图片描述

  • 7
    点赞
  • 33
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值