STM32-LCD中英文显示及应用

目录

字符编码

ASCII码(8位)

中文编码(16位)

GB2312标准

GBK编码

GB18030标准(32位)

Big5编码

Unicode字符集和编码

UTF-32(32位)

UTF-16(16位/32位,变长编码方式)

UTF-8(8位/16位/24位/32位,变长编码方式)

实验环节1:LCD显示中英文(字库存储在外部Flash)

存储在外部Flash的字模(GB2312)

显示中文字符

显示中文字符串

显示中英文字符串

实验测试

实验现象

实验环节2:LCD显示中英文(任意大小、任何类型、居中显示)

缩放字模

缩放字模

缩放字模后显示字符

缩放字符后显示字符串

实验测试

实验现象


字符编码

由于计算机只能识别0和1,所以文字需要以0和1的形式在计算机内继续存储,故需要对文字进行编码。最简单的编码就是ASCII码。

ASCII码(8位)

ASCII码分两部分:

0~31:控制字符或通讯字符。没有特定的图形显示,但会根据不同应用程序而对文本显示有不同的影响。

32~127:空格、阿拉伯数字、标点符号、大小写英文字母和DEL。除了DEL符号外,其余的都能以图形显示。

后来,引入其他国家时需要扩展新的符号,所以从128~255都用来使用作为ASCII扩展字符集

中文编码(16位)

GB2312标准

它把ASCII码表的0~127编号保留,ASCII扩展字符集全部取消。

当2个编号大于127的字符连在一起时,就表示一个汉字,第一个字节和第二个字节都使用0xA1~0xFE编码。

第1个字节第2个字节表示字符说明
0x680x69hi两个字节的值都小于127(0x7f),使用ASCII解码
0xb00xa1两个字节的值都大于127(0x7f),使用GB2312解码

GBK编码

在GB2312标准的基础上,再增加许多汉字。

具体是只要第一个字节大于127(0x7F),就表示汉字的开始。

第1个字节第1个字节第1个字节表示字符说明
0x680xb00xa1h啊第1个字节使用ASCII解码,第2、3个字节使用GBK解码

0xb0

0xa10x68啊h第1、2个字节使用GBK解码,第3个字节使用ASCII解码
0xb00x560x68癡h第1、2个字节使用GBK解码,第3个字节使用ASCII解码

GB18030标准(32位)

在GBK编码之后再扩展。目前主流是GBK编码,但国家要求一些产品必须支持GB18030标准。

Big5编码

在台湾、香港等地区使用较多,因为主要特点是收录了繁体字。但GBK编码已经把Big5的所有汉字都收录进编码了(两者编码也不相同)。

Unicode字符集和编码

兼容ASCII码的字符编号,统一对符号的编号(即符号的顺序),但没对编码有要求,于是产生了几种Unicode编码方案。

UTF-32(32位)

直接将字符对应的编号数字转换为4字节的二进制数。不兼容ASCII码(因为使用的是4字节)。

特点:编码简单,解码方便,但浪费存储空间,而且存储时需要指定字节顺序(大端/小端格式)。

字符GBK编码Unicode编号UTF-32编码
A0x410x0000 0041大端格式:0x0000 0041
0xB0A10x0000 554A大端格式:0x0000 554A

UTF-16(16位/32位,变长编码方式)

对Unicode字符编号在0~65535的统一用2个字节表示,即0x0000~0xFFFF。而由于Unicode字符集在0xD800~0xDBFF是没有表示任何字符的,UTF-16利用这个空间对Unicode字符编号超出0xFFFF的字符建立映射关系。

特点:相对于UTF-32节省了存储空间,但存储时需要指定字节顺序(大端/小端格式),且仍不兼容ASCII码。

UTF-8(8位/16位/24位/32位,变长编码方式)

目前Unicode字符集中使用最广泛的编码方式,目前大部分网页文件都使用UTF-8编码。

实验环节1:LCD显示中英文(字库存储在外部Flash)

继承上篇液晶显示实验的函数内容,额外增加了显示中文的函数。

存储在外部Flash的字模(GB2312)

#define WIDTH_CH_CHAR	16	//中文字符宽度 
#define HEIGHT_CH_CHAR	16	//中文字符高度 #define GBKCODE_START_ADDRESS    387*4096    // 外部Flash的存储字库的起始地址#define GetGBKCode( ucBuffer, usChar )  GetGBKCode_from_EXFlash( ucBuffer, usChar )  
int GetGBKCode_from_EXFlash(uint8_t *pBuffer, uint16_t c)
{unsigned char High8bit, Low8bit;unsigned int pos;static uint8_t everRead = 0;/*第一次使用,初始化FLASH*/if (everRead == 0){SPI_FLASH_Init();everRead = 1;}High8bit = c >> 8;    /* 取高8位数据 */Low8bit = c & 0x00FF; /* 取低8位数据 *//* GB2312 公式 */pos = ((High8bit - 0xa1) * 94 + Low8bit - 0xa1) * WIDTH_CH_CHAR * HEIGHT_CH_CHAR / 8;SPI_FLASH_BufferRead(pBuffer, GBKCODE_START_ADDRESS + pos, WIDTH_CH_CHAR * HEIGHT_CH_CHAR / 8); //读取字库数据return 0;
}

显示中文字符

/*** @brief  在 ILI9341 显示器上显示一个中文字符* @param  usX :在特定扫描方向下字符的起始X坐标* @param  usY :在特定扫描方向下字符的起始Y坐标* @param  usChar :要显示的中文字符(国标码)* @note 可使用LCD_SetBackColor、LCD_SetTextColor、LCD_SetColors函数设置颜色* @retval 无*/
void ILI9341_DispChar_CH(uint16_t usX, uint16_t usY, uint16_t usChar)
{uint8_t rowCount, bitCount;uint8_t ucBuffer [ WIDTH_CH_CHAR * HEIGHT_CH_CHAR / 8 ];uint16_t usTemp;//设置显示窗口ILI9341_OpenWindow(usX, usY, WIDTH_CH_CHAR, HEIGHT_CH_CHAR);ILI9341_Write_Cmd(CMD_SetPixel);//取字模数据GetGBKCode(ucBuffer, usChar);for (rowCount = 0; rowCount < HEIGHT_CH_CHAR; rowCount++){/* 取出两个字节的数据,在lcd上即是一个汉字的一行 */usTemp = ucBuffer [ rowCount * 2 ];usTemp = (usTemp << 8);usTemp |= ucBuffer [ rowCount * 2 + 1 ];for (bitCount = 0; bitCount < WIDTH_CH_CHAR; bitCount ++){if (usTemp & (0x8000 >> bitCount))      //高位在前{ILI9341_Write_Data(CurrentTextColor);}else{ILI9341_Write_Data(CurrentBackColor);}}}
}

显示中文字符串

/*** @brief  在 ILI9341 显示器上显示中文字符串* @param  usX :在特定扫描方向下字符的起始X坐标* @param  usY :在特定扫描方向下字符的起始Y坐标* @param  pStr :要显示的英文字符串的首地址* @note 可使用LCD_SetBackColor、LCD_SetTextColor、LCD_SetColors函数设置颜色* @retval 无*/
void ILI9341_DispString_CH(uint16_t usX, uint16_t usY, char *pStr)
{uint16_t usCh;while (* pStr != '\0'){if ((usX - ILI9341_DispWindow_X_Star + WIDTH_CH_CHAR) > LCD_X_LENGTH){usX = ILI9341_DispWindow_X_Star;usY += HEIGHT_CH_CHAR;}if ((usY - ILI9341_DispWindow_Y_Star + HEIGHT_CH_CHAR) > LCD_Y_LENGTH){usX = ILI9341_DispWindow_X_Star;usY = ILI9341_DispWindow_Y_Star;}usCh = * (uint16_t *) pStr;usCh = (usCh << 8) + (usCh >> 8);ILI9341_DispChar_CH(usX, usY, usCh);usX += WIDTH_CH_CHAR;pStr += 2;           //一个汉字两个字节}
}/*** @brief  在 ILI9341 显示器上显示中英文字符串* @param  line :在特定扫描方向下字符串的起始Y坐标*   本参数可使用宏LINE(0)、LINE(1)等方式指定文字坐标,*   宏LINE(x)会根据当前选择的字体来计算Y坐标值。*		显示中文且使用LINE宏时,需要把英文字体设置成Font8x16* @param  pStr :要显示的字符串的首地址* @note 可使用LCD_SetBackColor、LCD_SetTextColor、LCD_SetColors函数设置颜色* @retval 无*/
void ILI9341_DispStringLine_EN_CH(uint16_t line, char *pStr)
{uint16_t usCh;uint16_t usX = 0;while (* pStr != '\0'){if (* pStr <= 126)	           	//英文字符{if ((usX - ILI9341_DispWindow_X_Star + LCD_Currentfonts->Width) > LCD_X_LENGTH){usX = ILI9341_DispWindow_X_Star;line += LCD_Currentfonts->Height;}if ((line - ILI9341_DispWindow_Y_Star + LCD_Currentfonts->Height) > LCD_Y_LENGTH){usX = ILI9341_DispWindow_X_Star;line = ILI9341_DispWindow_Y_Star;}ILI9341_DispChar_EN(usX, line, * pStr);usX +=  LCD_Currentfonts->Width;pStr ++;}else	                            //汉字字符{if ((usX - ILI9341_DispWindow_X_Star + WIDTH_CH_CHAR) > LCD_X_LENGTH){usX = ILI9341_DispWindow_X_Star;line += HEIGHT_CH_CHAR;}if ((line - ILI9341_DispWindow_Y_Star + HEIGHT_CH_CHAR) > LCD_Y_LENGTH){usX = ILI9341_DispWindow_X_Star;line = ILI9341_DispWindow_Y_Star;}usCh = * (uint16_t *) pStr;usCh = (usCh << 8) + (usCh >> 8);ILI9341_DispChar_CH(usX, line, usCh);usX += WIDTH_CH_CHAR;pStr += 2;           //一个汉字两个字节}}
}

显示中英文字符串

/*** @brief  在 ILI9341 显示器上显示中英文字符串* @param  usX :在特定扫描方向下字符的起始X坐标* @param  usY :在特定扫描方向下字符的起始Y坐标* @param  pStr :要显示的字符串的首地址* @note 可使用LCD_SetBackColor、LCD_SetTextColor、LCD_SetColors函数设置颜色* @retval 无*/
void ILI9341_DispString_EN_CH(uint16_t usX, uint16_t usY, char *pStr)
{uint16_t usCh;while (* pStr != '\0'){if (* pStr <= 126)	           	//英文字符{if ((usX - ILI9341_DispWindow_X_Star + LCD_Currentfonts->Width) > LCD_X_LENGTH){usX = ILI9341_DispWindow_X_Star;usY += LCD_Currentfonts->Height;}if ((usY - ILI9341_DispWindow_Y_Star + LCD_Currentfonts->Height) > LCD_Y_LENGTH){usX = ILI9341_DispWindow_X_Star;usY = ILI9341_DispWindow_Y_Star;}ILI9341_DispChar_EN(usX, usY, * pStr);usX +=  LCD_Currentfonts->Width;pStr ++;}else	                            //汉字字符{if ((usX - ILI9341_DispWindow_X_Star + WIDTH_CH_CHAR) > LCD_X_LENGTH){usX = ILI9341_DispWindow_X_Star;usY += HEIGHT_CH_CHAR;}if ((usY - ILI9341_DispWindow_Y_Star + HEIGHT_CH_CHAR) > LCD_Y_LENGTH){usX = ILI9341_DispWindow_X_Star;usY = ILI9341_DispWindow_Y_Star;}usCh = * (uint16_t *) pStr;usCh = (usCh << 8) + (usCh >> 8);ILI9341_DispChar_CH(usX, usY, usCh);usX += WIDTH_CH_CHAR;pStr += 2;           //一个汉字两个字节}}
}/*** @brief  在 ILI9341 显示器上显示中英文字符串(沿Y轴方向)* @param  usX :在特定扫描方向下字符的起始X坐标* @param  usY :在特定扫描方向下字符的起始Y坐标* @param  pStr :要显示的中英文字符串的首地址* @note 可使用LCD_SetBackColor、LCD_SetTextColor、LCD_SetColors函数设置颜色* @retval 无*/
void ILI9341_DispString_EN_CH_YDir(uint16_t usX, uint16_t usY, char *pStr)
{uint16_t usCh;while (* pStr != '\0'){//统一使用汉字的宽高来计算换行if ((usY - ILI9341_DispWindow_Y_Star + HEIGHT_CH_CHAR) > LCD_Y_LENGTH){usY = ILI9341_DispWindow_Y_Star;usX += WIDTH_CH_CHAR;}if ((usX - ILI9341_DispWindow_X_Star + WIDTH_CH_CHAR) >  LCD_X_LENGTH){usX = ILI9341_DispWindow_X_Star;usY = ILI9341_DispWindow_Y_Star;}//显示if (* pStr <= 126)	           	//英文字符{ILI9341_DispChar_EN(usX, usY, * pStr);pStr ++;usY += HEIGHT_CH_CHAR;}else	                            //汉字字符{usCh = * (uint16_t *) pStr;usCh = (usCh << 8) + (usCh >> 8);ILI9341_DispChar_CH(usX, usY, usCh);usY += HEIGHT_CH_CHAR;pStr += 2;           //一个汉字两个字节}}
}

实验测试

/*用于测试各种液晶的函数*/
void LCD_Test(void)
{/*演示显示变量*/static uint8_t testCNT = 0;char dispBuff[100];testCNT++;LCD_SetFont(&Font8x16);								// 设置字体类型:8*16,16*24,24*32LCD_SetColors(RED, BLACK);                          // 设置前景和背景色ILI9341_Clear(0, 0, LCD_X_LENGTH, LCD_Y_LENGTH);	// 清屏,显示全黑/********显示字符串示例*******/ILI9341_DispString_EN_CH(24, 0,   "  爱爱           爱爱");ILI9341_DispString_EN_CH(24, 16,  " 爱爱爱         爱爱爱");ILI9341_DispString_EN_CH(24, 32,  "爱爱爱爱爱   爱爱爱爱爱");ILI9341_DispString_EN_CH(24, 48,  " 爱爱爱         爱爱爱");ILI9341_DispString_EN_CH(24, 64,  "  爱爱爱       爱爱爱");ILI9341_DispString_EN_CH(24, 80,  "   爱爱爱     爱爱爱");ILI9341_DispString_EN_CH(24, 96,  "    爱爱爱   爱爱爱");ILI9341_DispString_EN_CH(24, 112, "     爱爱爱 爱爱爱");ILI9341_DispString_EN_CH(24, 128, "      爱爱^_^爱爱");/********显示变量示例*******/sprintf(dispBuff, "%04d ", testCNT);ILI9341_DispString_EN(104, 48, dispBuff);/*******显示图形示例******/LCD_SetFont(&Font24x32);/* 画直线 */LCD_ClearLine(LINE(5));		/* LINE4 = 32*5 = 160,清除单行文字 */LCD_SetTextColor(BLUE);ILI9341_DispStringLine_EN_CH(LINE(5), "画直线:");LCD_SetTextColor(RED);ILI9341_DrawLine(0, 176, 239, 319);ILI9341_DrawLine(239, 176, 0, 319);LCD_SetTextColor(YELLOW);ILI9341_DrawLine(0, 200, 239, 200);ILI9341_DrawLine(0, 300, 239, 300);LCD_SetTextColor(BLUE);ILI9341_DrawLine(20, 176, 20, 319);ILI9341_DrawLine(220, 176, 220, 319);HAL_Delay(2000);ILI9341_Clear(0, 16 * 11, LCD_X_LENGTH, LCD_Y_LENGTH - 16 * 11);	/* 清中下屏,显示全黑 *//*画矩形*/LCD_ClearLine(LINE(5));		/* LINE4 = 32*5 = 160,清除单行文字 */LCD_SetTextColor(BLUE);ILI9341_DispStringLine_EN_CH(LINE(5), "画矩形:");LCD_SetTextColor(RED);ILI9341_DrawRectangle(0, 176, 240, 144, 1);LCD_SetTextColor(YELLOW);ILI9341_DrawRectangle(80, 200, 120, 100, 0);LCD_SetTextColor(BLUE);ILI9341_DrawRectangle(120, 190, 100, 50, 1);HAL_Delay(2000);ILI9341_Clear(0, 16 * 11, LCD_X_LENGTH, LCD_Y_LENGTH - 16 * 11);	/* 清中下屏,显示全黑 *//* 画圆 */LCD_ClearLine(LINE(5));		/* LINE4 = 32*5 = 160,清除单行文字 */LCD_SetTextColor(BLUE);ILI9341_DispStringLine_EN_CH(LINE(5), "画圆:");LCD_SetTextColor(RED);ILI9341_DrawCircle(120, 250, 50, 0);LCD_SetTextColor(YELLOW);ILI9341_DrawCircle(120, 250, 30, 1);LCD_SetTextColor(BLUE);ILI9341_DrawCircle(120, 250, 10, 1);HAL_Delay(2000);ILI9341_Clear(0, 16 * 11, LCD_X_LENGTH, LCD_Y_LENGTH - 16 * 11);	/* 清中下屏,显示全黑 */
}

实验现象

实验环节2:LCD显示中英文(任意大小、任何类型、居中显示)

缩放字模

缩放字模
#define ZOOMMAXBUFF 16384
uint8_t zoomBuff[ZOOMMAXBUFF] = {0};	//用于缩放的缓存,最大支持到128*128
uint8_t zoomTempBuff[1024] = {0};/*** @brief  缩放字模,缩放后的字模由1个像素点由8个数据位来表示0x01表示笔迹,0x00表示空白区* @param  in_width :原始字符宽度* @param  in_heig :原始字符高度* @param  out_width :缩放后的字符宽度* @param  out_heig:缩放后的字符高度* @param  in_ptr :字库输入指针		  注意:1pixel 1bit* @param  out_ptr :缩放后的字符输出指针 注意: 1pixel 8bit*		   out_ptr实际上没有正常输出,改成了直接输出到全局指针zoomBuff中* @param  en_cn :0为英文,1为中文* @retval 无*/
void ILI9341_zoomChar(uint16_t in_width,	//原始字符宽度uint16_t in_heig,		//原始字符高度uint16_t out_width,	//缩放后的字符宽度uint16_t out_heig,	//缩放后的字符高度uint8_t *in_ptr,		//字库输入指针	注意:1pixel 1bituint8_t *out_ptr, 	//缩放后的字符输出指针 注意: 1pixel 8bituint8_t en_cn)		//0为英文,1为中文
{uint8_t *pts, *ots;//根据源字模及目标字模大小,设定运算比例因子,左移16是为了把浮点运算转成定点运算unsigned int xrIntFloat_16 = (in_width << 16) / out_width + 1;unsigned int yrIntFloat_16 = (in_heig << 16) / out_heig + 1;unsigned int srcy_16 = 0;unsigned int y, x;uint8_t *pSrcLine;uint16_t byteCount, bitCount;//检查参数是否合法if (in_width >= 32){return;    //字库不允许超过32像素}if (in_width * in_heig == 0){return;}if (in_width * in_heig >= 1024){return;    //限制输入最大 32*32}if (out_width * out_heig == 0){return;}if (out_width * out_heig >= ZOOMMAXBUFF){return;    //限制最大缩放 128*128}pts = (uint8_t *)&zoomTempBuff;//为方便运算,字库的数据由1 pixel/1bit 映射到1pixel/8bit//0x01表示笔迹,0x00表示空白区if (en_cn == 0x00) //英文{//英文和中文字库上下边界不对,可在此处调整。需要注意tempBuff防止溢出for (byteCount = 0; byteCount < in_heig * in_width / 8; byteCount++){for (bitCount = 0; bitCount < 8; bitCount++){//把源字模数据由位映射到字节//in_ptr里bitX为1,则pts里整个字节值为1//in_ptr里bitX为0,则pts里整个字节值为0*pts++ = (in_ptr[byteCount] & (0x80 >> bitCount)) ? 1 : 0;}}}else //中文{for (byteCount = 0; byteCount < in_heig * in_width / 8; byteCount++){for (bitCount = 0; bitCount < 8; bitCount++){//把源字模数据由位映射到字节//in_ptr里bitX为1,则pts里整个字节值为1//in_ptr里bitX为0,则pts里整个字节值为0*pts++ = (in_ptr[byteCount] & (0x80 >> bitCount)) ? 1 : 0;}}}//zoom过程pts = (uint8_t *)&zoomTempBuff;	//映射后的源数据指针ots = (uint8_t *)&zoomBuff;		//输出数据的指针for (y = 0; y < out_heig; y++)	/*行遍历*/{unsigned int srcx_16 = 0;pSrcLine = pts + in_width * (srcy_16 >> 16);for (x = 0; x < out_width; x++) 		/*行内像素遍历*/{ots[x] = pSrcLine[srcx_16 >> 16]; 	//把源字模数据复制到目标指针中srcx_16 += xrIntFloat_16;			//按比例偏移源像素点}srcy_16 += yrIntFloat_16;				//按比例偏移源像素点ots += out_width;}/*!!!缩放后的字模数据直接存储到全局指针zoomBuff里了*/out_ptr = (uint8_t *)&zoomBuff;	//out_ptr没有正确传出,后面调用直接改成了全局变量指针!/*实际中如果使用out_ptr不需要下面这一句!!!只是因为out_ptr没有使用,会导致warning。强迫症*/out_ptr++;
}

缩放字模后显示字符
/*** @brief  利用缩放后的字模显示字符* @param  Xpos :字符显示位置x* @param  Ypos :字符显示位置y* @param  Font_width :字符宽度* @param  Font_Heig:字符高度* @param  c :要显示的字模数据* @param  DrawModel :是否反色显示* @retval 无*/
void ILI9341_DrawChar_Ex(uint16_t usX, 			//字符显示位置xuint16_t usY, 			//字符显示位置yuint16_t Font_width, 	//字符宽度uint16_t Font_Height,  //字符高度uint8_t *c,			//字模数据uint16_t DrawModel)	//是否反色显示
{uint32_t index = 0, counter = 0;//设置显示窗口ILI9341_OpenWindow(usX, usY, Font_width, Font_Height);ILI9341_Write_Cmd(CMD_SetPixel);//按字节读取字模数据//由于前面直接设置了显示窗口,显示数据会自动换行for (index = 0; index < Font_Height; index++){//一位一位处理要显示的颜色for (counter = 0; counter < Font_width; counter++){//缩放后的字模数据,以一个字节表示一个像素位//整个字节值为1表示该像素为笔迹//整个字节值为0表示该像素为背景if (*c++ == DrawModel){ILI9341_Write_Data(CurrentBackColor);}else{ILI9341_Write_Data(CurrentTextColor);}}}
}

缩放字符后显示字符串
/*** @brief  利用缩放后的字模显示字符串* @param  Xpos :字符显示位置x* @param  Ypos :字符显示位置y* @param  Font_width :字符宽度,英文字符在此基础上/2。注意为偶数* @param  Font_Heig:字符高度,注意为偶数* @param  c :要显示的字符串* @param  DrawModel :是否反色显示* @retval 无*/
void ILI9341_DisplayStringEx(uint16_t x, 		    //字符显示位置xuint16_t y, 			//字符显示位置yuint16_t Font_width,	//要显示的字体宽度,英文字符在此基础上/2。注意为偶数uint16_t Font_Height,	//要显示的字体高度,注意为偶数uint8_t *ptr,			//显示的字符内容uint16_t DrawModel)    //是否反色显示{uint16_t Charwidth = Font_width; //默认为Font_width,英文宽度为中文宽度的一半uint8_t *psr;uint8_t Ascii;	//英文uint16_t usCh;  //中文uint8_t ucBuffer [ WIDTH_CH_CHAR * HEIGHT_CH_CHAR / 8 ];while (*ptr != '\0'){/****处理换行*****/if ((x - ILI9341_DispWindow_X_Star + Charwidth) > LCD_X_LENGTH){x = ILI9341_DispWindow_X_Star;y += Font_Height;}if ((y - ILI9341_DispWindow_Y_Star + Font_Height) > LCD_Y_LENGTH){x = ILI9341_DispWindow_X_Star;y = ILI9341_DispWindow_Y_Star;}if (*ptr > 0x80) //如果是中文{Charwidth = Font_width;usCh = * (uint16_t *) ptr;usCh = (usCh << 8) + (usCh >> 8);GetGBKCode(ucBuffer, usCh);	//取字模数据//缩放字模数据,源字模为16*16ILI9341_zoomChar(WIDTH_CH_CHAR, HEIGHT_CH_CHAR, Charwidth, Font_Height, (uint8_t *)&ucBuffer, psr, 1);//显示单个字符ILI9341_DrawChar_Ex(x, y, Charwidth, Font_Height, (uint8_t *)&zoomBuff, DrawModel);x += Charwidth;ptr += 2;}else{Charwidth = Font_width / 2;Ascii = *ptr - 32;//使用16*24字体缩放字模数据ILI9341_zoomChar(16, 24, Charwidth, Font_Height,(uint8_t *)&Font16x24.table[Ascii * Font16x24.Height * Font16x24.Width / 8], psr, 0);//显示单个字符ILI9341_DrawChar_Ex(x, y, Charwidth, Font_Height, (uint8_t *)&zoomBuff, DrawModel);x += Charwidth;ptr++;}}
}/*** @brief  利用缩放后的字模显示字符串(沿Y轴方向)* @param  Xpos :字符显示位置x* @param  Ypos :字符显示位置y* @param  Font_width :字符宽度,英文字符在此基础上/2。注意为偶数* @param  Font_Heig:字符高度,注意为偶数* @param  c :要显示的字符串* @param  DrawModel :是否反色显示* @retval 无*/
void ILI9341_DisplayStringEx_YDir(uint16_t x, 		//字符显示位置xuint16_t y, 				//字符显示位置yuint16_t Font_width,	//要显示的字体宽度,英文字符在此基础上/2。注意为偶数uint16_t Font_Height,	//要显示的字体高度,注意为偶数uint8_t *ptr,					//显示的字符内容uint16_t DrawModel)  //是否反色显示
{uint16_t Charwidth = Font_width; //默认为Font_width,英文宽度为中文宽度的一半uint8_t *psr;uint8_t Ascii;	//英文uint16_t usCh;  //中文uint8_t ucBuffer [ WIDTH_CH_CHAR * HEIGHT_CH_CHAR / 8 ];while (*ptr != '\0'){//统一使用汉字的宽高来计算换行if ((y - ILI9341_DispWindow_X_Star + Font_width) > LCD_X_LENGTH){y = ILI9341_DispWindow_X_Star;x += Font_width;}if ((x - ILI9341_DispWindow_Y_Star + Font_Height) > LCD_Y_LENGTH){y = ILI9341_DispWindow_X_Star;x = ILI9341_DispWindow_Y_Star;}if (*ptr > 0x80) //如果是中文{Charwidth = Font_width;usCh = * (uint16_t *) ptr;usCh = (usCh << 8) + (usCh >> 8);GetGBKCode(ucBuffer, usCh);	//取字模数据//缩放字模数据,源字模为16*16ILI9341_zoomChar(WIDTH_CH_CHAR, HEIGHT_CH_CHAR, Charwidth, Font_Height, (uint8_t *)&ucBuffer, psr, 1);//显示单个字符ILI9341_DrawChar_Ex(x, y, Charwidth, Font_Height, (uint8_t *)&zoomBuff, DrawModel);y += Font_Height;ptr += 2;}else{Charwidth = Font_width / 2;Ascii = *ptr - 32;//使用16*24字体缩放字模数据ILI9341_zoomChar(16, 24, Charwidth, Font_Height,(uint8_t *)&Font16x24.table[Ascii * Font16x24.Height * Font16x24.Width / 8], psr, 0);//显示单个字符ILI9341_DrawChar_Ex(x, y, Charwidth, Font_Height, (uint8_t *)&zoomBuff, DrawModel);y += Font_Height;ptr++;}}
}

实验测试

/*******************中文********** 在显示屏上显示的字符大小 ***************************/
#define WIDTH_CH_CHAR	16	    //中文字符宽度 
#define HEIGHT_CH_CHAR	16		//中文字符高度 /*用于测试各种液晶的函数*/
void LCD_Test(void)
{/*演示显示变量*/static uint8_t testCNT = 0;static float testFloatCNT = 0;	char dispBuff[100];char *pStr = 0;testCNT++;testFloatCNT += 0.1;LCD_SetFont(&Font8x16);                             // 设置字体类型:8*16,16*24,24*32LCD_SetColors(RED, BLACK);                          // 设置前景和背景色ILI9341_Clear(0, 0, LCD_X_LENGTH, LCD_Y_LENGTH);	// 清屏,显示全黑//显示指定大小的字符ILI9341_DisplayStringEx(0, 0, 48, 48, (uint8_t *)"博客:", 0);ILI9341_DisplayStringEx(120, 0, 24, 24, (uint8_t *)"couvrir", 0);/********显示字符串示例*******/ILI9341_DispString_EN_CH (120, 24, "洪荒猛兽");/********显示变量示例*******/LCD_SetTextColor(GREEN);/*使用c标准库把变量转化成字符串*/sprintf(dispBuff, "显示变量: %d ", testCNT);LCD_ClearLine(LINE(3));ILI9341_DispStringLine_EN_CH(LINE(3), dispBuff);sprintf(dispBuff,"显示浮点型变量: %f ",testFloatCNT);LCD_ClearLine(LINE(4));ILI9341_DispStringLine_EN_CH(LINE(4), dispBuff);sprintf(dispBuff,"浮点型(保留2位小数): %.2f ",testFloatCNT);LCD_ClearLine(LINE(5));ILI9341_DispStringLine_EN_CH(LINE(5), dispBuff);/********居中显示示例*******/LCD_SetTextColor(YELLOW);pStr = "插入2个英文空格示例";//使用 %*c 在字符串前插入指定个数的英文空格sprintf(dispBuff, "%*c%s", 2, ' ', pStr);LCD_ClearLine(LINE(6));ILI9341_DispStringLine_EN_CH(LINE(6), dispBuff);ILI9341_DispStringLine_EN_CH(LINE(7), "居中示例:");pStr = "ABCDEF";//居中时,要插入的空格个数 = (液晶宽度/单个字体宽度 - 字符串长度)/2sprintf(dispBuff, "%*c%s", ( (LCD_X_LENGTH/(((sFONT *)LCD_GetFont())->Width) ) - strlen(pStr))/2, ' ', pStr);LCD_ClearLine(LINE(8));ILI9341_DispStringLine_EN_CH(LINE(8),dispBuff);pStr = "中文居中示例";//居中时,要插入的空格个数 = (液晶宽度/字体宽度 - 字符串长度)/2//strlen计算长度时,一个中文等于2个字节,即2个英文字符,而且插入的是英文空格//所以用(WIDTH_CH_CHAR/2)来计算字体宽度sprintf(dispBuff, "%*c%s", ( LCD_X_LENGTH/(WIDTH_CH_CHAR/2) - strlen(pStr))/2, ' ', pStr);LCD_ClearLine(LINE(9));ILI9341_DispStringLine_EN_CH(LINE(9),dispBuff);/*******显示图形示例******/LCD_SetFont(&Font24x32);/* 画直线 */LCD_ClearLine(LINE(5));		/* LINE4 = 32*5 = 160,清除单行文字 */LCD_SetTextColor(BLUE);ILI9341_DispStringLine_EN_CH(LINE(5), "画直线:");LCD_SetTextColor(RED);ILI9341_DrawLine(0, 176, 239, 319);ILI9341_DrawLine(239, 176, 0, 319);LCD_SetTextColor(YELLOW);ILI9341_DrawLine(0, 200, 239, 200);ILI9341_DrawLine(0, 300, 239, 300);LCD_SetTextColor(BLUE);ILI9341_DrawLine(20, 176, 20, 319);ILI9341_DrawLine(220, 176, 220, 319);HAL_Delay(2000);ILI9341_Clear(0, 16 * 11, LCD_X_LENGTH, LCD_Y_LENGTH - 16 * 11);	/* 清中下屏,显示全黑 *//*画矩形*/LCD_ClearLine(LINE(5));		/* LINE4 = 32*5 = 160,清除单行文字 */LCD_SetTextColor(BLUE);ILI9341_DispStringLine_EN_CH(LINE(5), "画矩形:");LCD_SetTextColor(RED);ILI9341_DrawRectangle(0, 176, 240, 144, 1);LCD_SetTextColor(YELLOW);ILI9341_DrawRectangle(80, 200, 120, 100, 0);LCD_SetTextColor(BLUE);ILI9341_DrawRectangle(120, 190, 100, 50, 1);HAL_Delay(2000);ILI9341_Clear(0, 16 * 11, LCD_X_LENGTH, LCD_Y_LENGTH - 16 * 11);	/* 清中下屏,显示全黑 *//* 画圆 */LCD_ClearLine(LINE(5));		/* LINE4 = 32*5 = 160,清除单行文字 */LCD_SetTextColor(BLUE);ILI9341_DispStringLine_EN_CH(LINE(5), "画圆:");LCD_SetTextColor(RED);ILI9341_DrawCircle(120, 250, 50, 0);LCD_SetTextColor(YELLOW);ILI9341_DrawCircle(120, 250, 30, 1);LCD_SetTextColor(BLUE);ILI9341_DrawCircle(120, 250, 10, 1);HAL_Delay(2000);ILI9341_Clear(0, 16 * 11, LCD_X_LENGTH, LCD_Y_LENGTH - 16 * 11);	/* 清中下屏,显示全黑 */
}

实验现象

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

桶装水订水送水小程序开发搭建;

上门送水小程序桶装水配送是一款的同城上门配送平台&#xff0c;为用户提供便捷的桶装水配送服务。解决用户在获取干净健康的饮用水方面的需求&#xff0c;提供高效、便捷的在线预约和下单服务。 小程序平台开发&#xff0c;具备强大的技术支持和良好的用户体验。用户可以通过…

【vue3】依赖注 provide、inject(父组件与儿子、孙子、曾孙子组件之间的传值)

一、基本用法&#xff1a; //父组件 import { ref, provide } from vue const radio ref<string>(red) provide(myColor,radio) //注入依赖//儿子组件、孙子组件、曾孙子组件 import { inject } from vue import type { Ref } from vue; const myColor inject<Ref&l…

设计模式中的黄金原则:引领你的代码风格,提升可维护性与扩展性

中国的先贤说过: 有道无术,术可求.有术无道,止于术. 术指的是技能、技术或方法&#xff0c;而道指的是原则、道德、智慧和理念。 西方古代的哲人也说过同样的话: 智慧之路从感性开始&#xff0c;却终极于理性.为什么要说设计原则呢, 因为设计模式通常需要遵循一些设计原则&…

基于减法平均优化的BP神经网络(分类应用) - 附代码

基于减法平均优化的BP神经网络&#xff08;分类应用&#xff09; - 附代码 文章目录 基于减法平均优化的BP神经网络&#xff08;分类应用&#xff09; - 附代码1.鸢尾花iris数据介绍2.数据集整理3.减法平均优化BP神经网络3.1 BP神经网络参数设置3.2 减法平均算法应用 4.测试结果…

筹备三年,自动驾驶L3标准将至,智驾产业链的关键一跃

‍作者|张祥威 编辑|德新 多位知情人士告诉HiEV&#xff0c;智能网联汽车准入试点通知&#xff0c;乐观预计将在一个月内发布。试点的推动&#xff0c;意味着国家层面的自动驾驶L3标准随之到来。 「L3标准内容大部分与主机厂相关&#xff0c;由工信部牵头&#xff0c;找了几家…

使用vite搭建前端项目

1、在vscode 终端那里执行创建前端工程项目&#xff0c;其中shop-admin为项目名称&#xff1a; npm init vite-app shop-admin 提示如需安装其他依赖执行npm install ....,否则忽略(第三步再讲)。 2、执行npm run dev 命令直接运行创建好的项目&#xff0c;在浏览器打开链接…

Spring底层原理(三)

Spring底层原理(三) Bean的生命周期 SpringBootApplication public class Application {public static void main(String[] args) {ConfigurableApplicationContext context SpringApplication.run(Application.class, args);context.close();} }Slf4j Component public cla…

Echarts自定义柱状图

目录 效果图 echarts官网找相似图 将柱状图引入html页面中 自定义柱状图 将不需要的属性删除 ​编辑 修改图形大小 grid 不显示x轴 ​编辑 不显示y轴线和相关刻度 ​编辑 y轴文字的颜色设置为自己想要的颜色 修改第一组柱子相关样式&#xff08;条状&#xff09; …

解决 /bin/bash^M: bad interpreter: No such file or directory

问题描述 linux 系统中知行*.sh 文件报/bin/bash^M: bad interpreter: No such file or directory 原因&#xff1a; .sh文件是在windows系统编写的&#xff0c;在linux执行就有问题 解决过程 转化下格式执行如下命令 # dos2unix app.sh 结果bash: dos2unix: command not …

性能优化:JIT即时编译与AOT提前编译

优质博文&#xff1a;IT-BLOG-CN 一、简介 JIT与AOT的区别&#xff1a; 两种不同的编译方式&#xff0c;主要区别在于是否处于运行时进行编译。 JIT:Just-in-time动态(即时)编译&#xff0c;边运行边编译&#xff1a;在程序运行时&#xff0c;根据算法计算出热点代码&#xf…

类图表示法

设计模式&#xff0c;用设计图表示的话&#xff0c;主要用到类图。常见UML类图如下&#xff1a; 1、类图&#xff1a;矩形框&#xff0c;代表一个类&#xff08;Class&#xff09;。类图分为三层&#xff0c;第一层显示类的名称&#xff0c;如果是抽象类&#xff0c;则用斜体显…

FFmpeg编译安装(windows环境)以及在vs2022中调用

文章目录 下载源码环境准备下载msys换源下载依赖源码位置 开始编译编译x264编译ffmpeg 在VS2022写cpp调用ffmpeg 下载源码 直接在官网下载压缩包 这个应该是目前&#xff08;2023/10/24&#xff09;最新的一个版本。下载之后是这个样子&#xff1a; 我打算添加外部依赖x264&a…

探索随机森林: 机器学习中的集成学习神器

机器学习 第七课 随机森林 概述机器学习机器学习的主要分类监督学习无监督学习强化学习 集成学习提高准确性增强稳定性提升泛化能力 集成学习的主要方法BaggingBoostingStacking 随机森林的理论基础决策树的基本原理随机森林的生成过程随机森林的优势与局限性 随机森林的实际应…

进阶JAVA篇-深入了解 Stream 流对象的创建与中间方法、终结方法

目录 1.0 Stream 流的说明 2.0 Stream 流对象的创建 2.1 对于 Collection 系列集合创建 Stream 流对象的方式 2.2 对于 Map 系列集合创建 Stream 流对象的方式 2.3 对于数组创建 Stream 流对象的方式 3.0 Stream 流的中间方法 3.1 Stream 流的 filter() 中间方法 3.2 Stream 流…

C++基类和派生类的内存分配,多态的实现

目录 基类和派生类的内存分配基类和派生类的成员归属多态的实现 基类和派生类的内存分配 类包括成员变量&#xff08;data member&#xff09;和成员函数&#xff08;member function&#xff09;。 成员变量分为静态数据&#xff08;static data&#xff09;和非静态数据&…

Git简明教程

1.Git的定位 在我们自己开发项目的过程中&#xff0c;经常会遇到这样的情况&#xff0c;为了防止代码丢失&#xff0c;或者新变更的代码影响到原有的代码功能&#xff0c;为了在失误后能恢复到原来的版本&#xff0c;不得不复制出一个副本,比如&#xff1a;“坦克大战1.0”“坦…

【Html】交通灯问题

效果 实现方式 计时器&#xff1a;setTimeout或setInterval来计时。setInterval和 setTimeout 在某些情况下可能会出现计时不准确的情况。这通常是由于JavaScript的事件循环机制和其他代码执行所需的时间造成的。 问询&#xff1a;通过getCurrentLight将每个状态的持续时间设置…

Git常用的命令有哪些?

一、前言 git 的操作可以通过命令的形式如执行&#xff0c;日常使用就如下图6个命令即可 实际上&#xff0c;如果想要熟练使用&#xff0c;超过60多个命令需要了解&#xff0c;下面则介绍下常见的的git 命令 二、有哪些 配置 Git 自带一个 git config 的工具来帮助设置控制…

Haproxy 服务

Haproxy&#xff1a;他也是常用的负载均衡软件 nginx 支持四层转发&#xff0c;七层转发 haproxy 也是四层和七层转发 LVS的DR和NAT都是基于四层转发 都是基于流量的转发。 tun:四层和七层都有。 基于四层的转发&#xff1a; 1&#xff0c;lvs 2&#xff0c;nginx 3&…

对python中切片详解

嗨喽&#xff0c;大家好呀~这里是爱看美女的茜茜呐 Python中什么可以切片 Python中符合序列的有序序列都支持切片(slice) 如:列表,字符,元祖 &#x1f447; &#x1f447; &#x1f447; 更多精彩机密、教程&#xff0c;尽在下方&#xff0c;赶紧点击了解吧~ python源码、视…