TFT-LCD显示中英文

news2024/11/28 16:41:17

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_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);
}

显示效果

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/3612.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【数据结构】搜索二叉树(C++实现)

目录 一、二叉搜索树的概念 二、二叉搜索树的实现 2.1 节点的定义及构造 2.2 树的结构及功能展示 2.3 树的 Insert 2.4 树的中序遍历 2.4 树的 Find 2.5 树的 Erase 2.6 拷贝构造、赋值运算符重载、析构函数 三、递归实现树的增删查 3.1 递归实现 FindR 3.2 递归实…

Vue | Vue.js Composition API(二)

&#x1f5a5;️ Vue.js专栏&#xff1a;Vue.js 初级知识 Composition API(二) &#x1f9d1;‍&#x1f4bc; 个人简介&#xff1a;一个不甘平庸的平凡人&#x1f36c; ✨ 个人主页&#xff1a;CoderHing的个人主页 &#x1f340; 格言: ☀️ 路漫漫其修远兮,吾将上下而求索☀…

嘿,朋友,其实 CSS 动画超简单的 - 时间函数篇(贝塞尔曲线、steps,看完还不懂算我输)

分配内存 - new 官方定义&#xff1a;new是一个分配内存的内置函数&#xff0c;第一个参数是类型&#xff0c;而不是值&#xff0c;返回的值是指向该类型新分配的零值的指针。 func new(Type) *Type 我们平常在使用指针的时候是需要分配内存空间的&#xff0c;未分配内存空间…

Java自定义注解

目录 一、什么是自定义注解 1&#xff09;Java注解简介 2&#xff09;Java注解分类 JDK基本注解 JDK元注解 自定义注解 如何自定义注解&#xff1f; 二、自定义注解 1&#xff09;获取类上注解值 2&#xff09;获取类属性上的注解属性值 3&#xff09;获取方法上的注…

WireShark 常用协议分析

WireShark 常用协议分析 1.3 实战&#xff1a;使用 WireShark 对常用协议抓包并分析原理 协议分析的时候 我们 关闭混淆模式&#xff0c; 避免一些干扰的数据包存在。 1.3.1 常用协议分析 - ARP 协议 地址解析协议 &#xff08;英语&#xff1a;Address Resolution Protocol&…

从内核角度看网络包发送流程

一、前置知识 1、RingBuffer结构详解 关于RingBuffer网上有很多说法&#xff0c;有的人说RingBuffer是系统启动时就预先申请好的一个环形数组&#xff0c;有的人说RingBuffer是在接收或发送数据时才动态申请的一个环形数组&#xff0c;那么到底RingBuffer的结构是怎么样的呢&…

《吉师作业》(2)之迟来的答案

前言 &#x1f340;作者简介&#xff1a;吉师散养学生&#xff0c;为挣钱努力拼搏的一名小学生。 &#x1f341;个人主页&#xff1a;吉师职业混子的博客_CSDN博客-python学习,HTML学习,清览题库--C语言程序设计第五版编程题解析领域博主 &#x1fad2;文章目的&#xff1a;我不…

初识C++(二)

简述 &#xff1a;本篇就缺省参数 和 函数重载 方面进行初步学习 &#xff0c;对比C语言学习C这两个语法&#xff0c;从而感受C在此方面对C语言进行的补充。 目录 缺省参数 什么是缺省参数 缺省参数的分类 缺省参数的应用 函数重载 什么是函数重载 函数重载的三种情况 支…

【JavaSE】函数or方法?方法的重载讲解

文章目录什么是方法如何定义方法方法的调用过程形参与实参的关系方法的重载为什么要重载重载的概念方法签名递归什么是方法 在C语言的学习中我们学习到了一个概念叫做函数&#xff0c;那么在Java的语法中有没有类似函数的东西的&#xff0c;答案是有的&#xff0c;但是在Java的…

strimzi实战之一:简介和准备

欢迎访问我的GitHub 这里分类和汇总了欣宸的全部原创(含配套源码)&#xff1a;https://github.com/zq2599/blog_demos 关于strimzi strimzi是一个开源项目&#xff0c;已加入了CNCF&#xff0c;官网地址&#xff1a;https://strimzi.io/借助strimzi&#xff0c;既能快速部署ka…

【生日快乐】搜索技术【深度优先搜索】 - 回溯法

搜索技术【深度优先搜索】 - 回溯法 回溯法是一种选优搜索法&#xff0c;按照选优条件深度优先搜索&#xff0c;以达到目标。当搜索到某一步时&#xff0c;发现原先的选择并不是最优或达不到目标&#xff0c;就退回一步重新选择&#xff0c;这种走不通就退回再走的技术被称为回…

如何用 Elasticsearch 实现 Word、PDF,TXT 文件的全文内容检索?

简单介绍一下需求 能支持文件的上传&#xff0c;下载 要能根据关键字&#xff0c;搜索出文件&#xff0c;要求要能搜索到文件里的文字&#xff0c;文件类型要支持 word&#xff0c;pdf&#xff0c;txt 文件上传&#xff0c;下载比较简单&#xff0c;要能检索到文件里的文字&am…

2022-ISCTF-部分MISC和PWN

misc 两层编码 第一层 sha256掩码爆破 第二层 base64解码找到key import string,sys from hashlib import sha256 from multiprocessing import Process from Crypto.Util.number import * from pwn import * import base64 from primefac import * context(log_leveldebug)…

【STL】容器 - set和map的使用

目录 前言 一.键值对 1.在SGI - STL中对键值对的定义: 2.make_pair 二.set 1.set的概念与注意事项 2.set的使用(常用接口) <1>.构造函数 <2>.迭代器与范围for <3>.插入和查找 <4>.删除erase <5>.计数count 三.map 1.map的概念与注…

洛谷千题详解 | P1012 [NOIP1998 提高组] 拼数【C++、Java语言】

博主主页&#xff1a;Yu仙笙 专栏地址&#xff1a;洛谷千题详解 目录 题目描述 输入格式 输出格式 输入输出样例 解析&#xff1a; C源码&#xff1a; C源码2&#xff1a; C源码3&#xff1a; Java源码&#xff1a; ---------------------------------------------------------…

element-ui upload图片上传组件使用

图片上传前端收集 数据 再调用接口发送到后端 组件标签内的参数&#xff1a; 参数说明类型可选值默认值action必选参数&#xff0c;上传的地址string——headers设置上传的请求头部object——multiple是否支持多选文件boolean——data上传时附带的额外参数object——name上传…

【数据结构】链表OJ第一篇 —— 移除链表元素 反转链表 合并两个有序链表

文章目录0. 前言1. 移除链表元素2. 反转链表3. 合并两个有序链表4. 结语0. 前言 上篇博客中&#xff0c;我们学习了实现了单链表。但是仅仅实现并不算掌握&#xff0c;所以我们需要做些题目来练习巩固。而从今天开始的几期&#xff0c;anduin 都会为大家带来链表OJ题&#xff…

在Linux环境下VScode中配置ROS、PCL和OpenCV开发环境记录

一.安装必要的插件 打开VScode&#xff0c;在开展中安装CMake、CMake Tools&#xff0c;ROS和catkin-tools插件&#xff0c;截图如下&#xff0c;安装后重新打开VScode插件生效。 二.创建ROS工作空间 在选择的路径下&#xff0c;打开终端创建工作空间&#xff0c;具体命令如下…

【概率论笔记】正态分布专题

文章目录一维正态分布多维正态分布n维正态分布二维正态分布一维正态分布 设X~N(μ,σ2)X\text{\large\textasciitilde}N(\mu,\sigma^2)X~N(μ,σ2)&#xff0c;则XXX的概率密度为f(x)12πσe−(x−μ)22σ2f(x)\frac{1}{\sqrt{2\pi}\sigma}e^{-\frac{(x-\mu)^2}{2\sigma^2}}f(…

WXML模板语法

文章目录1、数据绑定1.1 数据绑定的基本原则1.2在data中定义页面的数据1.3 Mustache语法的格式1.4 Mustache语法的应用场景1.5 算数运算2、事件绑定2.1 小程序常用的事件2.2事件对象的属性列表2.3 target和currentTarget的区别2.4 <font colorred>bindtap的语法格式2.5 在…