news 2026/5/10 18:50:02

STM32F103C6实战:用CubeMX配置SPI驱动ILI9341,并搞定中文显示和图片播放

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
STM32F103C6实战:用CubeMX配置SPI驱动ILI9341,并搞定中文显示和图片播放

STM32F103C6实战:CubeMX配置SPI驱动ILI9341实现中文与图片显示

在嵌入式开发中,显示界面往往是项目中最直观的交互部分。对于使用STM32F103C6这类资源受限MCU的开发者来说,如何高效驱动SPI接口的ILI9341屏幕并实现中文和图片显示,是一个既基础又具有挑战性的任务。本文将带你从CubeMX配置开始,一步步实现这些功能,特别针对F103C6的64KB Flash和20KB RAM资源限制进行优化。

1. 硬件准备与CubeMX基础配置

拿到一块STM32F103C6最小系统板和ILI9341 SPI屏幕后,首先要确保硬件连接正确。典型的SPI接口连接如下:

ILI9341引脚STM32F103C6引脚备注
CSPA4片选,可自定义
RESETPA3复位,可自定义
DCPA2数据/命令,可自定义
SDA(MOSI)PA7SPI1_MOSI固定
SCKPA5SPI1_SCK固定
VCC3.3V勿接5V
GNDGND

在CubeMX中的配置步骤:

  1. 新建工程选择STM32F103C6Tx
  2. 配置时钟树(建议使用内部HSI 8MHz倍频至48MHz)
  3. 启用SPI1为主机全双工模式
    • 时钟极性(CPOL): Low
    • 时钟相位(CPHA): 1 Edge
    • 数据大小: 8位
    • 首次位: MSB First
    • 预分频器: /8 (6MHz SPI时钟)
  4. 配置GPIO:
    // 在生成的代码中检查以下GPIO配置 HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_SET); // CS高电平 HAL_GPIO_WritePin(GPIOA, GPIO_PIN_3, GPIO_PIN_SET); // RESET高电平

注意:F103C6的SPI1最大支持18MHz,但实际速度受限于GPIO速度设置。建议初始配置为Medium速度,后续根据显示效果调整。

2. ILI9341驱动移植与优化

针对F103C6有限的RAM资源,我们需要对标准驱动进行优化:

驱动文件结构优化:

/Drivers /ILI9341 ├── ili9341.c // 核心驱动 ├── ili9341.h // 用户接口 └── fonts.c // 字库(使用const修饰)

关键优化点:

  1. 使用const将字库数据存入Flash:
    const uint8_t Font16x16[][32] = { // 字模数据... };
  2. 精简API接口,保留核心功能:
    void ILI9341_WriteCommand(uint8_t cmd); void ILI9341_WriteData(uint8_t data); void ILI9341_SetWindow(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1); void ILI9341_DrawPixel(uint16_t x, uint16_t y, uint16_t color);

显示初始化序列需要根据SPI模式调整:

void ILI9341_Init(void) { // 硬件复位 HAL_GPIO_WritePin(LCD_RST_GPIO_Port, LCD_RST_Pin, GPIO_PIN_RESET); HAL_Delay(100); HAL_GPIO_WritePin(LCD_RST_GPIO_Port, LCD_RST_Pin, GPIO_PIN_SET); HAL_Delay(120); // SPI初始化序列 ILI9341_WriteCommand(0xCF); // Power control B ILI9341_WriteData(0x00); ILI9341_WriteData(0xC1); ILI9341_WriteData(0x30); // ...更多初始化命令 }

3. 中文显示实现与字模处理

在资源受限的F103C6上实现中文显示,需要精心设计字库存储方案:

PC端取模步骤(以PCtoLCD2002为例):

  1. 设置取模方式:
    • 横向取模,字节不倒序
    • 阴码(1表示点亮)
    • 16x16点阵
  2. 生成字模数据格式示例:
    /*"中"*/ { 0x00,0x40,0x20,0x50,0x10,0x48,0x00,0x44, 0xFF,0xFE,0x00,0x40,0x00,0x40,0x00,0x40, 0x00,0x40,0x00,0x44,0x00,0x44,0x00,0x44, 0x00,0x44,0x00,0x44,0x00,0x04,0x00,0x00 },

F103C6上的存储优化技巧:

  1. 按需存储:只存储项目实际用到的汉字
  2. 使用二级索引表加速查找:
    typedef struct { uint16_t unicode; // Unicode编码 const uint8_t *data; // 指向字模数据 } FontIndex; const FontIndex ChineseFont[] = { {0x4E2D, Font16x16[0]}, // "中" {0x6587, Font16x16[1]}, // "文" // ... };

显示函数实现:

void ILI9341_DrawChinese(uint16_t x, uint16_t y, uint16_t color, uint16_t bg_color, uint16_t unicode) { const uint8_t *font = FindFontData(unicode); if(!font) return; ILI9341_SetWindow(x, y, x+15, y+15); for(int i=0; i<32; i++) { uint8_t byte = font[i]; for(int j=0; j<8; j++) { uint16_t pixel = (byte & (1<<(7-j))) ? color : bg_color; ILI9341_WriteData(pixel >> 8); ILI9341_WriteData(pixel & 0xFF); } } }

4. 图片显示与内存优化

在仅20KB RAM的F103C6上显示图片需要特殊处理:

图片预处理流程:

  1. 使用Photoshop或GIMP将图片调整为:
    • 尺寸不超过240x320
    • 颜色模式:RGB565
    • 保存为BMP格式
  2. 使用Img2Lcd工具转换:
    • 输出格式:C数组
    • 扫描模式:水平扫描
    • 颜色位序:RGB

F103C6上的显示策略:

  1. 分段加载:将大图片分割为多个小块显示
    void Show_SegmentImage(uint16_t x, uint16_t y, uint16_t width, uint16_t height, const uint8_t *img) { ILI9341_SetWindow(x, y, x+width-1, y+height-1); uint32_t index = 0; for(int h=0; h<height; h++) { for(int w=0; w<width; w++) { uint16_t color = (img[index]<<8) | img[index+1]; ILI9341_WriteData(color >> 8); ILI9341_WriteData(color & 0xFF); index += 2; } } }
  2. 使用外部Flash存储图片(如有):
    // 假设图片存储在W25Q64 SPI Flash void Show_Image_From_Flash(uint16_t x, uint16_t y, uint32_t flash_addr, uint16_t width, uint16_t height) { uint8_t buffer[64]; // 小缓冲区 ILI9341_SetWindow(x, y, x+width-1, y+height-1); for(uint32_t i=0; i<width*height*2; i+=64) { W25Qxx_Read(buffer, flash_addr+i, 64); for(int j=0; j<64; j+=2) { uint16_t color = (buffer[j]<<8) | buffer[j+1]; ILI9341_WriteData(color >> 8); ILI9341_WriteData(color & 0xFF); } } }

5. 性能优化与调试技巧

针对SPI显示速度慢的问题,可以尝试以下优化:

CubeMX配置优化:

  1. 将SPI时钟分频设置为/4 (12MHz @48MHz系统时钟)
  2. GPIO速度设置为"High"
  3. 启用SPI TX DMA通道(如有剩余DMA资源)

代码级优化:

  1. 批量写入优化:
    void ILI9341_WriteData_DMA(uint8_t *data, uint32_t len) { HAL_GPIO_WritePin(LCD_CS_GPIO_Port, LCD_CS_Pin, GPIO_PIN_RESET); HAL_GPIO_WritePin(LCD_DC_GPIO_Port, LCD_DC_Pin, GPIO_PIN_SET); HAL_SPI_Transmit_DMA(&hspi1, data, len); // 需要等待传输完成 }
  2. 屏幕局部刷新技术:
    void Update_Changed_Area(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t *buffer) { ILI9341_SetWindow(x1, y1, x2, y2); ILI9341_WriteData_DMA((uint8_t*)buffer, (x2-x1+1)*(y2-y1+1)*2); }

常见问题排查:

  1. 图片显示花屏:
    • 检查SPI时钟是否过高
    • 确认图片数据格式是否为RGB565
    • 验证GPIO速度设置
  2. 中文显示乱码:
    • 确认取模方式与显示代码一致
    • 检查Unicode编码是否正确
    • 验证字模数据是否被意外修改

在项目最后阶段,可以将不同功能模块化,创建一个简单的UI框架:

typedef struct { void (*Init)(void); void (*ShowText)(uint16_t x, uint16_t y, char *text); void (*ShowImage)(uint16_t x, uint16_t y, ImageType *img); } LCD_Driver; LCD_Driver ili9341_driver = { .Init = ILI9341_Init, .ShowText = ILI9341_ShowText, .ShowImage = ILI9341_ShowImage };

实际开发中发现,当同时启用SPI和USART时,偶尔会出现显示异常。通过逻辑分析仪捕获发现是SPI时钟被干扰,解决方案是在CubeMX中调整外设优先级,并确保关键显示代码段不被中断打断。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/10 18:48:42

植物大战僵尸(金铲铲版 无双版 西游版)2026.5.10最新修改版免费下载 手机电脑都可下 你肯定没玩过 看到赶紧转存 (资源随时失效)

金铲铲版下载 无双版下载 西游版下载 在国产游戏创意模组&#xff08;Mod&#xff09;与同人二创的广阔星海中&#xff0c;《植物大战僵尸&#xff1a;金铲铲版》&#xff08;以下简称“金铲铲版PvZ”&#xff09;无疑是一颗极具辨识度的璀璨新星。它成功地将经典塔防《植物…

作者头像 李华
网站建设 2026/5/10 18:47:59

从BT玩家到PT入门:聊聊那些年我们用过的下载工具和如今的选择

从BT玩家到PT入门&#xff1a;聊聊那些年我们用过的下载工具和如今的选择 还记得2005年第一次用迅雷下载《魔兽世界》客户端时的震撼吗&#xff1f;2MB的小水管硬是拖了三天三夜&#xff0c;期间经历了17次断线重连。那时候的下载工具就像西部荒野——规则模糊、弱肉强食&#…

作者头像 李华
网站建设 2026/5/10 18:44:30

从理论到实战:Kali Linux渗透测试核心工具链深度解析(John、Ettercap、SQL注入与Python脚本编写)

1. Kali Linux渗透测试入门指南 第一次接触Kali Linux时&#xff0c;我被它强大的工具集震撼到了。这个基于Debian的Linux发行版专为网络安全测试设计&#xff0c;预装了600多种渗透测试工具。记得我刚开始学习时&#xff0c;最困惑的就是如何系统地掌握这些工具的使用方法。经…

作者头像 李华
网站建设 2026/5/10 18:35:55

TegraRcmGUI完整指南:Windows上最简单的Switch注入工具终极教程

TegraRcmGUI完整指南&#xff1a;Windows上最简单的Switch注入工具终极教程 【免费下载链接】TegraRcmGUI C GUI for TegraRcmSmash (Fuse Gele exploit for Nintendo Switch) 项目地址: https://gitcode.com/gh_mirrors/te/TegraRcmGUI TegraRcmGUI是一款专为Windows系…

作者头像 李华
网站建设 2026/5/10 18:33:52

如何永久重置IDM试用期:终极免费解决方案指南

如何永久重置IDM试用期&#xff1a;终极免费解决方案指南 【免费下载链接】idm-trial-reset Use IDM forever without cracking 项目地址: https://gitcode.com/gh_mirrors/id/idm-trial-reset 还在为Internet Download Manager&#xff08;IDM&#xff09;的30天试用期…

作者头像 李华
网站建设 2026/5/10 18:32:52

新手教程使用Python和Taotoken密钥快速调用大模型聊天接口

&#x1f680; 告别海外账号与网络限制&#xff01;稳定直连全球优质大模型&#xff0c;限时半价接入中。 &#x1f449; 点击领取海量免费额度 新手教程使用Python和Taotoken密钥快速调用大模型聊天接口 本文面向刚开始接触大模型API调用的开发者&#xff0c;旨在提供一个清晰…

作者头像 李华