STM32F4驱动2.8寸TFTLCD屏保姆级教程(基于ILI9341控制器与FSMC)

张开发
2026/4/21 22:16:22 15 分钟阅读

分享文章

STM32F4驱动2.8寸TFTLCD屏保姆级教程(基于ILI9341控制器与FSMC)
STM32F4驱动2.8寸TFTLCD屏全流程实战指南ILI9341FSMC拿到一块2.8寸TFTLCD屏和STM32F407开发板时很多初学者会被硬件连接、FSMC配置和驱动初始化这些环节卡住。本文将用最直白的语言带你从焊接排针开始一步步完成屏幕驱动最终实现彩色图形显示。不同于单纯罗列寄存器配置的教程这里会重点解释每个操作背后的硬件原理并分享实际调试中可能遇到的坑点解决方案。1. 硬件准备与连接1.1 物料清单检查在开始前请确认你已准备好以下硬件STM32F407ZGT6最小系统板其他F4系列也可2.8寸TFTLCD模块ILI9341控制器杜邦线若干建议使用排线减少干扰万用表用于检查线路通断逻辑分析仪可选用于调试时序特别注意不同厂商的LCD模块引脚定义可能有差异务必核对你的屏幕规格书。正点原子2.8寸屏通常采用16位8080并行接口。1.2 引脚对应关系ILI9341的8080接口需要与STM32的FSMC总线正确对接。以下是关键信号线的连接方式LCD引脚信号类型STM32F4对应引脚备注CS片选FSMC_NE1 (PD7)Bank1片选WR写使能FSMC_NWE (PD5)低电平有效RD读使能FSMC_NOE (PD4)低电平有效RS数据/命令FSMC_A18 (PD13)地址线复用DB15-DB0数据总线FSMC_D15-D016位并行传输RST硬件复位NRST或独立IO建议接MCU复位电路BL_CTRL背光控制任意GPIO需PWM调光可接定时器通道// 示例背光控制代码PA8为例 #define LCD_BL_PIN GPIO_PIN_8 #define LCD_BL_PORT GPIOA void LCD_Backlight_Enable(void) { HAL_GPIO_WritePin(LCD_BL_PORT, LCD_BL_PIN, GPIO_PIN_SET); }1.3 硬件连接验证完成接线后建议进行以下检查电源测试用万用表测量LCD模块的VCC与GND之间电压通常3.3V信号线通断依次检查各控制线是否连通数据线交叉确认DB0-DB15没有错位连接常见问题若屏幕出现白屏但背光亮起很可能是数据线接反或FSMC配置错误。2. FSMC接口配置详解2.1 FSMC基础概念FSMCFlexible Static Memory Controller是STM32用于扩展外部存储器的外设其特性非常适合驱动8080接口的LCD支持多种存储器类型NOR/PSRAM/SRAM可编程时序参数建立/保持/维持时间最大16位数据总线宽度对于ILI9341我们将其配置为SRAM接口模式Bank1区域0x60000000起始地址。2.2 CubeMX配置步骤启用FSMC控制器选择SRAM模式配置Bank1子区域通常选NE1对应的Bank1设置数据宽度为16位调整关键时序参数单位HCLK周期参数推荐值说明Address Setup1地址建立时间Data Setup2数据建立时间Bus Turnaround0总线转换周期非必须// 生成的FSMC初始化代码示例HAL库 void MX_FSMC_Init(void) { FSMC_NORSRAM_TimingTypeDef Timing {0}; hfsmc1.Instance FSMC_Bank1_NORSRAM1; Timing.AddressSetupTime 1; Timing.AddressHoldTime 0; Timing.DataSetupTime 2; Timing.BusTurnAroundDuration 0; Timing.CLKDivision 0; Timing.DataLatency 0; Timing.AccessMode FSMC_ACCESS_MODE_A; HAL_SRAM_Init(hsram1, Timing, Timing); }2.3 地址映射技巧利用FSMC的地址线特性我们可以通过不同地址访问LCD的命令和数据寄存器命令寄存器地址0x60000000数据寄存器地址0x60020000A181#define LCD_CMD_ADDR (0x60000000) #define LCD_DATA_ADDR (0x60020000) #define LCD_CMD (*(__IO uint16_t *)LCD_CMD_ADDR) #define LCD_DATA (*(__IO uint16_t *)LCD_DATA_ADDR)3. ILI9341驱动实现3.1 初始化序列解析ILI9341需要一组特定的命令序列进行初始化。以下是关键命令说明软复位命令0x01等待至少5ms让控制器完成复位电源控制A0xCB设置内部稳压器参数像素格式设置0x3A配置为16位RGB565格式内存访问控制0x36控制显示方向详见下文// 示例初始化代码片段 void ILI9341_Init(void) { LCD_WriteCmd(0x01); // 软复位 HAL_Delay(120); // 等待复位完成 LCD_WriteCmd(0xCF); // 电源控制B LCD_WriteData(0x00); LCD_WriteData(0xC1); LCD_WriteData(0x30); // ... 其他初始化命令 }3.2 显示方向控制通过内存访问控制命令0x36可以设置屏幕的显示方向各bit功能如下Bit名称功能7MY垂直镜像1倒置6MX水平镜像1右到左5MV行列交换竖屏模式4ML垂直刷新顺序3BGR颜色顺序1BGR, 0RGB常用配置组合// 横向显示默认方向 LCD_WriteCmd(0x36); LCD_WriteData(0x08); // MY0, MX0, MV0, BGR1 // 竖向显示旋转90度 LCD_WriteCmd(0x36); LCD_WriteData(0x68); // MY0, MX1, MV1, BGR13.3 基本绘图函数实现核心绘图功能需要三个基础函数设置坐标范围void ILI9341_SetWindow(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2) { LCD_WriteCmd(0x2A); // 列地址设置 LCD_WriteData(x1 8); LCD_WriteData(x1 0xFF); LCD_WriteData(x2 8); LCD_WriteData(x2 0xFF); LCD_WriteCmd(0x2B); // 行地址设置 LCD_WriteData(y1 8); LCD_WriteData(y1 0xFF); LCD_WriteData(y2 8); LCD_WriteData(y2 0xFF); LCD_WriteCmd(0x2C); // 写入GRAM }单点绘制void ILI9341_DrawPixel(uint16_t x, uint16_t y, uint16_t color) { if(x 240 || y 320) return; // 边界检查 ILI9341_SetWindow(x, y, x, y); LCD_WriteData(color); }矩形填充优化版void ILI9341_FillRect(uint16_t x, uint16_t y, uint16_t w, uint16_t h, uint16_t color) { uint32_t pixels (uint32_t)w * h; ILI9341_SetWindow(x, y, xw-1, yh-1); while(pixels--) { LCD_WriteData(color); } }4. 性能优化与高级功能4.1 DMA加速图形绘制当需要刷新大面积区域时使用DMA可以显著提升性能// 配置DMA以DMA2 Stream0为例 void DMA_Config(void) { __HAL_RCC_DMA2_CLK_ENABLE(); hdma_memtomem_dma2_stream0.Instance DMA2_Stream0; hdma_memtomem_dma2_stream0.Init.Channel DMA_CHANNEL_0; hdma_memtomem_dma2_stream0.Init.Direction DMA_MEMORY_TO_MEMORY; hdma_memtomem_dma2_stream0.Init.PeriphInc DMA_PINC_ENABLE; hdma_memtomem_dma2_stream0.Init.MemInc DMA_MINC_ENABLE; hdma_memtomem_dma2_stream0.Init.PeriphDataAlignment DMA_PDATAALIGN_HALFWORD; hdma_memtomem_dma2_stream0.Init.MemDataAlignment DMA_MDATAALIGN_HALFWORD; hdma_memtomem_dma2_stream0.Init.Mode DMA_NORMAL; hdma_memtomem_dma2_stream0.Init.Priority DMA_PRIORITY_HIGH; HAL_DMA_Init(hdma_memtomem_dma2_stream0); } // DMA填充矩形 void ILI9341_FillRect_DMA(uint16_t x, uint16_t y, uint16_t w, uint16_t h, uint16_t color) { static uint16_t buffer[320]; // 最大行宽 for(int i0; iw; i) buffer[i] color; ILI9341_SetWindow(x, y, xw-1, yh-1); for(int row0; rowh; row) { HAL_DMA_Start(hdma_memtomem_dma2_stream0, (uint32_t)buffer, (uint32_t)LCD_DATA_ADDR, w); HAL_DMA_PollForTransfer(hdma_memtomem_dma2_stream0, HAL_DMA_FULL_TRANSFER, 10); } }4.2 双缓冲技术实现对于动画显示可以配置两个显示缓冲区交替使用在内存中分配两个帧缓冲区uint16_t frameBuffer1[240][320]; uint16_t frameBuffer2[240][320]; uint16_t *activeBuffer frameBuffer1;实现缓冲区切换函数void SwapBuffers(void) { activeBuffer (activeBuffer frameBuffer1) ? frameBuffer2 : frameBuffer1; ILI9341_SetWindow(0, 0, 239, 319); HAL_DMA_Start(hdma_memtomem_dma2_stream0, (uint32_t)activeBuffer, (uint32_t)LCD_DATA_ADDR, 240*320); }4.3 触摸屏集成对于带触摸功能的屏幕通常还需要处理XPT2046等触摸控制器uint8_t TP_Read(void) { uint16_t x, y; // 读取触摸坐标SPI接口 // ... if(触摸有效) { // 将物理坐标转换为屏幕坐标 *x_pos (x - CAL_X_MIN) * 240 / (CAL_X_MAX - CAL_X_MIN); *y_pos (y - CAL_Y_MIN) * 320 / (CAL_Y_MAX - CAL_Y_MIN); return 1; } return 0; }5. 常见问题排查5.1 屏幕无任何显示检查步骤确认背光是否开启测量背光引脚电压检查复位信号是否正常应有至少10ms低电平用逻辑分析仪抓取FSMC时序波形尝试读取LCD ID应返回0x93415.2 显示颜色异常可能原因数据线接错特别是高低字节混接像素格式配置错误确认是RGB565BGR/RGB顺序设置不当5.3 显示内容错位解决方法确认内存访问控制寄存器0x36配置正确检查SetWindow函数的坐标参数传递顺序验证FSMC地址线特别是RS线连接调试技巧绘制测试图案帮助定位问题// 绘制网格测试图 void DrawTestPattern(void) { for(int y0; y320; y) { for(int x0; x240; x) { uint16_t color 0; if(x % 20 10) color | 0xF800; // 红色条纹 if(y % 20 10) color | 0x07E0; // 绿色条纹 ILI9341_DrawPixel(x, y, color); } } }

更多文章