STM32 LCD中英文混合显示:从字模生成到GBK编码实战

任意大小全字库生成和使用方法(GBK编码) 通过U盘将字库写入flash,通过emwin的方式显示中英文 阅读详情

1. STM32 LCD中英文混合显示的核心挑战

在嵌入式系统开发中,LCD显示是必不可少的人机交互手段。对于英文显示,由于ASCII字符集只有128个字符,处理起来相对简单。但当我们遇到中文显示时,情况就变得复杂多了。中文汉字数量庞大,GB2312标准就包含6763个汉字,而GBK编码更是扩展到了21003个汉字字符。

我刚开始做STM32项目时,最头疼的就是中英文混合显示问题。直接使用位图字体吧,存储空间根本不够用;用矢量字体吧,STM32F103的性能又吃不消。经过多个项目的实践,我发现最实用的解决方案就是:GBK编码 + 外部存储器字库 + 字模提取。

这种方案的优势很明显:显示速度快、占用内存小、支持字符全面。但实现起来有几个技术难点需要攻克:GBK编码的理解、字模数据的提取、存储和读取,以及最终在LCD上的渲染显示。下面我就把这些年积累的经验和踩过的坑跟大家分享一下。

2. GBK编码原理深度解析

GBK编码是我们实现中英文混合显示的基础,必须彻底理解它的工作原理。GBK全称《汉字内码扩展规范》,是在GB2312-80标准基础上的扩展,完全兼容GB2312。

2.1 GBK编码结构

GBK采用双字节编码方案,每个汉字由两个字节组成。编码范围分为以下几个区域:

  • ASCII兼容区:0x00-0x7F,与ASCII完全一致
  • GBK/1区:0x8140-0xA0FE,收录GB 13000.1-93中的汉字
  • GBK/2区:0xA140-0xA7A0,收录GB 13000.1-93中的汉字
  • GBK/3区:0xA840-0xA9A0,收录GB 13000.1-93中的汉字
  • 用户自定义区:0xAA40-0xAFFE,供用户自定义字符

在实际项目中,我通常这样判断字符类型:

// 判断字符类型函数
uint8_t GetCharType(uint8_t *pChar)
{
    if (pChar[0] < 0x80) {
        return CHAR_TYPE_ASCII;  // ASCII字符
    } else if (pChar[0] >= 0x81 && pChar[0] <= 0xFE && 
               pChar[1] >= 0x40 && pChar[1] <= 0xFE) {
        return CHAR_TYPE_GBK;    // GBK汉字
    } else {
        return CHAR_TYPE_INVALID; // 无效字符
    }
}

2.2 GBK编码查询机制

GBK编码的查询是个关键技术点。由于GBK不是简单的线性编码,我们需要通过编码值计算出字模在字库中的位置。以16x16点阵字库为例,每个汉字占用32字节,计算偏移量的公式如下:

// 计算GBK字模偏移量
uint32_t GetGBKOffset(uint8_t *pGBK)
{
    uint32_t offset = 0;
    uint16_t highByte = pGBK[0];
    uint16_t lowByte = pGBK[1];
    
    if (highByte < 0x81 || highByte > 0xFE || 
        lowByte < 0x40 || lowByte > 0xFE) {
        return 0xFFFFFFFF;  // 无效编码
    }
    
    // 计算区位码
    uint16_t qu = highByte - 0x81;  // 区码
    uint16_t wei = lowByte - 0x40;   // 位码
    
    // 计算偏移量
    offset = (qu * 190 + wei) * 32;  // 每个汉字32字节
    
    return offset;
}

这里有个坑需要特别注意:GBK编码的第二个字节从0x40开始,而不是0x00。这是因为0x00-0x3F这些值有特殊用途,需要避开。

3. 字模生成实战:PCtoLCD2002高级用法

PCtoLCD2002是嵌入式开发中最常用的字模生成工具,但很多人只用了它的基础功能。下面我分享一些高级使用技巧。

3.1 优化字模设置

打开PCtoLCD2002,点击"选项"进行配置:

  1. 字模设置:选择"阴码"、"逐行式"、"顺向"(C51格式)
  2. 取模方式:16x16点阵时选择"横向取模"
  3. 输出格式:选择"C51"格式,方便直接嵌入代码
  4. 自定义格式:可以修改前缀、后缀,适应不同LCD驱动

我推荐的16x16点阵设置参数:

  • 点阵格式:阴码(亮点为1,暗点为0)
  • 取模方向:逐行取模
  • 输出顺序:顺向(高位在前)
  • 每行数据前缀:0x
  • 数据后缀:,(逗号)

3.2 批量生成技巧

如果需要生成整个字库,不要一个个字符操作:

  1. 点击"字符"->"批量生成"
  2. 输入需要生成的字符范围
  3. 设置输出文件名
  4. 选择"连续输出",这样所有字模会保存在一个文件中

对于大型项目,我建议将字库存放在外部SPI Flash中,这样可以节省大量的MCU内部Flash空间。生成字库后,使用编程器或者STM32的ISP功能将字库文件烧录到外部Flash的指定地址。

3.3 字模验证方法

生成字模后一定要验证是否正确。我常用的验证方法:

// 字模测试验证函数
void TestFontData(uint8_t *fontData)
{
    for (int i = 0; i < 16; i++) {  // 16行
        uint16_t rowData = (fontData[i*2] << 8) | fontData[i*2+1];
        for (int j = 0; j < 16; j++) {  // 16列
            if (rowData & (0x8000 >> j)) {
                printf("■");  // 有点
            } else {
                printf("□");  // 无点
            }
        }
        printf("\n");
    }
}

这个函数可以在串口助手上模拟显示汉字,确保字模数据正确后再烧录到硬件中。

4. STM32硬件驱动设计

4.1 LCD驱动层实现

LCD驱动是基础,必须稳定可靠。以ILI9341为例,首先实现基本的读写函数:

// ILI9341写命令函数
void ILI9341_Write_Cmd(uint8_t cmd)
{
    LCD_RS_LOW();  // RS=0,写命令
    LCD_CS_LOW();
    SPI_Write_Byte(cmd);
    LCD_CS_HIGH();
}

// ILI9341写数据函数
void ILI9341_Write_Data(uint8_t data)
{
    LCD_RS_HIGH(); // RS=1,写数据
    LCD_CS_LOW();
    SPI_Write_Byte(data);
    LCD_CS_HIGH();
}

// 设置显示窗口
void ILI9341_SetWindow(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2)
{
    ILI9341_Write_Cmd(0x2A);  // 列地址设置
    ILI9341_Write_Data(x1 >> 8);
    ILI9341_Write_Data(x1 & 0xFF);
    ILI9341_Write_Data(x2 >> 8);
    ILI9341_Write_Data(x2 & 0xFF);
    
    ILI9341_Write_Cmd(0x2B);  // 行地址设置
    ILI9341_Write_Data(y1 >> 8);
    ILI9341_Write_Data(y1 & 0xFF);
    ILI9341_Write_Data(y2 >> 8);
    ILI9341_Write_Data(y2 & 0xFF);
    
    ILI9341_Write_Cmd(0x2C);  // 开始写入显存
}

4.2 字库存储方案

根据项目需求选择不同的字库存储方案:

方案一:内部Flash存储(适合小字库)

// 内部Flash存储字模数据
const uint8_t Font16x16[][32] = {
    {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
     0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 空字符
    // 更多字模数据...
};

方案二:外部SPI Flash存储(推荐)

// 从SPI Flash读取字模数据
void ReadFontFromSPIFlash(uint32_t offset, uint8_t *buffer, uint32_t size)
{
    SPI_FLASH_CS_LOW();
    SPI_Write_Byte(0x03);  // 读命令
    SPI_Write_Byte((offset >> 16) & 0xFF);
    SPI_Write_Byte((offset >> 8) & 0xFF);
    SPI_Write_Byte(offset & 0xFF);
    
    for (uint32_t i = 0; i < size; i++) {
        buffer[i] = SPI_Read_Byte();
    }
    SPI_FLASH_CS_HIGH();
}

方案三:SD卡存储(适合超大字库)

// 从SD卡读取字模数据
FRESULT ReadFontFromSDCard(uint32_t offset, uint8_t *buffer, uint32_t size)
{
    FRESULT res;
    UINT bytesRead;
    
    res = f_lseek(&fontFile, offset);  // 定位到字模位置
    if (res != FR_OK) return res;
    
    res = f_read(&fontFile, buffer, size, &bytesRead);  // 读取字模数据
    return res;
}

在实际项目中,我最推荐方案二(外部SPI Flash),因为它在成本、速度和容量之间取得了很好的平衡。

5. 中英文混合显示算法

5.1 字符显示核心函数

实现中英文混合显示的关键是一个智能的字符显示函数,能够自动识别字符类型并选择相应的显示方式:

// 显示一个字符(自动识别中英文)
void LCD_DisplayChar(uint16_t x, uint16_t y, uint8_t *pChar, uint8_t type)
{
    if (type == CHAR_TYPE_ASCII) {
        // 显示ASCII字符
        LCD_DrawASCII(x, y, pChar[0]);
        x += ASCII_WIDTH;  // ASCII字符宽度
    } else if (type == CHAR_TYPE_GBK) {
        // 显示GBK汉字
        LCD_DrawGBK(x, y, pChar);
        x += GBK_WIDTH;   // 汉字宽度
    }
}

// 显示字符串函数
void LCD_DisplayString(uint16_t x, uint16_t y, uint8_t *pStr)
{
    uint16_t currentX = x;
    uint16_t currentY = y;
    
    while (*pStr != '\0') {
        // 判断字符类型
        uint8_t charType = GetCharType(pStr);
        
        // 检查是否需要换行
        if (currentX + (charType == CHAR_TYPE_ASCII ? ASCII_WIDTH : GBK_WIDTH) > LCD_WIDTH) {
            currentX = 0;
            currentY += (charType == CHAR_TYPE_ASCII ? ASCII_HEIGHT : GBK_HEIGHT);
            
            // 检查是否超出屏幕底部
            if (currentY >= LCD_HEIGHT) {
                break;  // 超出屏幕,停止显示
            }
        }
        
        // 显示字符
        LCD_DisplayChar(currentX, currentY, pStr, charType);
        
        // 更新位置
        currentX += (charType == CHAR_TYPE_ASCII ? ASCII_WIDTH : GBK_WIDTH);
        
        // 移动指针
        pStr += (charType == CHAR_TYPE_ASCII ? 1 : 2);
    }
}

5.2 文本渲染优化

文本渲染的性能优化很重要,特别是在低端STM32芯片上:

优化技巧1:使用显存缓存

// 使用缓存减少SPI访问次数
void LCD_DrawGBK_Optimized(uint16_t x, uint16_t y, uint8_t *pGBK)
{
    uint8_t fontData[32];
    uint32_t offset = GetGBKOffset(pGBK);
    
    // 从外部Flash读取字模数据
    ReadFontFromSPIFlash(offset, fontData, 32);
    
    // 设置显示窗口
    ILI9341_SetWindow(x, y, x + 15, y + 15);
    
    // 一次性发送所有像素数据
    LCD_CS_LOW();
    LCD_RS_HIGH();
    
    for (int i = 0; i < 32; i += 2) {
        uint16_t rowData = (fontData[i] << 8) | fontData[i+1];
        for (int j = 0; j < 16; j++) {
            if (rowData & (0x8000 >> j)) {
                SPI_Write_Byte(CurrentTextColor >> 8);
                SPI_Write_Byte(CurrentTextColor & 0xFF);
            } else {
                SPI_Write_Byte(CurrentBackColor >> 8);
                SPI_Write_Byte(CurrentBackColor & 0xFF);
            }
        }
    }
    
    LCD_CS_HIGH();
}

优化技巧2:使用DMA传输 对于支持DMA的STM32型号,可以使用DMA来加速数据传输:

// 使用DMA传输显示数据
void LCD_DrawGBK_DMA(uint16_t x, uint16_t y, uint8_t *pGBK)
{
    uint8_t fontData[32];
    uint32_t offset = GetGBKOffset(pGBK);
    
    // 从外部Flash读取字模数据
    ReadFontFromSPIFlash(offset, fontData, 32);
    
    // 设置显示窗口
    ILI9341_SetWindow(x, y, x + 15, y + 15);
    
    // 准备DMA传输
    LCD_RS_HIGH();
    LCD_CS_LOW();
    
    // 启动DMA传输
    SPI_DMA_Transfer(fontData, 32);
    
    // 等待DMA传输完成
    while (SPI_DMA_IsBusy());
    
    LCD_CS_HIGH();
}

6. 实际项目应用案例

6.1 工业控制系统界面

在一个工业控制项目中,我需要显示中英文混合的监控界面。界面包含设备状态、参数设置和报警信息。由于涉及大量中文显示,我采用了以下方案:

  1. 字库选择:16x16点阵中文字库 + 8x16英文字库
  2. 存储方案:外部W25Q64 SPI Flash存储完整GBK字库
  3. 显示优化:使用局部刷新技术,只更新变化的文本区域

关键实现代码:

// 工业监控界面显示
void DisplayMonitorUI(void)
{
    // 显示标题
    LCD_DisplayString(10, 10, (uint8_t *)"设备监控系统");
    LCD_DisplayString(10, 30, (uint8_t *)"Equipment Monitor System");
    
    // 显示设备状态
    LCD_DisplayString(10, 60, (uint8_t *)"状态: ");
    if (deviceStatus == STATUS_NORMAL) {
        LCD_DisplayString(60, 60, (uint8_t *)"正常运行");
    } else {
        LCD_DisplayString(60, 60, (uint8_t *)"异常报警");
    }
    
    // 显示实时数据
    char tempStr[20];
    sprintf(tempStr, "温度: %.1f℃", currentTemperature);
    LCD_DisplayString(10, 90, (uint8_t *)tempStr);
    
    sprintf(tempStr, "压力: %.2fMPa", currentPressure);
    LCD_DisplayString(10, 110, (uint8_t *)tempStr);
}

6.2 多语言支持系统

另一个项目需要支持中文和英文两种语言界面。我设计了一个简单的多语言系统:

// 语言枚举
typedef enum {
    LANG_CHINESE,
    LANG_ENGLISH
} LanguageType;

// 语言包结构
typedef struct {
    const uint8_t *title;
    const uint8_t *status;
    const uint8_t *temperature;
    const uint8_t *pressure;
} LanguagePack;

// 中文语言包
const LanguagePack ChineseLanguage = {
    "设备监控系统",
    "状态",
    "温度",
    "压力"
};

// 英文语言包
const LanguagePack EnglishLanguage = {
    "Equipment Monitor",
    "Status",
    "Temperature",
    "Pressure"
};

// 当前语言包指针
const LanguagePack *currentLanguage = &ChineseLanguage;

// 设置语言
void SetLanguage(LanguageType lang)
{
    switch (lang) {
        case LANG_CHINESE:
            currentLanguage = &ChineseLanguage;
            break;
        case LANG_ENGLISH:
            currentLanguage = &EnglishLanguage;
            break;
    }
}

// 多语言显示函数
void DisplayMultiLanguageUI(void)
{
    LCD_DisplayString(10, 10, (uint8_t *)currentLanguage->title);
    LCD_DisplayString(10, 40, (uint8_t *)currentLanguage->status);
    
    char tempStr[20];
    sprintf(tempStr, "%s: %.1f℃", currentLanguage->temperature, currentTemperature);
    LCD_DisplayString(10, 70, (uint8_t *)tempStr);
}

这种设计使得语言切换变得非常简单,只需要调用SetLanguage函数即可切换整个界面的语言。

7. 常见问题与解决方案

在实际开发中,我遇到过各种各样的问题,这里分享几个典型的案例:

7.1 乱码问题

问题现象:中文显示为乱码或错位 解决方案:

  1. 检查字模生成工具的设置,确保取模方式与代码解析方式一致
  2. 验证GBK编码是否正确,特别是高低字节顺序
  3. 检查字库存储地址偏移计算是否正确
// 字模验证函数
void VerifyFontData(uint8_t *pGBK)
{
    uint32_t offset = GetGBKOffset(pGBK);
    uint8_t fontData[32];
    
    // 读取字模数据
    ReadFontFromSPIFlash(offset, fontData, 32);
    
    // 打印字模数据用于调试
    printf("GBK Code: %02X %02X\n", pGBK[0], pGBK[1]);
    printf("Offset: %lu\n", offset);
    for (int i = 0; i < 32; i++) {
        printf("%02X ", fontData[i]);
        if ((i + 1) % 16 == 0) printf("\n");
    }
}

7.2 显示性能问题

问题现象:文本显示速度慢,刷新时有明显闪烁 解决方案:

  1. 使用DMA传输减少CPU开销
  2. 实现局部刷新,只更新变化的文本区域
  3. 使用双缓冲技术减少闪烁
// 局部刷新函数
void PartialRefresh(uint16_t x, uint16_t y, uint16_t width, uint16_t height)
{
    // 设置局部刷新区域
    ILI9341_Write_Cmd(0x30);
    ILI9341_Write_Data(x >> 8);
    ILI9341_Write_Data(x & 0xFF);
    ILI9341_Write_Data((x + width - 1) >> 8);
    ILI9341_Write_Data((x + width - 1) & 0xFF);
    
    ILI9341_Write_Cmd(0x31);
    ILI9341_Write_Data(y >> 8);
    ILI9341_Write_Data(y & 0xFF);
    ILI9341_Write_Data((y + height - 1) >> 8);
    ILI9341_Write_Data((y + height - 1) & 0xFF);
    
    ILI9341_Write_Cmd(0x34);  // 开启局部刷新
}

7.3 内存不足问题

问题现象:程序运行不稳定,经常死机 解决方案:

  1. 将字库存储到外部Flash,减少内部Flash占用
  2. 使用内存池管理动态内存分配
  3. 优化数据结构,减少内存碎片
// 内存池管理
#define FONT_CACHE_SIZE 10

typedef struct {
    uint16_t gbkCode;
    uint8_t fontData[32];
    uint8_t used;
} FontCacheItem;

FontCacheItem fontCache[FONT_CACHE_SIZE];

// 获取字模数据(带缓存)
uint8_t* GetFontDataWithCache(uint8_t *pGBK)
{
    uint16_t code = (pGBK[0] << 8) | pGBK[1];
    
    // 先在缓存中查找
    for (int i = 0; i < FONT_CACHE_SIZE; i++) {
        if (fontCache[i].used && fontCache[i].gbkCode == code) {
            return fontCache[i].fontData;
        }
    }
    
    // 缓存未命中,从Flash读取
    uint32_t offset = GetGBKOffset(pGBK);
    uint8_t *fontData = NULL;
    
    // 查找空闲缓存项
    for (int i = 0; i < FONT_CACHE_SIZE; i++) {
        if (!fontCache[i].used) {
            ReadFontFromSPIFlash(offset, fontCache[i].fontData, 32);
            fontCache[i].gbkCode = code;
            fontCache[i].used = 1;
            fontData = fontCache[i].fontData;
            break;
        }
    }
    
    // 如果缓存已满,替换最久未使用的项
    if (!fontData) {
        // 简单的FIFO替换策略
        static uint8_t replaceIndex = 0;
        ReadFontFromSPIFlash(offset, fontCache[replaceIndex].fontData, 32);
        fontCache[replaceIndex].gbkCode = code;
        fontData = fontCache[replaceIndex].fontData;
        replaceIndex = (replaceIndex + 1) % FONT_CACHE_SIZE;
    }
    
    return fontData;
}

这些解决方案都是我在实际项目中验证过的,能够有效解决常见的显示问题。特别是在资源有限的STM32平台上,合理的内存管理和性能优化至关重要。

通过以上内容,我相信你已经对STM32 LCD中英文混合显示有了全面的了解。从GBK编码原理到字模生成,从硬件驱动到软件优化,每个环节都需要仔细处理和调试。在实际项目中,建议先从简单的ASCII显示开始,逐步增加中文支持,最后实现混合显示功能。

别再手动敲字模了!用PCtoLCD2002为STM32 OLED生成中文字库(附完整代码) 本文详细介绍了如何使用PCtoLCD2002软件为STM32 OLED生成中文字库,并提供了完整的代码实现。通过优化字库存储和显示流程,开发者可以高效地在嵌入式项目中实现中文显示,解决手动取字模的繁琐问题。文章还涵盖了字库存储方案、数据结构设计以及显示性能优化等实用技巧。 阅读详情

相关推荐

告别点阵屏取模烦恼:用PCtoLCD2002为STM32的ST7567屏生成中文字库(附完整代码)

本文详细介绍了如何使用PCtoLCD2002工具为STM32的ST7567驱动12864点阵屏生成中文字库,解决嵌入式开发中的字符显示难题。通过自动化取模、灵活配置和批量处理,开发者可以高效集成中文字库到STM32工程,并附有完整代码示例和高级优化技巧。

weixin_42525551的博客 438

字库生成

PCtoLCD2002.exe 1.    字库的生成 1.1.    字库生成工具PCtoLCD2002.exe   利用PCtoLCD2002.exe可以生成国标汉字库和英文点阵字库二进制文件,同时也可以生成字库头文件。 1.2.    字库生成工具的使用     第一步: 在生成字库时,有如下选项可以配置: 1)点阵格式:阴码 2)取模方式:逐行式 3)取模走向:顺向(高位在前) 4)字

1467

嵌入式LCD字符编码与字模显示原理详解

字符编码是嵌入式人机交互的基础技术概念,本质是建立字符与整数的映射关系,支撑ASCII、GB2312等标准实现文本到二进制的转换;其核心原理在于分层解耦——数值存储→编码解码→字模渲染,确保微控制器能准确驱动LCD显示;技术价值体现在资源可控性、跨语言兼容性与实时性保障,尤其在STM32等MCU平台中,合理选择GB2312等双字节编码可兼顾中文支持与Flash/内存效率;典型应用场景包括工业HMI、智能仪表、物联网终端的中英文混合显示;本文聚焦嵌入式LCD系统中字符编码与点阵字模的协同机制,深入解析GB23

weixin_35749545的博客 74

从零构建STM32 LCD多语言显示引擎:解码GBK与Unicode的嵌入式实践

本文详细介绍如何在STM32平台上构建高效LCD多语言显示引擎,重点解析GBK与Unicode编码原理,提供字库存储优化、内存管理策略及显示引擎架构设计。通过实战案例展示如何实现中英文混合显示,解决嵌入式环境下的资源限制与性能优化问题。

f0g1h2的博客 1085

STM32F103驱动ST7565P LCD12864实现多语言混合显示实战

本文详细介绍了基于STM32F103微控制器驱动ST7565P芯片的LCD12864显示屏,实现多语言混合显示的实战方法。内容涵盖硬件连接、驱动初始化、字符与汉字显示原理、字库制作以及混合显示算法,并提供了调试技巧与常见问题解决方案,帮助开发者快速掌握无字库LCD的图形化界面开发。

coffee的博客 94

从零开始:PCtoLCD2002在嵌入式显示开发中的实战应用

本文详细介绍了PCtoLCD2002取模软件在嵌入式显示开发中的实战应用,包括核心功能解析、开发环境搭建、字库管理方案及显示性能优化技巧。通过具体案例和代码示例,帮助开发者高效实现文字在嵌入式设备上的精准显示,提升开发效率。

weixin_29279153的博客 325

LCD中英文显示(字库和取模)

已知字模是图形数据,而图形在计算机中是由一个个像素点组成的,所以字模实质是一个个像素点数据。为方便处理,我们把字模定义成方块形的像素点阵,且每个像素点只有0和1这两种状态(可以理解为单色图像数据),下图两个宽、高为16x16的像素点阵组成的两个汉字图形,其中的黑色像素点即为文字的笔迹。计算机要表示这样的图形,只需使用16x16个二进制数据位,每个数据位记录一个像素点的状态,把黑色像素点以“1”表示,无色像素点以“0”表示即可。这样的一个汉字图形,使用16x16/8=32个字节来就可以记录下来。

2302_76950368的博客 8112

STM32F4上给GUI换“活字”:FreeType2.13.2移植实战(含字形缓存优化)

本文详细介绍了在STM32F4平台上移植FreeType2.13.2库的实战经验,包括工程准备、源码裁剪、内存管理优化以及高性能渲染引擎的实现。通过多级缓存架构和渲染流水线优化,显著提升了嵌入式GUI的矢量字体渲染性能,适用于多语言支持场景。

weixin_30292843的博客 367

每节课都是一个项目 手把手用STM32打造联网气象站-9-用LCD显示中文英文和图片

一种字体库必须包括字符宽度,字符高度,以及对应ASCII表的地址信息。我们把这些信息放在一起,构建一个结构体。备注上面的typedefstruct_tFont{}sFont这种写法,可以用_tFontfont1这种方式初始化,相当于定义了两种结构体类型,第一种是_tFont,第二种是sFONT,两种可以互换,_tFont就是sFONT,sFONT就是_tFont;如果把_tFont去掉,写成typedefstruct{}sFONT,语法上面也是没有任何问题的。.........

可志嵌入式 3178

嵌入式GUI开发:emWin字体转换与色彩管理实战指南

在嵌入式系统开发中,图形用户界面(GUI)的渲染质量直接影响用户体验。其核心挑战在于如何将丰富的视觉资源高效适配到资源受限的硬件平台上。这涉及到两个关键技术:字体渲染和色彩管理。字体渲染的原理是将矢量字体轮廓在开发阶段预先栅格化为位图,并通过抗锯齿技术平滑边缘,以平衡显示效果与存储开销。色彩管理则充当逻辑颜色与应用层与物理颜色与硬件层之间的桥梁,通过高效的映射算法确保色彩显示的准确性。这两项技术的价值在于,它们能显著降低对MCU的Flash和RAM的资源占用,从而控制产品成本和功耗,并提升开发效率。其应用场

weixin_30718391的博客 381

嵌入式Unicode与UTF-8工程实践:STM32中文显示核心指南

Unicode是全球字符统一编号体系,本质为码点(Code Point)而非编码格式;其工程价值在于提供跨语言、跨协议、长期可读的抽象基础。UTF-8作为最适配嵌入式系统的实现编码,凭借ASCII兼容、自同步字节边界和大小端无关三大特性,在资源受限MCU(如STM32F103)中实现高效编解码。它支撑中英文混排、MQTT/HTTPS国际协议互通、OTA升级及LCD/HMI多语言渲染等关键场景。本文聚焦Unicode码点处理、UTF-8轻量级C实现、BOM规避策略与ANSI误区澄清,为物联网终端提供可量产的字

weixin_42400643的博客 75

【LCD】液晶显示中英文实验(4)

本文介绍了在嵌入式系统中显示中英文字符的两种实现方法:外部Flash存储和SD卡存储。硬件设计包括获取字模数据、编写液晶显示函数和测试程序。代码分析部分详细说明了显示32×32点阵汉字的函数实现,通过GetGBKCode从外部存储器读取字模数据并逐位绘制。同时提供了显示混合字符串的函数,支持自动换行处理。最后介绍了从SPI-Flash获取GB2312/GBK编码字模数据的方法,包括地址计算和初始化流程。这些方法适用于需要同时显示中英文的嵌入式显示应用场景。

weixin_72943539的博客 858

单片机字符显示必备:高效取字模软件推荐与实战应用

除了标准字符外,许多嵌入式系统还需显示温度计、电池电量、箭头等专用图标。这类图形无法通过常规字体获取,必须借助自定义设计手段。

weixin_29155599的博客 1234

stm32汉字字库显示实验与OLED的使用(开始于2021-09-01)

stm32汉字字库显示实验与OLED的使用 1.字库的使用 GBK字库的简介: GBK库的由两部分组成,如下图: 高位从0x81开始是为了兼容ASII字符,因为未扩展的ASII字符是从0-128,即0x00-0x80; 汉字编码均为连个字节,所以在ASII字符显示8 * 16的字符时,汉字为16 * 16; 这儿需要注意一点,我们使用的编辑器的方式,要与字库的编码方式对应才行(GBK); 因为在使用字库的过程中是1️⃣从字符的地址访问出它的(2字节)编码(编辑时使用GBK,则为GBK编码),2️⃣

weixin_51915497的博客 7280

TFTLCD汉字显示实战:点阵提取、GB2312编码与STM32驱动

嵌入式显示系统常遇到中文显示乱码问题,根源往往不在屏幕硬件,而在于汉字点阵数据的获取与编码换算。汉字在屏幕上的呈现本质是点阵的映射,16×16点阵每个字占用32字节,需按行列排列并逐位映射。GB2312编码通过区位码计算字库偏移,是连接字符与字模的关键。掌握点阵原理、编码换算和并口时序控制,即可在STM32平台实现稳定高效的TFTLCD中文显示,广泛应用于工控界面、仪表盘和智能家居等人机交互场景。本文从点阵基础出发,结合GB2312编码换算与8080并口驱动,提供可落地的工程实践方法。

weixin_42519985的博客 283

12864液晶显示汉字全攻略:ST7920带字库与GB2312编码详解

在嵌入式显示应用中,液晶屏是实现人机交互的核心器件,而汉字显示往往涉及编码转换与点阵字库等底层技术。GB2312编码作为中文字符集标准,决定了汉字在系统内的存储与传输方式;点阵字库则通过像素矩阵还原字形,二者共同构成了字符显示的基础。ST7920控制器内置中文字库,可简化汉字显示流程,避免外部字模开销,因此在12864液晶模块中被广泛采用。理解其工作原理,有助于解决中文乱码、地址偏移等问题。本文围绕12864液晶的汉字显示实践,从控制器选型、编码原理到初始化与驱动代码,系统梳理工程实现中的关键步骤与常见坑点

weixin_34326558的博客 394

从乱码到清晰中文:STM32显示项目中最容易踩的5个坑(字库、编码、取模方式详解)

本文详细解析了STM32液晶屏中文显示项目中最常见的5个问题,包括编码选择、字库存储、取模方式、内存不足和中英文混合排版。通过具体案例和解决方案,帮助开发者避免乱码和显示异常,提升嵌入式开发效率。特别针对STM32系列单片机的特性,提供了实用的代码示例和优化建议。

weixin_30920513的博客 569

电脑的kernelbase.dll故障怎么处理?kernelbase.dll是什么文件

kernelbase.dll​是一个系统文件,属于Microsoft Windows操作系统的一部分。该DLL(动态链接库)文件包含了许多基本且低级的系统函数,这些函数被Windows上运行的各种程序和进程调用。kernelbase.dll通常与Kernel32.dll紧密相关,它是实现许多Windows API(应用程序编程接口)的封装。这些API涉及到内存管理、输入输出操作、进程和线程管理以及其他许多核心的操作系统功能。

电脑修复君的博客 4534
上一篇: Zigbee无线传感网实战:基于ZStack与STM32的光敏数据采集系统
下一篇: 从零到一:华芯微特图形上位机在智能家居面板开发中的实战解析
sql99
博客等级 码龄19年 168粉丝 1905原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值