恒美微站
首页
关于我们
建站服务
主题模板
案例展示
资讯中心
联系我们
STM32F429 LTDC驱动RGB屏:从时序配置到SDRAM帧缓冲实战
首页
资讯中心
/
STM32F429 LTDC驱动RGB屏:从时序配置到SDRAM帧缓冲实战
STM32F429 LTDC驱动RGB屏:从时序配置到SDRAM帧缓冲实战
发布时间:2026/9/12 2:18:57
简介面向基于STM32F4系列微控制器的嵌入式开发者这份工程示例演示了如何借助STM32F429的LTDC外设驱动7英寸、1024×600分辨率的RGB液晶屏并同步支持触摸屏输入。实现采用纯寄存器操作方式开发者可直接面对内存映射和硬件接口通过配置帧缓冲区、行场同步时序、RGB565/ARGB8888色彩格式、图层透明度与混合模式、VSYNC中断等底层参数深入掌握LTDC显示链路的工作机制。工程代码按LCD显示、SDRAM帧缓冲、触摸控制、延时定时、按键检测、看门狗等功能模块拆分结构清晰便于按需裁剪和移植到其他STM32F4系列芯片。压缩包共43个文件以C源文件和头文件为主配合Keil工程文件、启动汇编文件、hex固件与批处理辅助脚本整体仅235KB导入工程即可直接编译验证。目前已有1003人学习下载对需要快速搭建RGB屏显示与触摸联调环境的开发者而言这份寄存器级参考代码兼具学习与二次开发价值。1. 在 STM32F429 上点不亮 RGB 屏之前先承认 LTDC 是套组合拳同样是接屏幕SPI OLED 只是把一帧数据挪进 SRAM而 7 寸 1024×600 的 RGB 屏一旦接到 STM32F429 的 LTDC 上就意味着一件事微控制器不能再“想到哪写到哪”而是要承诺以固定像素时钟持续输出一整条显存总线。这个资源把 HAL 抽象拆掉了用寄存器从头配置 LTDC、SDRAM、GPIO 和背光既不依赖库函数的初始化顺序也没有“默认参数”替你兜底。适合两种人一是把 7 寸屏当产品核心却总在花屏、偏移、黑屏里打转的嵌入式工程师二是想把手头 F4 板子接 40pin LCD 接口却不知道从哪查手册的人。读完后你至少能回答三个问题像素时钟到底从哪里来帧缓冲为什么必须放在 SDRAM以及层配置里的 width/pitch 是不是可以直接写 1024。2. LTDC 与 RGB 屏的握手先填对同步时序再谈画点2.1 从屏参表换算 LTDC 寄存器HBP、HFP、HSYNC 不只是四个数字RGB 屏不需要像 SPI 屏那样发“写像素”命令它要求主机持续输出行列同步信号、数据使能 DE 和像素数据。LTDC 正是为此设计的控制器但它不会自动识别你的屏你需要把屏厂 datasheet 里的 blanking 参数填进寄存器。7 寸 1024×600 屏的典型时序参数如下表具体数值必须以你手头屏型号为准。参数含义典型值HSYNC行同步脉冲宽度30 像素时钟HBP行后肩160 像素时钟HFP行前肩160 像素时钟VSYNC帧同步脉冲宽度13 行VBP帧后肩23 行VFP帧前肩12 行Pixel Clock像素时钟48~51.2 MHz很多初次接触的人把“有效区宽高”直接填进AWCR却忘记 LTDC 内部计数是从 0 开始的。实际应该填参数值减 1。而总周期是HSYNC HBP HACT HFP不是单纯把横向的 4 个参数相加后填一个“分辨率”就能了事。行方向总周期 30 160 1024 160 1374帧方向总周期 13 23 600 12 648。这个数值决定像素时钟与行频、场频的关系也就是你最终在屏幕点亮后能用示波器验证的那个“心跳”。2.2 用寄存器把时序写进 LTDC同步宽度、后肩、有效区和总宽下面的代码是典型的 LTDC 同步时序配置顺序。资源工程里没有引入 HAL直接访问LTDC外设寄存器所有时序位都和 2.1 的参数一一对应。void LTDC_Timing_Config(void) { // SSCR行同步宽 HSYNC30帧同步宽 VSYNC13均减 1 LTDC-SSCR (30 - 1) | ((13 - 1) 16); // BPCR后肩 HBP160VBP23 LTDC-BPCR (160 - 1) | ((23 - 1) 16); // AWCR有效区是 1024 x 600 LTDC-AWCR (1024 - 1) | ((600 - 1) 16); // TWCR行总周期 1374帧总周期 648 LTDC-TWCR (1374 - 1) | ((648 - 1) 16); }四个寄存器分别对应同步脉冲、后沿、有效区和总周期。SSCR决定同步脉冲宽度BPCR决定同步结束后等待多久才开始有效数据AWCR是指真正要显示的像素区域TWCR则是整条扫描线或整个帧的绝对长度。这样拆开后你会发现“花屏”往往不是因为 DCLK 抖动而是TWCR比实际时序少算了一个像素导致数据偏移成斜纹。接着要配置像素时钟极性和 DE 极性。这一项容易被忽略尤其是从别的工程抄初始化代码时。LTDC 的GCR寄存器里PCPOL控制采样沿DEPOL控制 DE 有效电平。多数 RGB 屏在 DE 高有效、上升沿采样时工作正常少数屏要求下降沿。如果你点亮后屏幕偏色、有细密横纹优先检查这里。// PCPOL0上升沿采样DEPOL0DE 高有效 LTDC-GCR ~(1u 1); LTDC-GCR ~(1u 3);这段代码的作用是让 LTDC 在普通 RGB 逻辑电平下工作。GCR位 1 是像素时钟极性位 3 是 DE 极性。颜色格式、抖动使能等也在这个寄存器里但初调时保持默认更稳妥。2.3 像素时钟 PLLSAI 从哪里来分频器不是随便填的STM32F429 的系统时钟 PLL 用于产生 HCLKLTDC 的像素时钟则由另一个 PLLSAI 提供。很多工程在 SDRAM 工作正常、GPIO 也都复用正确的情况下屏依然黑就是因为 LTDC 时钟没使能或者频率不对。PLLSAI 不是把晶振频率直接搬给 LTDC而是经过一个 VCO 再分频。void LTDC_PixelClock_Config(void) { // 假设 HSE25MHz // PLLSAIM25PLLSAIN192PLLSAIR4 // VCO 25MHz / 25 * 192 192MHz // LTDC clock VCO / 4 48MHz RCC-PLLSAICFGR (25u 28) | (192u 6) | (25u 0); // 使能 PLLSAI 并等待锁定 RCC-CR | RCC_CR_PLLSAION; while ((RCC-CR RCC_CR_PLLSAIRDY) 0) { } // LTDC 时钟不分频 RCC-DCKCFGR ~RCC_DCKCFGR_PLLSAIDIVR; }这段配置让 LTDC 得到 48MHz 像素时钟。PLLSAICFGR的高 7 位是分频系数 N低 6 位是倍频系数 M位 27:24 是 PLLSAIR。常见错误是只改了PLLSAIN而不动PLLSAIM导致 VCO 频率漂移刷新率也随之跑偏。如果你的屏显示偏右、偏下超过一两个像素也可以用手头屏的实际像素时钟反推 PLLSAIR不需要改TWCR去“找齐”。3. 把 40pin LCD 接口接到 F429GPIO 复用、DE 极性与背光 PWM3.1 信号分组与 F429 的 AF14 映射7 寸 LCD 的 40pin 接口通常会引出 RGB 数据、HSYNC、VSYNC、DE、PCLK、RESET、背光控制以及电源。F429 的 LTDC 引脚复用功能是 AF14但不是说任何 GPIO 都能接任意颜色位。你要先在 datasheet 里查每个引脚对应的 AF14 信号再决定用 RGB565 还是 RGB888。资源工程按寄存器驱动方式配置GPIO 初始化时用MODER选备用功能用AFRL/AFRH写入复用编号 14。void LCD_GPIO_Init(void) { // 使能对应 GPIO 时钟这里以 GPIOA 和 GPIOB 为例 RCC-AHB1ENR | RCC_AHB1ENR_GPIOAEN | RCC_AHB1ENR_GPIOBEN; // 将 PB0、PB1 设为 AF14作为 LTDC_R3、LTDC_R4 GPIOB-MODER ~(0x3u 0); GPIOB-MODER | (0x2u 0); GPIOB-AFR[0] | (0xEu 0); // AF140b1110 // 高速输出避免像素边界变糊 GPIOB-OSPEEDR | (0x3u 0); // HSYNC/VSYNC/DE/PCLK 同理全部设为 AF14 }GPIO 速度要和像素时钟匹配。48MHz 像素时钟下如果OSPEEDR还停留在低速档显示屏上会出现色彩渐变边界发虚的现象尤其是在黑白跳变的竖线边缘。每个引脚的复用模式和速度都要配置不能只配置数据线而忽略同步线因为 LTDC 的同步信号引脚阻抗不匹配会造成抖动图像偶发性偏移。从板级设计角度40pin 接口上相邻数据线之间如果没有地线隔离高频信号容易串扰。软件上能做的补救是降低OSPEEDR到合适档位以及让 LTDC 时钟极性选择下降沿采样避开数据线上的振铃区间。这些都是硬件板子画完之后才有的调试手段但在初始化代码里留好配置位比重新打板便宜得多。3.2 背光 PWM 与 LCD 亮度控制RGB 屏通常没有自带背光驱动需要外接升压电路或直接控制 LED 电流。软件上不会去控制电流而是通过 PWM 占空比调亮度。F429 里用定时器产生 PWM 非常常见工程HARDWARE/TIMER里就是给这类用途准备的基础。void LCD_BackLight_Init(void) { // 使能 TIM4 时钟 RCC-APB1ENR | RCC_APB1ENR_TIM4EN; // 预分频 99计数到 999PWM 频率为 APB1 时钟的 1/100000 TIM4-PSC 99; TIM4-ARR 999; // CH1 PWM 模式 1输出比较预装载 TIM4-CCMR1 | TIM_CCMR1_OC1M_1 | TIM_CCMR1_OC1M_2; TIM4-CCMR1 | TIM_CCMR1_OC1PE; // 使能 CH1 输出 TIM4-CCER | TIM_CCER_CC1E; // 初始亮度 50% TIM4-CCR1 500; // 启动定时器 TIM4-CR1 | TIM_CR1_CEN; }CCR1值决定占空比0 是全暗999 是全亮。如果背光 PWM 频率太低人眼会看到闪烁常见处理是 PWM 频率设置在 1kHz 以上20kHz 以下。部分屏的背光控制脚是低电平时点亮这时CCER里要配置CC1P极性或者直接让CCR1含义取反具体看屏的背光使能脚是接在 LED 阳极还是阴极。3.3 LCD 复位与上电顺序RGB 屏的控制器也需要复位但和 SPI 屏不同LTDC 初始化必须在 LCD 面板上电完成、复位释放之后进行。如果先开 LTDC 再拉屏的 RESET屏控制器可能锁在一个未定义状态。// 假设 RESET 引脚是 PE1低电平复位 GPIOE-BSRR (1u 1); // RESET 拉高 delay_ms(20); GPIOE-BSRR (1u 1) 16; // RESET 拉低 delay_ms(20); GPIOE-BSRR (1u 1); // 释放复位 delay_ms(50);这个延时不是随便加的。许多 7 寸屏的电源和复位时序要求 VCC 稳定后至少 10ms 再拉高 RESET随后再等 50ms 让面板内部控制逻辑和电荷泵稳定。如果你在点亮过程中反复出现“第一次黑屏按复位后正常”大概率是上电顺序没做对。4. 帧缓冲选址1024×600 的三字节彩色是不能交给 RAM 的4.1 内存占用与色彩格式选择在配置 LTDC 层之前必须先决定帧缓冲格式。同一块屏RGB565、RGB888、ARGB8888 的显存占用差很多。STM32F429 片内 SRAM 一共 256KB而 1024×600 的 RGB565 一帧就要 1.17MBARGB8888 更是达到 2.34MB。片内根本放不下所以外部 SDRAM 是必须的。色彩格式每像素位宽一帧 1024×600 占用RGB56516 bit1,228,800 B约 1.17 MiBRGB88824 bit1,843,200 B约 1.76 MiBARGB888832 bit2,457,600 B约 2.34 MiB字体、图标和 UI 控件都放在片内 Flash 或外部 SPI Flash运行时的画布放 SDRAM。这样安排下CPU 写一帧再切一帧LTDC 控制器持续从 SDRAM 读取二者互不阻塞。对 7 寸屏来说RGB565 在色彩过渡上会有轻微色阶但资源工程里默认 RGB565 的原因很简单显存减半、带宽减半对 SDRAM 访问 latency 的容忍度也更高。4.2 FMC 外接 SDRAM 初始化不是把地址指过去就能用SDRAM 上电之后必须经历预充电、自动刷新、配置模式寄存器三步否则 LTDC 从里面读到的是随机数据。FMC 控制器提供了FMC_Bank5_6寄存器组其中SDCR1配置行列宽度、突发长度和 CAS LatencySDTR1配置时序延迟SDCMCR下发命令。void SDRAM_Init(void) { // 以 16bit SDRAM、12 列地址、13 行地址为例 FMC_Bank5_6-SDCR1 (0x2u 12) | /* SDCLK HCLK/2 */ (0x2u 7) | /* 行地址 13 bit */ (0x1u 4) | /* 列地址 12 bit */ (0x3u 9); /* CAS 3 */ // 配置加载模式、刷新率等时序参数 FMC_Bank5_6-SDTR1 (0x4u 0) | /* TMRD */ (0x7u 4) | /* TXSR */ (0x4u 8) | /* TRAS */ (0x7u 12) | /* TRC */ (0x2u 16) | /* TWR */ (0x2u 20) | /* TRP */ (0x2u 24); /* TRCD */ // 发送 NOP 命令 FMC_Bank5_6-SDCMCR (0x1u 0); delay_ms(1); // 预充电 FMC_Bank5_6-SDCMCR (0x2u 0); delay_ms(1); // 连续 8 次自动刷新 FMC_Bank5_6-SDCMCR (0x3u 0) | (0x7u 5); delay_ms(1); // 加载模式寄存器 FMC_Bank5_6-SDCMCR (0x4u 0) | (0x13u 9); delay_ms(1); // 使能自动刷新 FMC_Bank5_6-SDCR1 | (0x1u 1); }这里有个很容易踩的坑SDTR1里的数值单位是以 FMC 时钟周期为单位的具体值由 SDRAM 芯片的 tRCD、tRP 等参数和HCLK共同决定。如果你把板子主频从 168MHz 改到 180MHzHCLK变了但SDTR1没同步调整SDRAM 读写就会偶发性失败。表现是屏幕大多数时候正常一旦画面大面积刷新会出现随机的整块噪点。FMC SDRAM 的地址映射从0xC0000000开始。如果你的板子用的是 Bank2则起始地址是0xD0000000。资源工程里通常只在system_stm32f4xx.c里改外部内存起始地址LTDC 层基址只要和 SDRAM 初始化对应的 Bank 一致即可。4.3 把帧缓冲地址告诉 LTDC 层LTDC 每个层都有独立的帧缓冲地址寄存器CFBAR。我们需要把已经初始化好的 SDRAM 首地址写入这个寄存器并告诉层控制器每行有多少字节、每帧有多少行。// 帧缓冲地址这里以 0xC0000000 为例 LTDC_Layer1-CFBAR 0xC0000000; // 行有效像素宽度 LTDC_Layer1-CACR 1024; // 每行字节数 宽度 * 2RGB565 LTDC_Layer1-CACR (1024 * 2) / 8; // 层大小寄存器行数 600行宽 1024 LTDC_Layer1-CLUTS (600 16) | (1024);注意CACR和CLUTS这两个名字是示意性的不同固件库里的命名有差异。关键是理解三个参数像素行宽、帧缓冲 pitch以 32bit 字为单位时通常是 8 的倍数、窗口高度。1024×2 字节本身就是 2048是 8 的倍数所以不用手动补齐。如果你改用 RGB888每行字节数是 3072也是 8 的倍数但如果是 900×600 这类不凑 8 的宽度就要把 pitch 向上取整到 8 的倍数否则行末会出现一条斜切错位。层配置完成后还必须在LTDC-GCR里使能 LTDC然后等待至少一个帧周期。很多人只配置LTDC_Layer1而忘记使能 LTDC 本身结果是 LTDC 中断不产生屏幕保持黑屏。5. 触摸屏接入与坐标校正从原始 ADC 到 UI 坐标5.1 工程里的 TPAD 不是触摸屏别把两个概念混在一起打开HARDWARE目录时会看到TPAD这个文件夹但它对应的是 STM32 的电容触摸按键不是一个触摸屏控制器。真正的 7 寸 RGB 屏触摸面板有两种主流接口电阻屏通过 SPI 采样典型芯片是 XPT2046电容屏通过 I2C 读取典型芯片是 GT911。资源工程没有随屏附带触摸驱动需要你根据屏的型号把手写驱动接进来。好消息是触摸屏的坐标读取和屏的显示驱动是松耦合的LTDC 初始化完成后触摸驱动可以独立挂到任意 I2C 或 SPI 总线上。如果你买的是 “40pin LCD 接口 触摸排线” 组合屏触摸排线上通常包含SDA、SCL、INT、RST和 3.3V 电源。GT911 在复位后根据INT高低电平选择 I2C 地址常见是0x14或0x5D。软件上必须先给触摸芯片复位再按屏厂给的寄存器地址读取触点数据。5.2 读取触摸点GT911 的坐标寄存器流GT911 的坐标报告放在一组连续寄存器里读取顺序是先读状态寄存器确认有触摸再读坐标寄存器。下面的代码是一个最小读点流程。// 读取 GT911 状态寄存器地址 0x814E uint8_t status I2C_ReadReg(GT_ADDR, 0x814E); if (status 0x80) { // 第 7 位表示 buffer 已准备好 uint8_t touch_buf[4]; // 读取第一点的 x/y 坐标寄存器 0x8150 起 I2C_ReadRegs(GT_ADDR, 0x8150, touch_buf, 4); uint16_t x (touch_buf[0] 0x0F) | (touch_buf[1] 8); uint16_t y (touch_buf[2] 0x0F) | (touch_buf[3] 8); // 读完后写 0 清状态 I2C_WriteReg(GT_ADDR, 0x814E, 0x00); }GT911 的单点坐标实际只用低 12 位所以touch_buf[0]的高 4 位要屏蔽。I2C_ReadRegs这类底层函数可以基于项目里的软件 I2C也可以直接用HARDWARE里的 delay 和 GPIO 模拟。这里没有用中断是因为电容屏自带触点跟踪轮询已经能满足大多数 UI 需求。如果你追求功耗控制可以引入INT中断在触摸按下时才通过 EXTI 触发读取。5.3 坐标校准三点校准把所有误差放进一个线性映射触摸屏的 ADC 坐标和 LCD 像素坐标之间不是简单的倍率换算屏贴合偏移、触摸面板旋转和放大电阻差异都会造成读数偏差。最常用的校准方式是三点校准假设 X 方向映射为screen_x a0 * raw_x b0 * raw_y c0Y 方向同理。先让用户依次点击屏幕上的三个校准点解出六个系数。typedef struct { int a0, b0, c0; // X 方向映射系数 int a1, b1, c1; // Y 方向映射系数 } TouchCal_t; void Touch_MapPoint(TouchCal_t *cal, int raw_x, int raw_y, int *px, int *py) { *px (cal-a0 * raw_x cal-b0 * raw_y cal-c0) 16; *py (cal-a1 * raw_x cal-b1 * raw_y cal-c1) 16; }用右移 16 位代替浮点除法在 Cortex-M4 上可以避免浮点库开销。系数本身通过解三元一次方程得到校准点选取四个角落和中心点取三次采样平均。实际项目中很多人把触摸芯片的原始坐标直接当作像素坐标用结果 UI 按钮总是点偏。加一个校准函数整体体验会立刻从“能出图”变成“可点准”。电阻屏 XPT2046 的读取方式更简单它通过 SPI 发一个 8bit 命令例如0x90表示测 X0xD0表示测 Y返回 12bit ADC。校准思路完全一样但要注意电阻屏需要做阈值滤波手指按下的瞬间会有抖动通常连续读 4 次去掉最大值最小值再取平均。6. 用 VSYNC 中断验证刷新率再让 RGB 屏快速显示中文6.1 帧中断测量看 PB3 的翻转频率对不对屏点亮后第一件事不是画 UI而是验证 LTDC 实际刷新率是否接近你计算的帧频。打开 LTDC 的行中断或 VSYNC 中断在中断服务函数里翻转一个 GPIO用示波器量 GPIO 频率这是最直接的板级验证手段。void LTDC_IRQHandler(void) { if (LTDC-ISR LTDC_ISR_LI) { // 行中断标志 GPIOB-ODR ^ (1u 3); // PB3 翻转一次 LTDC-ICR LTDC_ICR_CLI; // 清除中断标志 } }在LTDC_Timing_Config()之后使能行中断并配置 NVIC。如果你按 2.1 里的总周期计算实际的脉冲频率应该是像素时钟 / 行总周期 / 帧总周期。比如 48MHz、1374 行、648 帧周期帧率大约 53Hz。如果示波器看到的频率明显偏低通常是 PLLSAI 输出没达到预期而不是 LTDC 时序错了。6.2 快速显示中文行偏移决定可写速度RGB 屏显示中文最自然的做法是使用全字库点阵把字模放在 Flash 里。16×16 点阵的中文字模一个字符占 32 字节UI 上无需配置外接 GBK 字库芯片只要把字模数据按行列写入显存即可。与 SPI OLED 需要逐字节往外传不同这里可以直接用行指针向 SDRAM 写入连续内存。void LCD_DrawFont16(uint16_t *buf, int x, int y, const uint8_t *font, uint16_t color) { for (int row 0; row 16; row) { uint8_t lo font[row * 2]; uint8_t hi font[row * 2 1]; // buf 指向 SDRAM 帧缓冲首地址1024 为屏宽 uint16_t *line buf (y row) * 1024 x; for (int bit 0; bit 8; bit) { if (lo (0x80 bit)) line[bit] color; } for (int bit 0; bit 8; bit) { if (hi (0x80 bit)) line[bit 8] color; } } }这套写法避免了逐像素调用绘制函数让 16 个像素点一次性落在连续显存区域。由于 LTDC 总会自动从帧缓冲刷新屏幕写显存后的下一个行周期新字符就会出现在物理屏上不需要额外刷新指令。这也是 RGB 屏相比 SPI OLED 在显示中文时可以更流畅的原因大量字模数据走 SDRAM 总线而不是被限制在 10MHz 的 SPI 上。最后说一个常见的性能隐患如果你在启用 D-Cache 的工程里调试显存更新CPU 写入的 SDRAM 数据可能还留在 Cache 里而 LTDC 直接读物理内存画面会出现局部花屏。遇到这种问题可以先直接关闭 D-Cache或者对显存区域执行SCB_CleanDCache_by_Addr刷新写入。这个细节和 LTDC 时序无关但往往会在验证刷新率之后成为下一块绊脚石。本文还有配套的精品资源点击获取