【玩转嵌入式屏幕显示】(四)TFT-LCD屏幕显示英文字符(ASCII)和字符串

1. 简单的显示测试程序 — 帮助理解

使用PCtoLCD对字符取模

无论什么屏幕,都是由一个个像素点组成的,所以显示英文字符’A’的原理如图:

显示一个字符需要确定字符的高度和宽度:

  • 宽度的像素点是高度的一半;
  • 高度是16/24/32个像素点,称为字号(上图中是16个像素点)

取模软件使用PCtoLCD2002完美版,附上下载链接

取模软件中的设置如下:

  • 生成数据:C51格式:
  • 点阵格式:阴码(阴码是1显示,0不显示);
  • 取模方式:逐行式
  • 取模走向:顺向
  • 其余设置:默认


这里我使用的屏幕分辨率240240,所以我们选择显示一个240120的字符’A’,在取模软件中设置大小:

生成的数据较多,点击保存到文件:

修改文件名为font_A.h,然后修改文件格式如下,便于后续使用:

const char CH_A[] = 
{
    //生成的字符数据
};

编写程序显示字符

这个数组具有225行,每行16个字节的数据,每个字节对应该处的8个像素点是否显示,然后程序根据此数组判断是否要向像素点写入颜色。

简单的测试程序如下:

void LCD_ShowChar(uint16_t x, uint16_t y, char ch, uint16_t back_color, uint16_t font_color, 	uint8_t font_size)
{
	int i = 0, j = 0;
	uint8_t temp = 0;
	
	LCD_Address_Set(x, y, x + font_size/2 - 1, y + font_size - 1);//(x,y,x+8-1,y+16-1)
	
	for(i = 0;i < 225*16; i++)
	{
		temp = CH_A[i];
		for(j = 0; j < 8;j++)
		{
			//判断temp的最高位是否为1
			if(temp & 0x80)
			{
				//最高位为1,显示该点,设置颜色为字体颜色
				LCD_Write_2Byte(font_color);
			}
			else
			{
				//最高位为0,不显示该点,设置该点为背景色
				LCD_Write_2Byte(back_color);
			}
			temp <<= 1;
		}
	}
}

在mian.c中调用,如下:

int main(void)
{
	HAL_Init();
	SystemClock_Config();
	LCD_Init();
	
	LCD_ShowChar(60 ,0,'A',BLACK,YELLOW,240);
	
	while (1);
}

显示结果

2. 使用英文字库文件"font.h"

font.h内容

当程序中只需要显示几个字符时,可以使用取模的方式,也非常节省内存,但是当我们程序中需要使用不确定的字符时或者大量字符时,逐个取模的方式显然不可行,需要使用一个已经将常用字符按常用大小曲目完成的字库文件,即font.h,文件详细内容见我的Github。

基于font.h的任意字符显示函数

首先将字符文件包含进来:

#include "font.h"

然后在之前编写的函数上进行改进:

/**
 * @brief		显示一个ASCII码字符
 * @param   x,y		显示起始坐标
 * @param   ch		需要显示的字符
 * @param   size	字体大小(支持16/24/32号字体)
 * @return  none
 * @note		需要font.h字库文件的支持
 */
void LCD_ShowChar(uint16_t x, uint16_t y, char ch, uint16_t back_color, uint16_t font_color, uint8_t font_size)
{
	int i = 0, j = 0;
	uint8_t temp = 0;
	uint8_t size = 0;
	uint8_t t = 0;
	
	/* 检测显示是否会越界 */
	 if((x > (LCD_Width - font_size / 2)) || (y > (LCD_Height - font_size)))	
		 return;
	
	/* 根据字符大小设置显存操作区域 */
	LCD_Address_Set(x, y, x + font_size/2 - 1, y + font_size - 1);
	 
	 /* 计算字符在字库中的偏移值*/
	 ch = ch - ' ';
	 
	 /* 显示16号/32号字体 */
	 if((font_size == 16) || (font_size == 32) )
	 {
		  /* 计算字体一个字符对应点阵集所占的字节数 */
 			size = (font_size / 8 + ((font_size % 8) ? 1 : 0)) * (font_size / 2);

			for(i = 0; i < size; i++)
			{
					if(font_size == 16)
							temp = asc2_1608[ch][i];	//调用1608字体
					else if(font_size == 32)
							temp = asc2_3216[ch][i];	//调用3216字体
					else 
							return;			//没有的字库

					for(j = 0; j < 8; j++)
					{
							if(temp & 0x80)
								LCD_Write_2Byte(font_color);
							else 
								LCD_Write_2Byte(back_color);

							temp <<= 1;
					}
			}
	 }
	  /* 显示12号字体 */
	 else if(font_size == 12)
	 {
		  /* 计算字体一个字符对应点阵集所占的字节数 */
 			size = (font_size / 8 + ((font_size % 8) ? 1 : 0)) * (font_size / 2);

			for(i = 0; i < size; i++)
			{
				  temp = asc2_1206[ch][i];

					for(j = 0; j < 6; j++)
					{
							if(temp & 0x80)
								LCD_Write_2Byte(font_color);
							else 
								LCD_Write_2Byte(back_color);

							temp <<= 1;
					}
			}
	 }
	 /* 显示24号字体 */
	 else if(font_size == 24)
	 {
		  /* 计算字体一个字符对应点阵集所占的字节数 */
 			size = (font_size * 16) / 8;

			for(i = 0; i < size; i++)
			{
				  temp = asc2_2412[ch][i];
					if(i % 2 == 0)
							t = 8;
					else
							t = 4;
					for(j = 0; j < t; j++)
					{
							if(temp & 0x80)
								LCD_Write_2Byte(font_color);
							else 
								LCD_Write_2Byte(back_color);

							temp <<= 1;
					}
			}
	 }	 
	 /* 其余字体 */
	 else
		 return;
}

测试4种字体的显示

int main(void)
{
	HAL_Init();
	SystemClock_Config();
	LCD_Init();
	
	LCD_ShowChar(0,0,'A',BLACK,BLUE,12);
	LCD_ShowChar(6,12,'B',BLACK,YELLOW,16);
	LCD_ShowChar(14,28,'C',BLACK,GREEN,24);
	LCD_ShowChar(26,52,'D',BLACK,PINK,32);
	
	while (1);
}

测试结果

3. 字符串显示函数

/**
 * @brief		显示一个ASCII码字符串
 * @param   x,y		显示起始坐标
 * @param   str		需要显示的字符串
 * @param   size	字体大小(支持16/24/32号字体)
 * @return  none
 * @note		1. 需要font.h字库文件的支持
 * 					2. 超过指定width不显示超过的字符
 */
void LCD_ShowCharStr(uint16_t x, uint16_t y, uint8_t max_width, char* str, uint16_t back_color, uint16_t font_color, uint8_t font_size)
{

	max_width += x;
	
	while((*str <= '~') && (*str >= ' '))	//判断是否非法字符
	{
			if(x >= max_width)
			{
					//x方向越界,结束
					break;
			}
			
			LCD_ShowChar(x,y,*str,back_color, font_color,font_size);
			x += font_size / 2;
			str++;
	}
}

测试代码:

int main(void)
{
	HAL_Init();
	SystemClock_Config();
	LCD_Init();
	
	LCD_ShowChar(0,0,'A',BLACK,BLUE,12);
	LCD_ShowChar(6,12,'B',BLACK,YELLOW,16);
	LCD_ShowChar(14,28,'C',BLACK,GREEN,24);
	LCD_ShowChar(26,52,'D',BLACK,PINK,32);

	LCD_ShowCharStr(0,240-32,240,"Mculover666",BLACK,BLUE,32);
	
	while (1);
}

测试结果:

发布了156 篇原创文章 · 获赞 489 · 访问量 18万+

猜你喜欢

转载自blog.csdn.net/Mculover666/article/details/95615030