• 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)

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

    显示中文字符

    1. /**
    2. * @brief 在 ILI9341 显示器上显示一个中文字符
    3. * @param usX :在特定扫描方向下字符的起始X坐标
    4. * @param usY :在特定扫描方向下字符的起始Y坐标
    5. * @param usChar :要显示的中文字符(国标码)
    6. * @note 可使用LCD_SetBackColor、LCD_SetTextColor、LCD_SetColors函数设置颜色
    7. * @retval 无
    8. */
    9. void ILI9341_DispChar_CH(uint16_t usX, uint16_t usY, uint16_t usChar)
    10. {
    11. uint8_t rowCount, bitCount;
    12. uint8_t ucBuffer [ WIDTH_CH_CHAR * HEIGHT_CH_CHAR / 8 ];
    13. uint16_t usTemp;
    14. //设置显示窗口
    15. ILI9341_OpenWindow(usX, usY, WIDTH_CH_CHAR, HEIGHT_CH_CHAR);
    16. ILI9341_Write_Cmd(CMD_SetPixel);
    17. //取字模数据
    18. GetGBKCode(ucBuffer, usChar);
    19. for (rowCount = 0; rowCount < HEIGHT_CH_CHAR; rowCount++)
    20. {
    21. /* 取出两个字节的数据,在lcd上即是一个汉字的一行 */
    22. usTemp = ucBuffer [ rowCount * 2 ];
    23. usTemp = (usTemp << 8);
    24. usTemp |= ucBuffer [ rowCount * 2 + 1 ];
    25. for (bitCount = 0; bitCount < WIDTH_CH_CHAR; bitCount ++)
    26. {
    27. if (usTemp & (0x8000 >> bitCount)) //高位在前
    28. {
    29. ILI9341_Write_Data(CurrentTextColor);
    30. }
    31. else
    32. {
    33. ILI9341_Write_Data(CurrentBackColor);
    34. }
    35. }
    36. }
    37. }

    显示中文字符串

    1. /**
    2. * @brief 在 ILI9341 显示器上显示中文字符串
    3. * @param usX :在特定扫描方向下字符的起始X坐标
    4. * @param usY :在特定扫描方向下字符的起始Y坐标
    5. * @param pStr :要显示的英文字符串的首地址
    6. * @note 可使用LCD_SetBackColor、LCD_SetTextColor、LCD_SetColors函数设置颜色
    7. * @retval 无
    8. */
    9. void ILI9341_DispString_CH(uint16_t usX, uint16_t usY, char *pStr)
    10. {
    11. uint16_t usCh;
    12. while (* pStr != '\0')
    13. {
    14. if ((usX - ILI9341_DispWindow_X_Star + WIDTH_CH_CHAR) > LCD_X_LENGTH)
    15. {
    16. usX = ILI9341_DispWindow_X_Star;
    17. usY += HEIGHT_CH_CHAR;
    18. }
    19. if ((usY - ILI9341_DispWindow_Y_Star + HEIGHT_CH_CHAR) > LCD_Y_LENGTH)
    20. {
    21. usX = ILI9341_DispWindow_X_Star;
    22. usY = ILI9341_DispWindow_Y_Star;
    23. }
    24. usCh = * (uint16_t *) pStr;
    25. usCh = (usCh << 8) + (usCh >> 8);
    26. ILI9341_DispChar_CH(usX, usY, usCh);
    27. usX += WIDTH_CH_CHAR;
    28. pStr += 2; //一个汉字两个字节
    29. }
    30. }
    31. /**
    32. * @brief 在 ILI9341 显示器上显示中英文字符串
    33. * @param line :在特定扫描方向下字符串的起始Y坐标
    34. * 本参数可使用宏LINE(0)、LINE(1)等方式指定文字坐标,
    35. * 宏LINE(x)会根据当前选择的字体来计算Y坐标值。
    36. * 显示中文且使用LINE宏时,需要把英文字体设置成Font8x16
    37. * @param pStr :要显示的字符串的首地址
    38. * @note 可使用LCD_SetBackColor、LCD_SetTextColor、LCD_SetColors函数设置颜色
    39. * @retval 无
    40. */
    41. void ILI9341_DispStringLine_EN_CH(uint16_t line, char *pStr)
    42. {
    43. uint16_t usCh;
    44. uint16_t usX = 0;
    45. while (* pStr != '\0')
    46. {
    47. if (* pStr <= 126) //英文字符
    48. {
    49. if ((usX - ILI9341_DispWindow_X_Star + LCD_Currentfonts->Width) > LCD_X_LENGTH)
    50. {
    51. usX = ILI9341_DispWindow_X_Star;
    52. line += LCD_Currentfonts->Height;
    53. }
    54. if ((line - ILI9341_DispWindow_Y_Star + LCD_Currentfonts->Height) > LCD_Y_LENGTH)
    55. {
    56. usX = ILI9341_DispWindow_X_Star;
    57. line = ILI9341_DispWindow_Y_Star;
    58. }
    59. ILI9341_DispChar_EN(usX, line, * pStr);
    60. usX += LCD_Currentfonts->Width;
    61. pStr ++;
    62. }
    63. else //汉字字符
    64. {
    65. if ((usX - ILI9341_DispWindow_X_Star + WIDTH_CH_CHAR) > LCD_X_LENGTH)
    66. {
    67. usX = ILI9341_DispWindow_X_Star;
    68. line += HEIGHT_CH_CHAR;
    69. }
    70. if ((line - ILI9341_DispWindow_Y_Star + HEIGHT_CH_CHAR) > LCD_Y_LENGTH)
    71. {
    72. usX = ILI9341_DispWindow_X_Star;
    73. line = ILI9341_DispWindow_Y_Star;
    74. }
    75. usCh = * (uint16_t *) pStr;
    76. usCh = (usCh << 8) + (usCh >> 8);
    77. ILI9341_DispChar_CH(usX, line, usCh);
    78. usX += WIDTH_CH_CHAR;
    79. pStr += 2; //一个汉字两个字节
    80. }
    81. }
    82. }

    显示中英文字符串

    1. /**
    2. * @brief 在 ILI9341 显示器上显示中英文字符串
    3. * @param usX :在特定扫描方向下字符的起始X坐标
    4. * @param usY :在特定扫描方向下字符的起始Y坐标
    5. * @param pStr :要显示的字符串的首地址
    6. * @note 可使用LCD_SetBackColor、LCD_SetTextColor、LCD_SetColors函数设置颜色
    7. * @retval 无
    8. */
    9. void ILI9341_DispString_EN_CH(uint16_t usX, uint16_t usY, char *pStr)
    10. {
    11. uint16_t usCh;
    12. while (* pStr != '\0')
    13. {
    14. if (* pStr <= 126) //英文字符
    15. {
    16. if ((usX - ILI9341_DispWindow_X_Star + LCD_Currentfonts->Width) > LCD_X_LENGTH)
    17. {
    18. usX = ILI9341_DispWindow_X_Star;
    19. usY += LCD_Currentfonts->Height;
    20. }
    21. if ((usY - ILI9341_DispWindow_Y_Star + LCD_Currentfonts->Height) > LCD_Y_LENGTH)
    22. {
    23. usX = ILI9341_DispWindow_X_Star;
    24. usY = ILI9341_DispWindow_Y_Star;
    25. }
    26. ILI9341_DispChar_EN(usX, usY, * pStr);
    27. usX += LCD_Currentfonts->Width;
    28. pStr ++;
    29. }
    30. else //汉字字符
    31. {
    32. if ((usX - ILI9341_DispWindow_X_Star + WIDTH_CH_CHAR) > LCD_X_LENGTH)
    33. {
    34. usX = ILI9341_DispWindow_X_Star;
    35. usY += HEIGHT_CH_CHAR;
    36. }
    37. if ((usY - ILI9341_DispWindow_Y_Star + HEIGHT_CH_CHAR) > LCD_Y_LENGTH)
    38. {
    39. usX = ILI9341_DispWindow_X_Star;
    40. usY = ILI9341_DispWindow_Y_Star;
    41. }
    42. usCh = * (uint16_t *) pStr;
    43. usCh = (usCh << 8) + (usCh >> 8);
    44. ILI9341_DispChar_CH(usX, usY, usCh);
    45. usX += WIDTH_CH_CHAR;
    46. pStr += 2; //一个汉字两个字节
    47. }
    48. }
    49. }
    50. /**
    51. * @brief 在 ILI9341 显示器上显示中英文字符串(沿Y轴方向)
    52. * @param usX :在特定扫描方向下字符的起始X坐标
    53. * @param usY :在特定扫描方向下字符的起始Y坐标
    54. * @param pStr :要显示的中英文字符串的首地址
    55. * @note 可使用LCD_SetBackColor、LCD_SetTextColor、LCD_SetColors函数设置颜色
    56. * @retval 无
    57. */
    58. void ILI9341_DispString_EN_CH_YDir(uint16_t usX, uint16_t usY, char *pStr)
    59. {
    60. uint16_t usCh;
    61. while (* pStr != '\0')
    62. {
    63. //统一使用汉字的宽高来计算换行
    64. if ((usY - ILI9341_DispWindow_Y_Star + HEIGHT_CH_CHAR) > LCD_Y_LENGTH)
    65. {
    66. usY = ILI9341_DispWindow_Y_Star;
    67. usX += WIDTH_CH_CHAR;
    68. }
    69. if ((usX - ILI9341_DispWindow_X_Star + WIDTH_CH_CHAR) > LCD_X_LENGTH)
    70. {
    71. usX = ILI9341_DispWindow_X_Star;
    72. usY = ILI9341_DispWindow_Y_Star;
    73. }
    74. //显示
    75. if (* pStr <= 126) //英文字符
    76. {
    77. ILI9341_DispChar_EN(usX, usY, * pStr);
    78. pStr ++;
    79. usY += HEIGHT_CH_CHAR;
    80. }
    81. else //汉字字符
    82. {
    83. usCh = * (uint16_t *) pStr;
    84. usCh = (usCh << 8) + (usCh >> 8);
    85. ILI9341_DispChar_CH(usX, usY, usCh);
    86. usY += HEIGHT_CH_CHAR;
    87. pStr += 2; //一个汉字两个字节
    88. }
    89. }
    90. }

    实验测试

    1. /*用于测试各种液晶的函数*/
    2. void LCD_Test(void)
    3. {
    4. /*演示显示变量*/
    5. static uint8_t testCNT = 0;
    6. char dispBuff[100];
    7. testCNT++;
    8. LCD_SetFont(&Font8x16); // 设置字体类型:8*16,16*24,24*32
    9. LCD_SetColors(RED, BLACK); // 设置前景和背景色
    10. ILI9341_Clear(0, 0, LCD_X_LENGTH, LCD_Y_LENGTH); // 清屏,显示全黑
    11. /********显示字符串示例*******/
    12. ILI9341_DispString_EN_CH(24, 0, " 爱爱 爱爱");
    13. ILI9341_DispString_EN_CH(24, 16, " 爱爱爱 爱爱爱");
    14. ILI9341_DispString_EN_CH(24, 32, "爱爱爱爱爱 爱爱爱爱爱");
    15. ILI9341_DispString_EN_CH(24, 48, " 爱爱爱 爱爱爱");
    16. ILI9341_DispString_EN_CH(24, 64, " 爱爱爱 爱爱爱");
    17. ILI9341_DispString_EN_CH(24, 80, " 爱爱爱 爱爱爱");
    18. ILI9341_DispString_EN_CH(24, 96, " 爱爱爱 爱爱爱");
    19. ILI9341_DispString_EN_CH(24, 112, " 爱爱爱 爱爱爱");
    20. ILI9341_DispString_EN_CH(24, 128, " 爱爱^_^爱爱");
    21. /********显示变量示例*******/
    22. sprintf(dispBuff, "%04d ", testCNT);
    23. ILI9341_DispString_EN(104, 48, dispBuff);
    24. /*******显示图形示例******/
    25. LCD_SetFont(&Font24x32);
    26. /* 画直线 */
    27. LCD_ClearLine(LINE(5)); /* LINE4 = 32*5 = 160,清除单行文字 */
    28. LCD_SetTextColor(BLUE);
    29. ILI9341_DispStringLine_EN_CH(LINE(5), "画直线:");
    30. LCD_SetTextColor(RED);
    31. ILI9341_DrawLine(0, 176, 239, 319);
    32. ILI9341_DrawLine(239, 176, 0, 319);
    33. LCD_SetTextColor(YELLOW);
    34. ILI9341_DrawLine(0, 200, 239, 200);
    35. ILI9341_DrawLine(0, 300, 239, 300);
    36. LCD_SetTextColor(BLUE);
    37. ILI9341_DrawLine(20, 176, 20, 319);
    38. ILI9341_DrawLine(220, 176, 220, 319);
    39. HAL_Delay(2000);
    40. ILI9341_Clear(0, 16 * 11, LCD_X_LENGTH, LCD_Y_LENGTH - 16 * 11); /* 清中下屏,显示全黑 */
    41. /*画矩形*/
    42. LCD_ClearLine(LINE(5)); /* LINE4 = 32*5 = 160,清除单行文字 */
    43. LCD_SetTextColor(BLUE);
    44. ILI9341_DispStringLine_EN_CH(LINE(5), "画矩形:");
    45. LCD_SetTextColor(RED);
    46. ILI9341_DrawRectangle(0, 176, 240, 144, 1);
    47. LCD_SetTextColor(YELLOW);
    48. ILI9341_DrawRectangle(80, 200, 120, 100, 0);
    49. LCD_SetTextColor(BLUE);
    50. ILI9341_DrawRectangle(120, 190, 100, 50, 1);
    51. HAL_Delay(2000);
    52. ILI9341_Clear(0, 16 * 11, LCD_X_LENGTH, LCD_Y_LENGTH - 16 * 11); /* 清中下屏,显示全黑 */
    53. /* 画圆 */
    54. LCD_ClearLine(LINE(5)); /* LINE4 = 32*5 = 160,清除单行文字 */
    55. LCD_SetTextColor(BLUE);
    56. ILI9341_DispStringLine_EN_CH(LINE(5), "画圆:");
    57. LCD_SetTextColor(RED);
    58. ILI9341_DrawCircle(120, 250, 50, 0);
    59. LCD_SetTextColor(YELLOW);
    60. ILI9341_DrawCircle(120, 250, 30, 1);
    61. LCD_SetTextColor(BLUE);
    62. ILI9341_DrawCircle(120, 250, 10, 1);
    63. HAL_Delay(2000);
    64. ILI9341_Clear(0, 16 * 11, LCD_X_LENGTH, LCD_Y_LENGTH - 16 * 11); /* 清中下屏,显示全黑 */
    65. }

    实验现象

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

    缩放字模

    缩放字模
    1. #define ZOOMMAXBUFF 16384
    2. uint8_t zoomBuff[ZOOMMAXBUFF] = {0}; //用于缩放的缓存,最大支持到128*128
    3. uint8_t zoomTempBuff[1024] = {0};
    4. /**
    5. * @brief 缩放字模,缩放后的字模由1个像素点由8个数据位来表示
    6. 0x01表示笔迹,0x00表示空白区
    7. * @param in_width :原始字符宽度
    8. * @param in_heig :原始字符高度
    9. * @param out_width :缩放后的字符宽度
    10. * @param out_heig:缩放后的字符高度
    11. * @param in_ptr :字库输入指针 注意:1pixel 1bit
    12. * @param out_ptr :缩放后的字符输出指针 注意: 1pixel 8bit
    13. * out_ptr实际上没有正常输出,改成了直接输出到全局指针zoomBuff中
    14. * @param en_cn :0为英文,1为中文
    15. * @retval 无
    16. */
    17. void ILI9341_zoomChar(uint16_t in_width, //原始字符宽度
    18. uint16_t in_heig, //原始字符高度
    19. uint16_t out_width, //缩放后的字符宽度
    20. uint16_t out_heig, //缩放后的字符高度
    21. uint8_t *in_ptr, //字库输入指针 注意:1pixel 1bit
    22. uint8_t *out_ptr, //缩放后的字符输出指针 注意: 1pixel 8bit
    23. uint8_t en_cn) //0为英文,1为中文
    24. {
    25. uint8_t *pts, *ots;
    26. //根据源字模及目标字模大小,设定运算比例因子,左移16是为了把浮点运算转成定点运算
    27. unsigned int xrIntFloat_16 = (in_width << 16) / out_width + 1;
    28. unsigned int yrIntFloat_16 = (in_heig << 16) / out_heig + 1;
    29. unsigned int srcy_16 = 0;
    30. unsigned int y, x;
    31. uint8_t *pSrcLine;
    32. uint16_t byteCount, bitCount;
    33. //检查参数是否合法
    34. if (in_width >= 32)
    35. {
    36. return; //字库不允许超过32像素
    37. }
    38. if (in_width * in_heig == 0)
    39. {
    40. return;
    41. }
    42. if (in_width * in_heig >= 1024)
    43. {
    44. return; //限制输入最大 32*32
    45. }
    46. if (out_width * out_heig == 0)
    47. {
    48. return;
    49. }
    50. if (out_width * out_heig >= ZOOMMAXBUFF)
    51. {
    52. return; //限制最大缩放 128*128
    53. }
    54. pts = (uint8_t *)&zoomTempBuff;
    55. //为方便运算,字库的数据由1 pixel/1bit 映射到1pixel/8bit
    56. //0x01表示笔迹,0x00表示空白区
    57. if (en_cn == 0x00) //英文
    58. {
    59. //英文和中文字库上下边界不对,可在此处调整。需要注意tempBuff防止溢出
    60. for (byteCount = 0; byteCount < in_heig * in_width / 8; byteCount++)
    61. {
    62. for (bitCount = 0; bitCount < 8; bitCount++)
    63. {
    64. //把源字模数据由位映射到字节
    65. //in_ptr里bitX为1,则pts里整个字节值为1
    66. //in_ptr里bitX为0,则pts里整个字节值为0
    67. *pts++ = (in_ptr[byteCount] & (0x80 >> bitCount)) ? 1 : 0;
    68. }
    69. }
    70. }
    71. else //中文
    72. {
    73. for (byteCount = 0; byteCount < in_heig * in_width / 8; byteCount++)
    74. {
    75. for (bitCount = 0; bitCount < 8; bitCount++)
    76. {
    77. //把源字模数据由位映射到字节
    78. //in_ptr里bitX为1,则pts里整个字节值为1
    79. //in_ptr里bitX为0,则pts里整个字节值为0
    80. *pts++ = (in_ptr[byteCount] & (0x80 >> bitCount)) ? 1 : 0;
    81. }
    82. }
    83. }
    84. //zoom过程
    85. pts = (uint8_t *)&zoomTempBuff; //映射后的源数据指针
    86. ots = (uint8_t *)&zoomBuff; //输出数据的指针
    87. for (y = 0; y < out_heig; y++) /*行遍历*/
    88. {
    89. unsigned int srcx_16 = 0;
    90. pSrcLine = pts + in_width * (srcy_16 >> 16);
    91. for (x = 0; x < out_width; x++) /*行内像素遍历*/
    92. {
    93. ots[x] = pSrcLine[srcx_16 >> 16]; //把源字模数据复制到目标指针中
    94. srcx_16 += xrIntFloat_16; //按比例偏移源像素点
    95. }
    96. srcy_16 += yrIntFloat_16; //按比例偏移源像素点
    97. ots += out_width;
    98. }
    99. /*!!!缩放后的字模数据直接存储到全局指针zoomBuff里了*/
    100. out_ptr = (uint8_t *)&zoomBuff; //out_ptr没有正确传出,后面调用直接改成了全局变量指针!
    101. /*实际中如果使用out_ptr不需要下面这一句!!!只是因为out_ptr没有使用,会导致warning。强迫症*/
    102. out_ptr++;
    103. }

    缩放字模后显示字符
    1. /**
    2. * @brief 利用缩放后的字模显示字符
    3. * @param Xpos :字符显示位置x
    4. * @param Ypos :字符显示位置y
    5. * @param Font_width :字符宽度
    6. * @param Font_Heig:字符高度
    7. * @param c :要显示的字模数据
    8. * @param DrawModel :是否反色显示
    9. * @retval 无
    10. */
    11. void ILI9341_DrawChar_Ex(uint16_t usX, //字符显示位置x
    12. uint16_t usY, //字符显示位置y
    13. uint16_t Font_width, //字符宽度
    14. uint16_t Font_Height, //字符高度
    15. uint8_t *c, //字模数据
    16. uint16_t DrawModel) //是否反色显示
    17. {
    18. uint32_t index = 0, counter = 0;
    19. //设置显示窗口
    20. ILI9341_OpenWindow(usX, usY, Font_width, Font_Height);
    21. ILI9341_Write_Cmd(CMD_SetPixel);
    22. //按字节读取字模数据
    23. //由于前面直接设置了显示窗口,显示数据会自动换行
    24. for (index = 0; index < Font_Height; index++)
    25. {
    26. //一位一位处理要显示的颜色
    27. for (counter = 0; counter < Font_width; counter++)
    28. {
    29. //缩放后的字模数据,以一个字节表示一个像素位
    30. //整个字节值为1表示该像素为笔迹
    31. //整个字节值为0表示该像素为背景
    32. if (*c++ == DrawModel)
    33. {
    34. ILI9341_Write_Data(CurrentBackColor);
    35. }
    36. else
    37. {
    38. ILI9341_Write_Data(CurrentTextColor);
    39. }
    40. }
    41. }
    42. }

    缩放字符后显示字符串
    1. /**
    2. * @brief 利用缩放后的字模显示字符串
    3. * @param Xpos :字符显示位置x
    4. * @param Ypos :字符显示位置y
    5. * @param Font_width :字符宽度,英文字符在此基础上/2。注意为偶数
    6. * @param Font_Heig:字符高度,注意为偶数
    7. * @param c :要显示的字符串
    8. * @param DrawModel :是否反色显示
    9. * @retval 无
    10. */
    11. void ILI9341_DisplayStringEx(uint16_t x, //字符显示位置x
    12. uint16_t y, //字符显示位置y
    13. uint16_t Font_width, //要显示的字体宽度,英文字符在此基础上/2。注意为偶数
    14. uint16_t Font_Height, //要显示的字体高度,注意为偶数
    15. uint8_t *ptr, //显示的字符内容
    16. uint16_t DrawModel) //是否反色显示
    17. {
    18. uint16_t Charwidth = Font_width; //默认为Font_width,英文宽度为中文宽度的一半
    19. uint8_t *psr;
    20. uint8_t Ascii; //英文
    21. uint16_t usCh; //中文
    22. uint8_t ucBuffer [ WIDTH_CH_CHAR * HEIGHT_CH_CHAR / 8 ];
    23. while (*ptr != '\0')
    24. {
    25. /****处理换行*****/
    26. if ((x - ILI9341_DispWindow_X_Star + Charwidth) > LCD_X_LENGTH)
    27. {
    28. x = ILI9341_DispWindow_X_Star;
    29. y += Font_Height;
    30. }
    31. if ((y - ILI9341_DispWindow_Y_Star + Font_Height) > LCD_Y_LENGTH)
    32. {
    33. x = ILI9341_DispWindow_X_Star;
    34. y = ILI9341_DispWindow_Y_Star;
    35. }
    36. if (*ptr > 0x80) //如果是中文
    37. {
    38. Charwidth = Font_width;
    39. usCh = * (uint16_t *) ptr;
    40. usCh = (usCh << 8) + (usCh >> 8);
    41. GetGBKCode(ucBuffer, usCh); //取字模数据
    42. //缩放字模数据,源字模为16*16
    43. ILI9341_zoomChar(WIDTH_CH_CHAR, HEIGHT_CH_CHAR, Charwidth, Font_Height, (uint8_t *)&ucBuffer, psr, 1);
    44. //显示单个字符
    45. ILI9341_DrawChar_Ex(x, y, Charwidth, Font_Height, (uint8_t *)&zoomBuff, DrawModel);
    46. x += Charwidth;
    47. ptr += 2;
    48. }
    49. else
    50. {
    51. Charwidth = Font_width / 2;
    52. Ascii = *ptr - 32;
    53. //使用16*24字体缩放字模数据
    54. ILI9341_zoomChar(16, 24, Charwidth, Font_Height,
    55. (uint8_t *)&Font16x24.table[Ascii * Font16x24.Height * Font16x24.Width / 8], psr, 0);
    56. //显示单个字符
    57. ILI9341_DrawChar_Ex(x, y, Charwidth, Font_Height, (uint8_t *)&zoomBuff, DrawModel);
    58. x += Charwidth;
    59. ptr++;
    60. }
    61. }
    62. }
    63. /**
    64. * @brief 利用缩放后的字模显示字符串(沿Y轴方向)
    65. * @param Xpos :字符显示位置x
    66. * @param Ypos :字符显示位置y
    67. * @param Font_width :字符宽度,英文字符在此基础上/2。注意为偶数
    68. * @param Font_Heig:字符高度,注意为偶数
    69. * @param c :要显示的字符串
    70. * @param DrawModel :是否反色显示
    71. * @retval 无
    72. */
    73. void ILI9341_DisplayStringEx_YDir(uint16_t x, //字符显示位置x
    74. uint16_t y, //字符显示位置y
    75. uint16_t Font_width, //要显示的字体宽度,英文字符在此基础上/2。注意为偶数
    76. uint16_t Font_Height, //要显示的字体高度,注意为偶数
    77. uint8_t *ptr, //显示的字符内容
    78. uint16_t DrawModel) //是否反色显示
    79. {
    80. uint16_t Charwidth = Font_width; //默认为Font_width,英文宽度为中文宽度的一半
    81. uint8_t *psr;
    82. uint8_t Ascii; //英文
    83. uint16_t usCh; //中文
    84. uint8_t ucBuffer [ WIDTH_CH_CHAR * HEIGHT_CH_CHAR / 8 ];
    85. while (*ptr != '\0')
    86. {
    87. //统一使用汉字的宽高来计算换行
    88. if ((y - ILI9341_DispWindow_X_Star + Font_width) > LCD_X_LENGTH)
    89. {
    90. y = ILI9341_DispWindow_X_Star;
    91. x += Font_width;
    92. }
    93. if ((x - ILI9341_DispWindow_Y_Star + Font_Height) > LCD_Y_LENGTH)
    94. {
    95. y = ILI9341_DispWindow_X_Star;
    96. x = ILI9341_DispWindow_Y_Star;
    97. }
    98. if (*ptr > 0x80) //如果是中文
    99. {
    100. Charwidth = Font_width;
    101. usCh = * (uint16_t *) ptr;
    102. usCh = (usCh << 8) + (usCh >> 8);
    103. GetGBKCode(ucBuffer, usCh); //取字模数据
    104. //缩放字模数据,源字模为16*16
    105. ILI9341_zoomChar(WIDTH_CH_CHAR, HEIGHT_CH_CHAR, Charwidth, Font_Height, (uint8_t *)&ucBuffer, psr, 1);
    106. //显示单个字符
    107. ILI9341_DrawChar_Ex(x, y, Charwidth, Font_Height, (uint8_t *)&zoomBuff, DrawModel);
    108. y += Font_Height;
    109. ptr += 2;
    110. }
    111. else
    112. {
    113. Charwidth = Font_width / 2;
    114. Ascii = *ptr - 32;
    115. //使用16*24字体缩放字模数据
    116. ILI9341_zoomChar(16, 24, Charwidth, Font_Height,
    117. (uint8_t *)&Font16x24.table[Ascii * Font16x24.Height * Font16x24.Width / 8], psr, 0);
    118. //显示单个字符
    119. ILI9341_DrawChar_Ex(x, y, Charwidth, Font_Height, (uint8_t *)&zoomBuff, DrawModel);
    120. y += Font_Height;
    121. ptr++;
    122. }
    123. }
    124. }

    实验测试

    1. /*******************中文********** 在显示屏上显示的字符大小 ***************************/
    2. #define WIDTH_CH_CHAR 16 //中文字符宽度
    3. #define HEIGHT_CH_CHAR 16 //中文字符高度
    4. /*用于测试各种液晶的函数*/
    5. void LCD_Test(void)
    6. {
    7. /*演示显示变量*/
    8. static uint8_t testCNT = 0;
    9. static float testFloatCNT = 0;
    10. char dispBuff[100];
    11. char *pStr = 0;
    12. testCNT++;
    13. testFloatCNT += 0.1;
    14. LCD_SetFont(&Font8x16); // 设置字体类型:8*16,16*24,24*32
    15. LCD_SetColors(RED, BLACK); // 设置前景和背景色
    16. ILI9341_Clear(0, 0, LCD_X_LENGTH, LCD_Y_LENGTH); // 清屏,显示全黑
    17. //显示指定大小的字符
    18. ILI9341_DisplayStringEx(0, 0, 48, 48, (uint8_t *)"博客:", 0);
    19. ILI9341_DisplayStringEx(120, 0, 24, 24, (uint8_t *)"couvrir", 0);
    20. /********显示字符串示例*******/
    21. ILI9341_DispString_EN_CH (120, 24, "洪荒猛兽");
    22. /********显示变量示例*******/
    23. LCD_SetTextColor(GREEN);
    24. /*使用c标准库把变量转化成字符串*/
    25. sprintf(dispBuff, "显示变量: %d ", testCNT);
    26. LCD_ClearLine(LINE(3));
    27. ILI9341_DispStringLine_EN_CH(LINE(3), dispBuff);
    28. sprintf(dispBuff,"显示浮点型变量: %f ",testFloatCNT);
    29. LCD_ClearLine(LINE(4));
    30. ILI9341_DispStringLine_EN_CH(LINE(4), dispBuff);
    31. sprintf(dispBuff,"浮点型(保留2位小数): %.2f ",testFloatCNT);
    32. LCD_ClearLine(LINE(5));
    33. ILI9341_DispStringLine_EN_CH(LINE(5), dispBuff);
    34. /********居中显示示例*******/
    35. LCD_SetTextColor(YELLOW);
    36. pStr = "插入2个英文空格示例";
    37. //使用 %*c 在字符串前插入指定个数的英文空格
    38. sprintf(dispBuff, "%*c%s", 2, ' ', pStr);
    39. LCD_ClearLine(LINE(6));
    40. ILI9341_DispStringLine_EN_CH(LINE(6), dispBuff);
    41. ILI9341_DispStringLine_EN_CH(LINE(7), "居中示例:");
    42. pStr = "ABCDEF";
    43. //居中时,要插入的空格个数 = (液晶宽度/单个字体宽度 - 字符串长度)/2
    44. sprintf(dispBuff, "%*c%s", ( (LCD_X_LENGTH/(((sFONT *)LCD_GetFont())->Width) ) - strlen(pStr))/2, ' ', pStr);
    45. LCD_ClearLine(LINE(8));
    46. ILI9341_DispStringLine_EN_CH(LINE(8),dispBuff);
    47. pStr = "中文居中示例";
    48. //居中时,要插入的空格个数 = (液晶宽度/字体宽度 - 字符串长度)/2
    49. //strlen计算长度时,一个中文等于2个字节,即2个英文字符,而且插入的是英文空格
    50. //所以用(WIDTH_CH_CHAR/2)来计算字体宽度
    51. sprintf(dispBuff, "%*c%s", ( LCD_X_LENGTH/(WIDTH_CH_CHAR/2) - strlen(pStr))/2, ' ', pStr);
    52. LCD_ClearLine(LINE(9));
    53. ILI9341_DispStringLine_EN_CH(LINE(9),dispBuff);
    54. /*******显示图形示例******/
    55. LCD_SetFont(&Font24x32);
    56. /* 画直线 */
    57. LCD_ClearLine(LINE(5)); /* LINE4 = 32*5 = 160,清除单行文字 */
    58. LCD_SetTextColor(BLUE);
    59. ILI9341_DispStringLine_EN_CH(LINE(5), "画直线:");
    60. LCD_SetTextColor(RED);
    61. ILI9341_DrawLine(0, 176, 239, 319);
    62. ILI9341_DrawLine(239, 176, 0, 319);
    63. LCD_SetTextColor(YELLOW);
    64. ILI9341_DrawLine(0, 200, 239, 200);
    65. ILI9341_DrawLine(0, 300, 239, 300);
    66. LCD_SetTextColor(BLUE);
    67. ILI9341_DrawLine(20, 176, 20, 319);
    68. ILI9341_DrawLine(220, 176, 220, 319);
    69. HAL_Delay(2000);
    70. ILI9341_Clear(0, 16 * 11, LCD_X_LENGTH, LCD_Y_LENGTH - 16 * 11); /* 清中下屏,显示全黑 */
    71. /*画矩形*/
    72. LCD_ClearLine(LINE(5)); /* LINE4 = 32*5 = 160,清除单行文字 */
    73. LCD_SetTextColor(BLUE);
    74. ILI9341_DispStringLine_EN_CH(LINE(5), "画矩形:");
    75. LCD_SetTextColor(RED);
    76. ILI9341_DrawRectangle(0, 176, 240, 144, 1);
    77. LCD_SetTextColor(YELLOW);
    78. ILI9341_DrawRectangle(80, 200, 120, 100, 0);
    79. LCD_SetTextColor(BLUE);
    80. ILI9341_DrawRectangle(120, 190, 100, 50, 1);
    81. HAL_Delay(2000);
    82. ILI9341_Clear(0, 16 * 11, LCD_X_LENGTH, LCD_Y_LENGTH - 16 * 11); /* 清中下屏,显示全黑 */
    83. /* 画圆 */
    84. LCD_ClearLine(LINE(5)); /* LINE4 = 32*5 = 160,清除单行文字 */
    85. LCD_SetTextColor(BLUE);
    86. ILI9341_DispStringLine_EN_CH(LINE(5), "画圆:");
    87. LCD_SetTextColor(RED);
    88. ILI9341_DrawCircle(120, 250, 50, 0);
    89. LCD_SetTextColor(YELLOW);
    90. ILI9341_DrawCircle(120, 250, 30, 1);
    91. LCD_SetTextColor(BLUE);
    92. ILI9341_DrawCircle(120, 250, 10, 1);
    93. HAL_Delay(2000);
    94. ILI9341_Clear(0, 16 * 11, LCD_X_LENGTH, LCD_Y_LENGTH - 16 * 11); /* 清中下屏,显示全黑 */
    95. }

    实验现象

  • 相关阅读:
    qt使用QCustomplot绘制cpu和内存使用率图
    flutter在导航栏处实现对两个列表的点击事件
    著名书法家傅成洪在香港第八届“一带一路”高峰论坛上展示艺术与合作的融合
    C++:符号的作用【::(命名空间、类、结构体作用域限定符)】【:(类的继承、初始化列表、)】【A.B(A必须为对象或结构体)】【A->B(箭头左边必须为指针),A只能是指向类、结构体、联合体的指针】
    C++--智能指针--1123
    接口自动化入门:Requests请求头设置详解!
    SpringBoot 学习(九)Redis
    【Android-Jetpack进阶】3、ViewModel 视图模型:使用、源码解析
    【编译原理】实验一 词法分析器(Java实现)
    JAVA:实现ThreeSum三数和问题算法(附完整源码)
  • 原文地址:https://blog.csdn.net/weixin_47077788/article/details/133982584