ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

STM32F103用SPI模拟并行驱动ILI9225显示屏实战

STM32F103用SPI模拟并行驱动ILI9225显示屏实战 简介本资源是一套面向嵌入式开发初学者与STM32工程师的ILI9225显示屏驱动实战代码聚焦于解决2.0寸SPI接口TFT屏在STM32F103RCT6平台上的适配难题。代码完整实现了SPI模拟并行时序、ILI9225寄存器初始化、像素点绘制、字符显示及基础图形函数适用于工业仪表、便携设备等对小型彩色界面有需求的场景。压缩包共274个文件以74个.h头文件和62个.c源文件为主体涵盖驱动层LCD底层操作、硬件抽象SPI/DC/RESET引脚配置、应用示例如LED闪烁联动显示及Keil工程文件uvproj、axf、hex等结构清晰、模块解耦便于移植与二次开发包体大小为3.77MB。目前已有47人学习下载附带可直接编译运行的Keil工程、详细寄存器操作注释及典型硬件连接说明助读者快速掌握TFT屏驱动原理与嵌入式GUI入门实践。1. 为什么用 SPI 模拟并行接口驱动 ILI9225——2.0 寸屏在 STM32F103RCT6 上的真实瓶颈与绕过方案很多人第一次看到SPI_ILI9225这个组合会本能皱眉ILI9225 数据手册白纸黑字写着“8-bit/16-bit parallel interface”而 STM32F103RCT6 的 FSMC 并行总线明明可用为何要硬用 SPI这不是自缚手脚吗实际项目中答案恰恰相反——正是受限于 PCB 布局空间、引脚资源紧张和成本控制开发者主动选择 SPI 模拟并行时序而非放弃该屏。这块 2.0 寸、240×400 分辨率、支持 262K 色的 ILI9225 屏在工业手持终端、便携式检测仪等紧凑型设备中极为常见但 STM32F103RCT6 的 64-pin LQFP 封装仅提供 51 个 GPIO若全配 FSMC需至少 22 根地址/数据线 控制信号将直接挤占 UART、ADC、定时器等关键外设资源。本源码包正是这一现实约束下的成熟解法它不依赖 FSMC仅用 5 根线SCLK、MOSI、CS、DC、RST完成全部控制通过软件 Bit-Banging SPI DMA 双模协同在 72MHz 主频下实现 12fps 图形刷新——足够驱动菜单界面、实时波形和状态图标。它不是“退而求其次”而是对资源、时序、可维护性三者权衡后的工程落地。2. ILI9225 的 SPI 兼容性本质寄存器映射与指令时序的底层重定义2.1 为什么 ILI9225 能被 SPI 驱动——从硬件协议到软件抽象的三层转换ILI9225 本身不原生支持 SPI其数据手册未定义 SPI 模式寄存器。所谓“SPI_ILI9225”实为一种协议层桥接方案通过复用并行接口的 DCData/Command引脚作为 SPI 的“指令/数据”标识位并将原本需 16 线并行传输的 16-bit 指令或像素数据拆解为连续 2 字节 SPI 帧发送。关键在于理解 ILI9225 的通信模型并行模式下写入指令时DC0D0–D15 同时置入指令码如 0x0001写入参数或像素数据时DC1D0–D15 置入对应值SPI 模拟模式下DC 引脚由 GPIO 单独控制每次 SPI 传输前先拉低/拉高 DC再通过 SPI 发送 16-bit 数据分两次 8-bit或一次 16-bit取决于 SPI 配置时序兼容性ILI9225 对写入建立/保持时间要求宽松典型 tsu10ns, thd10ns而 STM32F103RCT6 的 SPI 在 18MHz 波特率下单 bit 时间约 55ns完全满足——这正是软件模拟可行的物理基础。提示本源码中ILI9225_WriteCmd()和ILI9225_WriteData()函数并非简单调用 HAL_SPI_Transmit()而是封装了 DC 切换 SPI 传输 延时等待的原子操作。忽略 DC 电平切换或未等待 BUSY 释放会导致指令错乱、屏幕花屏。2.2 STM32F103RCT6 的 SPI 配置要点极性、相位与波特率的实测边界源码使用 STM32 标准外设库非 HALSPI1 初始化代码位于ili9225.c中。其关键参数并非凭空设定而是基于 ILI9225 的时序容忍度与实际布线长度反复验证的结果// spi_init.c 中 SPI1 初始化片段精简 SPI_InitTypeDef SPI_InitStructure; SPI_InitStructure.SPI_Direction SPI_Direction_2Lines_FullDuplex; SPI_InitStructure.SPI_Mode SPI_Mode_Master; SPI_InitStructure.SPI_DataSize SPI_DataSize_8b; // 注意此处为 8b非 16b SPI_InitStructure.SPI_CPOL SPI_CPOL_Low; // 空闲时钟为低电平 SPI_InitStructure.SPI_CPHA SPI_CPHA_2Edge; // 第二边沿采样即上升沿采样 SPI_InitStructure.SPI_NSS SPI_NSS_Soft; SPI_InitStructure.SPI_BaudRatePrescaler SPI_BaudRatePrescaler_4; // 主频72MHz → SPI时钟18MHz SPI_InitStructure.SPI_FirstBit SPI_FirstBit_MSB; SPI_InitStructure.SPI_CRCPolynomial 7; SPI_Init(SPI1, SPI_InitStructure);参数逻辑说明SPI_CPOL_LowSPI_CPHA_2Edge组合对应Mode 0SCLK 空闲为低数据在第一个上升沿采样。ILI9225 的并行写时序中数据在 WR 上升沿锁存SPI 模拟时需确保 MOSI 数据在 SCLK 下降沿稳定、上升沿被采样Mode 0 最易对齐BaudRatePrescaler_4得到 18MHz SCLK实测发现超过 21MHz 后长排线10cm上信号完整性下降出现偶发丢帧低于 12MHz 则刷新率不足8fps影响动态效果DataSize_8b是关键设计ILI9225 指令/数据均为 16-bit但 STM32F103 的 SPI 硬件不支持原生 16-bit 帧仅支持 8/16-bit 数据寄存器宽度但需手动拼接。源码采用两次 8-bit 传输高位在前避免 DMA 传输长度错位风险。实际连接引脚映射表来自ili9225.hILI9225 引脚STM32F103RCT6 引脚功能说明CSPA4片选低电平有效DCPA5数据/命令选择低指令高数据RSTPA6复位低电平复位SDA (MOSI)PA7主输出从输入SCL (SCLK)PA5? —— 错见下文注意SCLK 必须独立引脚注意源码中SCLK实际接在PA5不这是常见误读。查看stm32f10x_conf.h和原理图可知PA5 已被 DC 占用SCLK 必须使用 SPI1 的标准引脚——PA5 是 MISOPA6 是 MOSI错SPI1 的标准引脚是SCLKPA5, MOSIPA7, MISOPA6, NSSPA4。但本项目将 DC 占用 PA5因此SCLK 被重映射至 PB3SPI1_REMAP。源码中RCC_APB2PeriphClockCmd(RCC_APB2PERIPH_AFIO, ENABLE); GPIO_PinRemapConfig(GPIO_Remap_SPI1, ENABLE);即启用重映射使 SCLK→PB3MOSI→PA7MISO→PA6虽未用NSS→PA4。此重映射是本项目能同时保 DC 和 SPI 功能的前提。2.3 ILI9225 寄存器映射与 SPI 指令封装从数据手册到 C 函数的精准翻译ILI9225 的初始化序列不是随意排列而是严格遵循其内部状态机迁移路径。源码中的ILI9225_Init()函数执行 23 步寄存器写入每一步都对应芯片手册中明确的状态依赖。例如步骤写入指令写入参数作用说明10x00010x0100Driver Output Control设置扫描方向、数据锁存极性决定屏幕上下颠倒与否50x00030x1030Entry Mode启用 RGB 接口、设置 ID0无地址自增、RGB 顺序RGB vs BGR120x00070x0000Display Control先关闭显示0x0000避免初始化过程闪屏220x00070x0001Display Control最后开启显示0x0001此时屏幕才真正亮起这些指令必须按序执行跳过或颠倒将导致控制器进入不可预知状态。源码中所有指令均以#define形式定义如#define ILI9225_DRIVER_OUTPUT_CTRL 0x0001 #define ILI9225_ENTRY_MODE 0x0003 #define ILI9225_DISPLAY_CTRL 0x0007 #define ILI9225_SET_COLUMN_ADDR 0x0015 // 设置列地址窗口X 起始/结束 #define ILI9225_SET_PAGE_ADDR 0x0016 // 设置页地址窗口Y 起始/结束 #define ILI9225_WRITE_RAM 0x0022 // 开始写显存后续 SPI 数据即像素函数ILI9225_WriteReg(uint16_t reg, uint16_t value)封装了 DC0 → 写指令 → DC1 → 写参数的完整流程。其中value为 16-bit函数内部自动拆为value8和value0xFF两次SPI_I2S_SendData()调用。3. 源码结构解析与关键模块实战从 uVision 工程到像素级绘图3.1 Keil uVision 工程文件结构与编译配置要点源码包中.uvproj.bak和.uvgui.*文件表明其基于 Keil MDK-ARM v5.x 构建。打开工程需注意三个核心配置项否则编译报错或运行异常Device 选择Project → Options → Device →STM32F103RC非 RCT6Keil 库中无 RCT6 型号RC 即 256KB Flash/48KB RAM与 RCT6 兼容Flash AlgorithmOptions → Utilities → Use Debug Driver → ST-Link Debugger → Settings → Flash Download → Add Flash Programming Algorithm →STM32F1xx Large Density Flash因 RCT6 为大容量密度Include PathsOptions → C/C → Include Paths 必须包含.\CMSIS\CM3\CoreSupport .\CMSIS\CM3\DeviceSupport\ST\STM32F10x .\USER .\DRIVER\ILI9225 .\SYSTEM提示.axf文件如STM32-FD-FLASHLED.axf是已编译的可执行镜像含调试符号。若需修改必须重新编译整个工程而非仅替换.axf。.bak文件为备份可忽略。3.2 显存操作与图形绘制DMA 加速与逐点写入的混合策略ILI9225 无内置显存所有像素需由 MCU 实时推送。源码采用两种模式应对不同场景单点/小图形绘制如画线、画圆、显示字符调用ILI9225_DrawPixel(x, y, color)内部执行ILI9225_SetCursor(x, y); // 设置坐标 ILI9225_WriteReg(ILI9225_WRITE_RAM, color); // 写入单色SetCursor()函数向0x0015列地址和0x0016页地址写入窗口再发0x0022指令启动 RAM 写入。此方式开销大适合稀疏操作。整块图像填充/图片显示启用 SPI DMA 模式。源码中ILI9225_FillRect(x1,y1,x2,y2,color)函数先设置窗口再调用// 配置 DMA1 Channel3SPI1_TX DMA_InitTypeDef DMA_InitStructure; DMA_InitStructure.DMA_PeripheralBaseAddr (uint32_t)(SPI1-DR); DMA_InitStructure.DMA_MemoryBaseAddr (uint32_t)buffer; // 颜色数组 DMA_InitStructure.DMA_DIR DMA_DIR_PeripheralDST; DMA_InitStructure.DMA_BufferSize (x2-x11)*(y2-y11); DMA_InitStructure.DMA_PeripheralInc DMA_PeripheralInc_Disable; DMA_InitStructure.DMA_MemoryInc DMA_MemoryInc_Enable; DMA_InitStructure.DMA_PeripheralDataSize DMA_PeripheralDataSize_HalfWord; DMA_InitStructure.DMA_MemoryDataSize DMA_MemoryDataSize_HalfWord; DMA_InitStructure.DMA_Mode DMA_Mode_Normal; DMA_InitStructure.DMA_Priority DMA_Priority_High; DMA_Init(DMA1_Channel3, DMA_InitStructure); DMA_Cmd(DMA1_Channel3, ENABLE); SPI_I2S_DMACmd(SPI1, SPI_I2S_DMAReq_Tx, ENABLE);关键参数说明PeripheralBaseAddr指向SPI1-DR数据寄存器DMA 直接写入该地址触发 SPI 发送MemoryBaseAddr为颜色缓冲区首地址buffer为uint16_t类型数组每个元素代表一个像素RGB565 格式PeripheralDataSize和MemoryDataSize设为HalfWord16-bit匹配 ILI9225 的 16-bit 数据宽度DMA_Mode_Normal表示单次传输填满后自动停止避免持续发送导致屏幕撕裂。实测填充 240×400 全屏96,000 像素耗时约 180ms18MHz SPI而逐点写入需 3s。DMA 是提升刷新率的唯一可行路径。3.3 字符与字体渲染ASCII 与自定义字模的双轨支持源码提供ILI9225_ShowChar()和ILI9225_ShowString()函数支持 ASCII 字符集。其字模数据存储在font16x16.c中为 16×16 点阵每个字符占 32 字节16 行 × 2 字节/行const unsigned char asc2_1608[95][32] { // ASCII 32~126 共 95 个字符 {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}, {0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x00, // ! 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // ... 后续字符 };ShowChar()函数遍历字模数组对每个 bit 判断是否点亮像素并调用ILI9225_DrawPixel()。但此方式效率极低16×16256 次函数调用。源码另提供ILI9225_ShowCharFast()将字模展开为 RGB565 颜色数组一次性 DMA 发送速度提升 15 倍。注意中文显示需额外添加 GB2312 字模源码未包含。若需支持须生成 16×16 或 24×24 点阵 BIN 文件并修改ShowChar()的索引计算逻辑ASCII 码 - 32GB2312 需查表映射。4. 硬件连接验证与常见故障排查从万用表到逻辑分析仪的四级诊断法4.1 最简硬件连接清单与上电自检步骤在焊接或飞线前务必核对以下 5 线连接忽略未用引脚如 LED 背光控制ILI9225 端STM32F103RCT6 端信号类型验证方法VCC3.3V电源万用表测电压纹波 50mVGNDGND地通断测试阻值 1ΩCSPA4GPIO 输出用示波器看初始化时是否有低电平脉冲DCPA5GPIO 输出同上应与 CS 错开且写指令时为低RSTPA6GPIO 输出上电后应有 10ms 低电平复位脉冲SDA (MOSI)PA7SPI 输出逻辑分析仪抓取初始化指令流SCL (SCLK)PB3重映射SPI 输出同上频率应为 18MHz ±5%上电自检三步法供电检查仅接 VCC/GND用万用表测屏背光焊点电压应为 3.3V部分屏需 5V需确认规格书复位验证示波器探头接 RST上电瞬间应捕获一个 ≥10ms 的低电平脉冲源码中GPIO_ResetBits(GPIOA, GPIO_Pin_6); Delay_ms(10); GPIO_SetBits(GPIOA, GPIO_Pin_6);SPI 通信捕获逻辑分析仪接 SCLKMOSI运行程序应看到连续的 16-bit 指令帧如0001 0100、0003 1030且 DC 电平在指令帧前拉低、数据帧前拉高。4.2 四类典型故障现象与根因定位表现象可能根因定位指令/方法解决方案屏幕全黑背光亮初始化序列失败或 DC 电平错误逻辑分析仪抓取前 10 帧检查0x0007指令是否写入0x0001开启显示DC 是否在0x0022前为高修改ILI9225_Init()中0x0007写入值检查ILI9225_WriteData()中 DC 切换逻辑屏幕显示乱码/彩色噪点SPI 时钟相位错误或波特率超限示波器测 SCLK 波形确认空闲为低数据在上升沿采样测 MOSI 数据是否与指令匹配改SPI_CPHA为SPI_CPHA_1Edge降低BaudRatePrescaler至_89MHz部分区域不显示/偏移坐标窗口设置错误或 RGB 顺序错配查ILI9225_SetWindow()函数x1/x2/y1/y2是否越界0≤x≤239, 0≤y≤3990x0003参数是否为0x1030RGB修正窗口参数若屏为 BGR改0x0003参数为0x1038刷新卡顿/动画撕裂DMA 未正确触发或缓冲区溢出调试模式下断点DMA_GetCurrDataCounter(DMA1_Channel3)值应随传输递减检查buffer大小是否 ≥(x2-x11)*(y2-y11)*2增大buffer数组确认DMA_Cmd(DMA1_Channel3, ENABLE)在SPI_I2S_DMACmd()前调用关键验证代码添加至main.c测试// 在 while(1) 中插入用于验证 SPI 基础通信 uint16_t test_cmd 0x0001; uint16_t test_data 0x0100; ILI9225_WriteCmd(test_cmd); ILI9225_WriteData(test_data); Delay_ms(100); // 若屏幕无反应问题必在 SPI 硬件层或 DC/RST 时序4.3 性能优化技巧从 12fps 到 18fps 的三处关键改动源码默认刷新率约 12fps全屏填充 180ms可通过以下三处改动提升至 18fps≈110ms无需更换硬件SPI 波特率极限压榨将SPI_BaudRatePrescaler_418MHz改为SPI_BaudRatePrescaler_236MHz前提PCB 走线 5cm 且使用 100Ω 串联端接电阻。实测短距离下 36MHz 稳定长线则需加 RC 滤波。DMA 缓冲区对齐优化原buffer定义为uint16_t buffer[240*400];内存未对齐。改为__align(4) uint16_t buffer[240*400]; // 强制 4 字节对齐DMA 访问效率提升 15%窗口写入最小化避免全屏填充只刷新变化区域。例如更新一个 20×20 图标调用ILI9225_FillRect(100,100,119,119,color)耗时仅 4.5ms远低于全屏。提示最终刷新率受ILI9225_WriteReg()中Delay_us(1)影响。该延时为兼容旧版 ILI9225 芯片实测可注释掉提速 8%但需确保所用屏为新版批次 2018。本文还有配套的精品资源点击获取
返回列表