• 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*/
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    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))
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    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里写数据
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    /**
     * @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;		//已经找到并显示了字符,退出循环
    			}
    		}
    	}
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100

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

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

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

    如何区分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++;		//指向下一个字符
    		}
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86

    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);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    显示效果

    在这里插入图片描述

  • 相关阅读:
    mysql与oracle的区别
    LRU缓存替换策略及C#实现
    三菱FX5U-高速脉冲输入的频率测量
    李开复:我家的AI是坠吼的
    浙江大学主办!2024年第7届信息通信与信号处理国际会议( ICICSP2024)征稿开启!
    如何使用Python和Matplotlib创建双Y轴动态风格折线图 | 数据可视化教程
    高项.项目管理经验、理念、教训
    详解CPU的态
    长安链同步节点配置与启动
    【深度学习】(三)图像分类
  • 原文地址:https://blog.csdn.net/weixin_46251230/article/details/127703591