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.mzph.cn/news/119559.shtml

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

相关文章

二十三、设计模式之组合模式![

目录 二十三、设计模式之组合模式能帮我们干什么&#xff1f;主要解决什么问题&#xff1f;优缺点优点缺点&#xff1a; 使用的场景理解实现角色组合模式 总结 魔战已经完结。成功登顶。占领敌军最高峰。 二十三、设计模式之组合模式 “组合模式”也被称为“部分整体模式”该…

方舟生存进化ARK个人服务器搭建教程保姆级

方舟生存进化ARK个人服务器搭建教程保姆级 大家好我是艾西&#xff0c;在很久之前我有给大家分享过方舟生存进化的搭建架设教程&#xff0c;但时间久远且以前的教程我现在回头看去在某些地方说的并不是那么清楚。最近也是闲暇无事打算重新巩固下方舟生存进化的搭建架设教程&…

argparse模块介绍

argparse是一个Python模块&#xff1a;命令行选项、参数和子命令解析器。argparse 模块可以让人轻松编写用户友好的命令行接口。程序定义了所需的参数&#xff0c;而 argparse 将找出如何从 sys.argv &#xff08;命令行&#xff09;中解析这些参数。argparse 模块还会自动生成…

B-3:Web安全之综合渗透测试

B-3:Web安全之综合渗透测试 任务环境说明: 服务器场景:Server2104(关闭链接) 服务器场景用户名、密码:未知 1.通过URL访问http://靶机IP/1,对该页面进行渗透测试,将完成后返回的结果内容作为FLAG值提交; 通过访问IP/1,查看源代码发现flagishere,访问后发现什么也没…

【RabbitMQ】常用消息模型详解

文章目录 AMQP协议的回顾RabbitMQ支持的消息模型第一种模型(直连)开发生产者开发消费者生产者、消费者开发优化API参数细节 第二种模型(work quene)开发生产者开发消费者消息自动确认机制 第三种模型(fanout)开发生产者开发消费者 第四种模型(Routing)开发生产者开发消费者 第五…

jvm摘要

第 2 章 Java 内存区域与内存溢出异常 2.2 运行时数据区域 程序计数器-线程私有:是一块较小的内存空间&#xff0c;它可以看作是当前线程所执行的字节码的行号指示器。 程序计数器是唯一一个没有规定任何OutOfMemoryError 情况的区域。 Java 虚拟机栈-线程私有:用于执行Java …

悟空crm安装搭建 报错[0] RedisException in Redis.php line 56问题处理办法

相信很多朋友进行安装悟空crm的时候 提示错误&#xff1a; [0] RedisException in Redis.php line 56 Connection refused 不知道怎么样处理是吧~~~ $this->options array_merge($this->options, $options);}# redis 密码$password config(cache.password);if (!empty…

(二开)Flink 修改源码拓展 SQL 语法

1、Flink 扩展 calcite 中的语法解析 1&#xff09;定义需要的 SqlNode 节点类-以 SqlShowCatalogs 为例 a&#xff09;类位置 flink/flink-table/flink-sql-parser/src/main/java/org/apache/flink/sql/parser/dql/SqlShowCatalogs.java 核心方法&#xff1a; Override pu…

【C++】priority_queue仿函数

今天我们来学习C中另一个容器适配器&#xff1a;优先级队列——priority_queue&#xff1b;和C一个重要组件仿函数&#xff1a; 目录 一、priority_queue 1.1 priority_queue是什么 1.2 priority_queue的接口 1.2.1 priority_queue使用举例 二、仿函数 三、关于priority…

Docker GitLab-Runner安装

Docker GitLab-Runner安装 GitLab-Runner安装 问题合集GitLab 域名的配置修改Runner容器内注册失败&#xff0c;提示 dial tcp: lookup home.zsl0.com on 192.168.254.2:53: no such host GitLab-Runner 安装 拉去gitlab/gitlab-runner镜像 docker pull gitlab/gitlab-runne…

适用于 Windows 10 和 Windows 11 设备的笔记本电脑管理软件

便携式计算机管理软件使 IT 管理员能够简化企业中使用的便携式计算机的部署和管理&#xff0c;当今大多数员工使用Windows 笔记本电脑作为他们的主要工作机器&#xff0c;他们确实已成为几乎每个组织不可或缺的一部分。由于与台式机相比&#xff0c;笔记本电脑足够便携&#xf…

Git的远程仓库

Git的远程仓库 添加远程仓库从远程库克隆 添加远程仓库 你在本地创建了一个Git仓库后&#xff0c;又想在GitHub创建一个Git仓库&#xff0c;并且让这两个仓库进行远程同步&#xff0c;这样&#xff0c;GitHub上的仓库既可以作为备份&#xff0c;又可以让其他人通过该仓库来协作…

JoySSL:免费SSL证书的新选择

阿里云曾经提供了一年期的免费SSL证书&#xff0c;然而从下个月14号开始&#xff0c;阿里云不再提供免费的一年期SSL证书&#xff0c;而是改为68元/张/年&#xff0c;这对于很多网站建设公司需要大量基本证书来说&#xff0c;无疑是一种负担&#xff0c;又不知道该去哪里获取可…

jmeter如何测试websocket接口?

jmeter做接口测试&#xff0c;很多人都是做http协议的接口&#xff0c;就有很多人问websocket的接口怎么测试啊&#xff1f; 首先&#xff0c;我们要明白&#xff0c;websocket接口是什么接口。 然后&#xff0c;我们怎么用jmeter测试&#xff1f; jmeter要测试websocket接口…

fastjson对象序列化的问题

今天偶然遇到一个fastjson将字符串反序列化为一个对象的时候的问题&#xff0c;就是简单的通过com.alibaba.fastjson.JSON将对象转为字符串&#xff0c;然后再从字符串转换为原类型的对象。 涉及的代码也非常简单 package cn.edu.sgu.www.mhxysy.service.role.impl;import cn…

Linux文件I/O

下面的内容需要了解系统调用&#xff0c;可看下面的链接&#xff1a; 系统调用来龙去脉-CSDN博客 1.底层文件IO和标准IO 这里指的是操作系统提供的IO服务&#xff0c;不同于ANSI建立的标准IO。 底层IO和标准IO各自所使用的函数&#xff1a; 区别&#xff1a; 1.底层文件IO不…

Android 13 Framework 裁剪

裁剪应用 1. 修改 build/core/product.mk 添加PRODUCT_DEL_PACKAGES变量的声明 新增一行_product_single_value_vars PRODUCT_DEL_PACKAGES # The first API level this product shipped with _product_single_value_vars PRODUCT_SHIPPING_API_LEVEL _product_single_val…

本地存储 sessionStoragelocalStorage

随着互联网的快速发展&#xff0c;基于网页的应用越来越普遍&#xff0c;同时也变的越来越复杂&#xff0c;为了满足各种各样的需求&#xff0c;会经常性在本地存储大量的数据&#xff0c;HTML5规范提出了相关解决方案。 本地存储特性 数据存储在用户浏览器中 设置、读取方便、…

使用字节流读取文件中的数据的几种方式

public class FileReader02_ {public static void main(String[] args) {}Testpublic void m1() {String filePath "e:\\hello.txt";FileReader fileReader null;int date0;try {fileReader new FileReader(filePath);//循环读取 使用readwhile ((datefileReader.…

【opencv】【CPU】windows10下opencv4.8.0-cuda C++版本源码编译教程

【opencv】【CPU】windows10下opencv4.8.0-cuda C版本源码编译教程 提示:博主取舍了很多大佬的博文并亲测有效,分享笔记邀大家共同学习讨论 文章目录 【opencv】【CPU】windows10下opencv4.8.0-cuda C版本源码编译教程前言准备工具cmakeopencv4.8.0opencv_contrib CMake编译VS2…