十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

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

STM32驱动ILI7789V彩色LCD的SPI时序与初始化详解

STM32驱动ILI7789V彩色LCD的SPI时序与初始化详解 简介本资源是一套基于STM32F10x系列MCU的SPI接口驱动ST7789V彩色TFT液晶屏的完整工程例程面向嵌入式初学者与中级开发者解决LCD显示驱动开发中SPI配置、初始化时序、像素数据传输及基础图形绘制等核心问题。压缩包含185个文件主体为33个C源码、35个头文件.h、34个编译中间文件.o/.d/.crf辅以Keil工程配置.uvprojx/.uvoptx、启动文件.s、链接脚本.sct及可执行镜像.hex/.axf总大小4.91MB结构完整可直接编译下载运行。已有1057人学习下载资源包含标准外设库驱动框架、ST7789V专用LCD驱动层、屏幕初始化序列、RGB565像素写入函数及基础绘图接口代码注释清晰结合内容预览可见其覆盖RCC、GPIO、SPI、TIM等关键外设模块便于理解底层硬件协同逻辑与显示驱动全流程实现。1. STM32 驱动 ILI7789V 彩色 LCD 不是“接上线就能亮”而是 SPI 时序、引脚复用与初始化序列的三重校准很多刚接触 ILI7789V 屏幕的开发者会误以为只要把 STM32 的 SPI 引脚连到屏的 SCL/SDA/CS/DC调用 HAL_SPI_Transmit() 发几条命令屏幕就该亮起彩色图像——结果却是全黑、花屏、闪屏或只显示固定灰阶。根本原因在于ILI7789V 并非标准 SPI 设备它要求严格匹配的时钟极性CPOL、相位CPHA、数据宽度8-bit、片选时序CS active-low 且需保持足够低电平时间更关键的是其初始化序列包含 20 条寄存器写入指令顺序、延时、参数缺一不可。本例程聚焦 STM32F103/F407 等主流型号使用 HAL 库 CubeMX 配置 SPI 外设不依赖第三方 GUI 库从裸寄存器操作级还原驱动逻辑。适合需要嵌入式图形界面但受限于 Flash/RAM 资源的工业 HMI、便携设备或毕业设计项目尤其适用于已掌握基础 GPIO/SPI 操作、正卡在“屏不响应”环节的 1–3 年经验工程师。2. ILI7789V 与 STM32 的硬件连接必须满足三类电气约束SPI 模式、DC/CS 电平逻辑与供电稳定性2.1 ILI7789V 的 SPI 接口特性决定了 STM32 外设配置不能套用通用模板ILI7789V 数据手册明确标注其 SPI 接口工作在Mode 0CPOL0, CPHA0空闲时 SCK 为低电平数据在 SCK 上升沿采样且必须在 SCK 下降沿前建立稳定。这与多数 Flash 或传感器不同若 CubeMX 中误设为 Mode 3CPOL1, CPHA1则通信必然失败表现为 SPI_TXE 标志永不置位或接收数据全为 0xFF。此外该芯片仅支持8-bit 数据帧不兼容 16-bit 传输其最大 SCK 频率标称为 30 MHz但实测在 STM32F103 上超过 12 MHz 易出现误码因 GPIO 切换速度与布线容性影响推荐初始配置为8 MHz对应 APB272 MHz 时预分频值为 8。提示不要直接复制其他 OLED 或 ST7735 的 SPI 配置。ILI7789V 的 DCData/Command引脚功能等效于“寄存器地址/数据选择信号”高电平时发送的是显存数据GRAM低电平时发送的是控制寄存器地址与参数——这一逻辑必须由软件精确控制不能交由硬件自动管理。2.2 典型硬件连接表与关键引脚复用冲突规避ILI7789V 引脚功能说明推荐 STM32 引脚F103C8T6注意事项VCC3.3V 电源3.3VLDO 输出必须加 100nF 陶瓷电容紧靠屏端避免上电瞬间电流冲击导致初始化失败GND地GND与 MCU 共地避免地线环路SCLSPI 时钟PA5SPI1_SCK若使用 SPI2需注意 PB13 可能被 JTAG 占用需禁用 SWD/JTAG 或改用其他引脚SDASPI 数据MOSIPA7SPI1_MOSI不可接 MISOPA6ILI7789V 为单向写入设备无读回需求CS片选低有效PA4软件控制必须软件片选HAL_SPI_Transmit() 不自动拉低 CS需在每次传输前手动置低DC数据/命令选择PA3GPIO 输出初始化阶段需频繁切换电平建议用推挽输出模式避免开漏导致上升沿缓慢RESET复位低有效PA2GPIO 输出上电后需保持低电平 ≥ 10ms再拉高部分模块已内置 RC 复位电路可悬空LED背光控制PB0PWM 输出建议通过 MOSFET 驱动避免 MCU IO 直接带载典型电流达 80–150mA注意PA4CS与 PA3DC不可复用为 ADC 或其他外设功能。若使用 STM32F407优先选用 SPI1APB2 总线因其时钟频率更高可支撑更高刷率若用 SPI2APB1需确认预分频后 SCK 实际频率仍满足 8 MHz 要求。2.3 CubeMX 中 SPI1 的关键参数配置步骤以 F103 为例在 Pinout 视图中将 PA5/PA7/PA4/PA3 分别配置为SPI1_SCK/SPI1_MOSI/GPIO_Output/GPIO_Output进入 Configuration → Connectivity → SPI1Mode:Full-Duplex MasterHardware NSS:Disabled强制软件片选Frame Format:MotorolaData Size:8 BitsClock Polarity (CPOL):LowClock Phase (CPHA):1st EdgeNSS Signal:SoftwareBaud Rate Prescaler:8APB272MHz → SCK9MHz实测稳定First Bit:MSB First生成代码后在main.c中确认hspi1.Init.CLKPolarity SPI_POLARITY_LOW;与hspi1.Init.CLKPhase SPI_PHASE_1EDGE;已正确赋值。// 验证 SPI 初始化是否生效调试时添加 if (HAL_SPI_GetState(hspi1) ! HAL_SPI_STATE_RESET) { // 正常SPI 外设已初始化 } else { // 错误检查 CubeMX 是否生成了 MX_SPI1_Init() }该段代码用于快速定位初始化失败点——常见原因是未勾选Generate peripheral initialization as a pair of xxx_MspInit/DeInit functions导致时钟使能代码缺失。3. ILI7789V 初始化序列必须按精确时序执行23 条寄存器写入 5 类延时策略3.1 初始化流程图谱从复位释放到进入 RGB 模式共 7 个阶段ILI7789V 的初始化不是简单写入几个寄存器而是一个状态机驱动过程①硬复位同步→ ②睡眠退出→ ③像素格式设定→ ④伽马校正加载→ ⑤显示方向配置→ ⑥TE 使能可选→ ⑦显示开启。其中第②、④、⑦步存在最小延时要求单位ms而第③、⑤步需连续写入多寄存器中间不能插入 CS 抬升。3.2 关键寄存器写入函数与 DC 电平控制逻辑所有寄存器操作均通过同一函数完成区别仅在于is_cmd参数// ILI7789V 驱动核心函数需在 lcd.h 中声明 void ILI7789_WriteCmd(uint8_t cmd) { HAL_GPIO_WritePin(LCD_DC_GPIO_Port, LCD_DC_Pin, GPIO_PIN_RESET); // DC0: command mode HAL_GPIO_WritePin(LCD_CS_GPIO_Port, LCD_CS_Pin, GPIO_PIN_RESET); // CS low HAL_SPI_Transmit(hspi1, cmd, 1, HAL_MAX_DELAY); HAL_GPIO_WritePin(LCD_CS_GPIO_Port, LCD_CS_Pin, GPIO_PIN_SET); // CS high } void ILI7789_WriteData(uint8_t data) { HAL_GPIO_WritePin(LCD_DC_GPIO_Port, LCD_DC_Pin, GPIO_PIN_SET); // DC1: data mode HAL_GPIO_WritePin(LCD_CS_GPIO_Port, LCD_CS_Pin, GPIO_PIN_RESET); HAL_SPI_Transmit(hspi1, data, 1, HAL_MAX_DELAY); HAL_GPIO_WritePin(LCD_CS_GPIO_Port, LCD_CS_Pin, GPIO_PIN_SET); } // 批量写入数据用于GRAM填充或伽马表 void ILI7789_WriteDataBuffer(uint8_t *buf, uint16_t len) { HAL_GPIO_WritePin(LCD_DC_GPIO_Port, LCD_DC_Pin, GPIO_PIN_SET); HAL_GPIO_WritePin(LCD_CS_GPIO_Port, LCD_CS_Pin, GPIO_PIN_RESET); HAL_SPI_Transmit(hspi1, buf, len, HAL_MAX_DELAY); HAL_GPIO_WritePin(LCD_CS_GPIO_Port, LCD_CS_Pin, GPIO_PIN_SET); }逻辑说明HAL_SPI_Transmit()是阻塞式发送HAL_MAX_DELAY表示无限等待 TXE 标志。若实际项目需非阻塞应改用HAL_SPI_Transmit_IT()并配合回调函数但初始化阶段无需考虑实时性阻塞更可靠。LCD_DC_Pin和LCD_CS_Pin需在main.h中定义为对应 GPIO 引脚宏。3.3 完整初始化序列含精确延时与寄存器含义注释void ILI7789_Init(void) { // 1. 硬件复位若 RESET 引脚已接 MCU HAL_GPIO_WritePin(LCD_RST_GPIO_Port, LCD_RST_Pin, GPIO_PIN_RESET); HAL_Delay(20); // ≥10ms HAL_GPIO_WritePin(LCD_RST_GPIO_Port, LCD_RST_Pin, GPIO_PIN_SET); HAL_Delay(150); // 等待内部 PLL 锁定 // 2. 退出睡眠模式 ILI7789_WriteCmd(0x11); // Sleep Out HAL_Delay(120); // 必须 ≥120ms // 3. 设置像素格式16-bit RGB565 ILI7789_WriteCmd(0x3A); ILI7789_WriteData(0x05); // 16-bit // 4. 设置列地址X 轴范围0–239 ILI7789_WriteCmd(0x2A); ILI7789_WriteData(0x00); ILI7789_WriteData(0x00); ILI7789_WriteData(0x00); ILI7789_WriteData(0xEF); // 239 // 5. 设置行地址Y 轴范围0–319 ILI7789_WriteCmd(0x2B); ILI7789_WriteData(0x00); ILI7789_WriteData(0x00); ILI7789_WriteData(0x01); ILI7789_WriteData(0x3F); // 319 // 6. 伽马校正简化版仅写关键点 ILI7789_WriteCmd(0xE0); // Positive Gamma uint8_t gamma_p[] {0x0F,0x1F,0x1C,0x0C,0x0F,0x08,0x48,0x90, 0x8F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F}; ILI7789_WriteDataBuffer(gamma_p, 16); ILI7789_WriteCmd(0xE1); // Negative Gamma uint8_t gamma_n[] {0x0F,0x21,0x1F,0x0F,0x0F,0x0F,0x48,0x90, 0x8F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F}; ILI7789_WriteDataBuffer(gamma_n, 16); // 7. 设置显示方向竖屏0x60横屏0xA0 ILI7789_WriteCmd(0x36); ILI7789_WriteData(0x60); // MADCTL: MY0, MX1, MV0, ML0, RGB1 // 8. 开启显示 ILI7789_WriteCmd(0x29); // Display On }参数说明0x36寄存器MADCTL控制屏幕旋转与 RGB/BGR 顺序。0x60表示 X/Y 轴翻转组合为竖屏240×320若需横屏显示320×240应改为0xA00x05在0x3A寄存器中指定 16-bit 数据格式这是 ILI7789V 最常用模式兼容大多数嵌入式 GUI 库。3.4 四类延时策略对比与选型建议延时类型适用场景优点缺点本例程采用HAL_Delay()初始化阶段ms 级简单、精准、不占中断资源依赖 SysTick需配置好时基✅us_delay()寄存器间微秒级间隔如 1μs精度高基于 DWT 或 NOP占用 CPU不可在中断中调用❌未用HAL_TIM_Base_Start_IT()动态刷新时帧同步可触发 DMA 传输配置复杂增加中断负载⚠️进阶FreeRTOS vTaskDelay()RTOS 环境下任务调度延时不阻塞其他任务需移植 FreeRTOS❌裸机本例程全程使用HAL_Delay()因其在初始化阶段唯一且可靠。若后续需实现动画应迁移到定时器中断 DMA 方式。4. 实现 16-bit RGB565 图像填充与矩形绘制从裸数据到可验证的视觉反馈4.1 GRAM 写入协议与内存布局映射关系ILI7789V 的显存GRAM是线性排列的 16-bit 像素数组总容量为240 × 320 × 2 153,600 bytes。写入流程为① 发送0x2CMemory Write命令 → ② 连续发送像素数据每个像素 2 字节高位在前。关键约束不能跨行写入。例如设置区域为(0,0)到(239,319)后必须一次性写满 320 行 × 240 像素否则屏幕会错位。因此批量填充函数需严格按行组织数据。4.2 全屏纯色填充函数含错误检测与性能提示// 填充指定区域为单一颜色RGB565 格式R5:G6:B5 void ILI7789_FillRect(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t color) { uint32_t width x2 - x1 1; uint32_t height y2 - y1 1; uint32_t total_pixels width * height; // 1. 设置地址窗口 ILI7789_WriteCmd(0x2A); // Column Address Set ILI7789_WriteData(x1 8); ILI7789_WriteData(x1 0xFF); ILI7789_WriteData(x2 8); ILI7789_WriteData(x2 0xFF); ILI7789_WriteCmd(0x2B); // Page Address Set ILI7789_WriteData(y1 8); ILI7789_WriteData(y1 0xFF); ILI7789_WriteData(y2 8); ILI7789_WriteData(y2 0xFF); ILI7789_WriteCmd(0x2C); // Memory Write // 2. 准备颜色数据缓冲区避免栈溢出 #define MAX_FILL_SIZE 2048 // 一次最多填 1024 像素2KB static uint8_t fill_buf[MAX_FILL_SIZE]; uint16_t *p (uint16_t*)fill_buf; for (uint32_t i 0; i total_pixels; i) { p[i] color; if ((i 1) % (MAX_FILL_SIZE/2) 0 || i total_pixels - 1) { uint16_t send_len (i 1) % (MAX_FILL_SIZE/2) 0 ? MAX_FILL_SIZE/2 : (i 1) % (MAX_FILL_SIZE/2); HAL_GPIO_WritePin(LCD_DC_GPIO_Port, LCD_DC_Pin, GPIO_PIN_SET); HAL_GPIO_WritePin(LCD_CS_GPIO_Port, LCD_CS_Pin, GPIO_PIN_RESET); HAL_SPI_Transmit(hspi1, fill_buf, send_len * 2, HAL_MAX_DELAY); HAL_GPIO_WritePin(LCD_CS_GPIO_Port, LCD_CS_Pin, GPIO_PIN_SET); } } }逻辑说明该函数将color如0xF800表示纯红重复写入指定矩形区域。为防止大区域填充时栈溢出采用分块发送策略每 1024 像素2048 字节为一批调用HAL_SPI_Transmit()发送。0x2A/0x2B命令设定地址窗口后0x2C命令启动连续写入此时 CS 必须保持低电平直至整批数据发完。4.3 验证驱动是否成功的三步测试法复位后观察背光上电后 LED 引脚应输出 PWM 信号屏背光亮起若背光不亮检查 PB0 是否配置为 AF_PP 或 TIM 输出模式执行ILI7789_FillRect(0,0,239,319,0x001F)填充纯蓝B5若屏幕显示均匀蓝色证明初始化与 GRAM 写入通路正常叠加红色矩形ILI7789_FillRect(50,50,150,150,0xF800)若出现清晰红色方块说明坐标映射与区域设置无误。注意若第二步显示灰色或绿色大概率是0x3A寄存器未设为0x0516-bit或0x36寄存器方向配置错误导致 RGB 位域错位若第三步方块位置偏移需检查0x2A/0x2B命令中高低字节顺序是否颠倒。5. 排查 SPI 通信失败的五大硬核线索从示波器波形到寄存器快照5.1 使用逻辑分析仪捕获 SPI 波形的三个必检点当屏幕无反应时最高效的方式是用 Saleae 或 PulseView 抓取 SCK/SDA/CS/DC 四路信号信号正常特征异常表现与根因SCK方波频率 ≈ 8 MHz占空比 50%空闲为低电平频率远低于配置值 → APB2 时钟未使能无波形 → SPI 外设未初始化或引脚复用冲突SDA在 SCK 上升沿变化数据为 8-bit首字节应为0x11Sleep Out数据全为 0x00 → CS 未拉低或 MOSI 引脚虚焊数据乱码 → CPOL/CPHA 配置错误或线路干扰CS每次命令/数据传输前拉低传输结束后拉高低电平持续时间 ≥ 100ns始终高电平 →HAL_GPIO_WritePin()调用被注释或引脚宏定义错误脉冲过窄 → 未加HAL_Delay(1)DC发送命令时为低发送数据时为高切换时刻严格对齐 CS 下降沿DC 电平不变 →LCD_DC_Pin宏指向错误引脚切换延迟 → GPIO 输出速度未设为GPIO_SPEED_FREQ_HIGH提示在 CubeMX 的 GPIO 配置中PA4/PA3 必须设为GPIO_MODE_OUTPUT_PPGPIO_SPEED_FREQ_HIGH否则 DC 切换延迟可达数微秒破坏时序。5.2 STM32 调试寄存器快照法绕过 HAL 直查底层状态若无示波器可通过调试器读取 SPI 相关寄存器判断硬件状态寄存器F103偏移读取值含义故障指示SPI1-CR10x00bit0:SPI_ENABLEbit1:SPI_SPEbit2:SPI_SSIbit3:SPI_SSMSPI_ENABLE0→ 外设未使能SPI_SPE0→ 主模式未激活SPI1-SR0x0Cbit1:TXE发送缓冲空bit2:RXNE接收非空bit4:BSY忙TXE0→ 数据未发出BSY1且TXE0→ 通信卡死可能 CS 未拉低或从机未响应SPI1-DR0x0C发送/接收数据寄存器写入后TXE仍为 0 → 时钟未启动或 MOSI 引脚断开在 Keil 或 STM32CubeIDE 调试模式下打开Peripherals → SPI1 → CR1/SR/DR视图执行ILI7789_WriteCmd(0x11)后立即暂停观察SR寄存器中TXE是否由 1 变 0 再变 1——若始终为 1说明数据未真正发出。5.3 常见“伪成功”现象与真实原因对照表表象真实原因解决方案屏幕偶尔闪一下白光随后黑屏初始化序列中0x29Display On前缺少HAL_Delay(120)导致显示控制器未就绪在0x29前添加HAL_Delay(120)参考数据手册 Table 12 “Display ON Timing”花屏彩色噪点SDA 线过长未加 100Ω 串联电阻或与 SCK 平行走线 5cm 引起串扰PCB 布线时 SDA/SCK 间距 ≥ 3 倍线宽SCK 线加 33Ω 电阻SDA 线加 100Ω 电阻颜色严重偏色如红变黄0x36MADCTL寄存器设置错误或0x3AInterface Pixel Format未设为0x0516-bit用逻辑分析仪确认0x36命令后紧跟0x600x3A后紧跟0x05检查ILI7789_WriteData()是否传入正确字节初始化耗时超 5 秒HAL_Delay()依赖的 SysTick 未配置或SystemCoreClock未正确更新在main()开头添加HAL_Init(); SystemClock_Config();确保HAL_GetTick()返回值递增使用不同批次屏幕效果不一ILI7789V 存在 Rev.A/Rev.B 差异B 版本需额外写入0xB1Frame Rate Control寄存器查阅屏厂规格书若为 B 版本在0x11后插入ILI7789_WriteCmd(0xB1); ILI7789_WriteData(0x00);最后一行技术内容若需在 STM32F407 上启用 DMA 加速 GRAM 填充应配置hdma_spi1_tx通道将SPI1-DR地址设为外设地址显存缓冲区地址设为内存地址并在HAL_SPI_Transmit_DMA()调用前确保hspi1.State为HAL_SPI_STATE_READY。本文还有配套的精品资源点击获取
返回列表