资讯动态

STM32F407驱动3.5寸TFT电阻触摸屏实战:FSMC与触摸校准

发布时间:2026/10/27 8:36:03 来源:尧图企业网站定制
简介面向STM32F407及F4系列单片机的三点五寸液晶触摸屏驱动代码包完整覆盖三百二十乘四百八十分辨率下的图像显示与电阻触摸交互适合正在学习嵌入式显示驱动和界面开发的工程师。资源共包含二百三十六个文件其中一百二十三个头文件、一百零八个源文件占主体另有工程配置文件、链接脚本、固件文件和说明文档压缩包仅一点六七兆字节可直接导入集成开发环境编译运行。代码基于官方硬件抽象层编写从引脚复用配置、液晶控制器初始化、串行或并行接口时序到帧缓存输出和直接存储器访问传输均有实现同时包括触摸屏的通道采样、坐标校准与事件响应模块划分清楚便于按需裁剪。已有三百零三人学习下载适合用作快速原型验证或二次开发基础。通过研读源码可以掌握驱动大尺寸电阻触摸屏的时序要点、总线配置和调试方法并为后续添加图形菜单或控件交互提供稳定起点。1. 从一块3.5寸屏说起为什么STM32F407是驱动它的主力选手在嵌入式项目里3.5寸、320x480分辨率的TFT LCD电阻触摸屏是出货量极大的一个品类。它比1.8寸、2.4寸的小屏多出足够的显示面积能呈现相对完整的交互界面又比7寸、10寸屏在成本和驱动难度上低一个量级。而STM32F407之所以成为驱动这类屏幕的常见选择并不是因为它主频高、跑得快而是因为它内置了FSMC灵活的静态存储控制器外设。这个外设可以直接把LCD当成一块外部SRAM来访问写像素点就像写内存地址一样不需要用GPIO模拟时序也不需要占用DMA资源。这就是很多工控HMI、仪器仪表、手持设备方案里出现“STM32F407 3.5寸电阻屏”这对组合的根本原因。不过把FSMC接到TFT LCD上只是第一步。屏幕背后的初始化时序、电阻触摸屏的坐标采集和校准、以及如何在320x480的分辨率下保持流畅的刷新率才是真正决定项目能否落地的关键。本文就从方案选型、硬件接线、底层驱动、触摸校准到性能优化把这条完整链路拆开讲清楚。读者无论是第一次接触FSMC驱动LCD还是想在现有F4工程里加入触摸功能都可以跟着下面的步骤走通。2. FSMC驱动TFT LCD把屏幕映射成内存的硬件原理2.1 为什么选FSMC而不是GPIO模拟用GPIO模拟8080并口时序当然可以驱动TFT LCD很多开发板例程就是这么做的。但这种方式有两个明显的短板。第一GPIO翻转速度受软件循环限制即使主频跑到168MHz一次完整的写周期也要几十个时钟周期刷新一帧320x480的画面会明显卡顿。第二GPIO模拟时序会长期占用CPU导致主循环里其他任务比如触摸扫描、通信处理难以获得稳定的执行时间。FSMC则完全不同。STM32F407的FSMC可以配置为LCD接口模式配合NE片选线、RS地址线通常用A6或其他地址线、WR写使能和RD读使能就能把LCD控制器映射到MCU的存储空间中。以常见的ILI9488控制器为例它内部的GRAM其实就是一块内存FSMC写GRAM和写SRAM在时序上基本一致。这样一条简单的*(volatile uint16_t *)0x6C000000 pixel;指令就能完成一次像素写入写地址由FSMC硬件自动产生时序不占用CPU循环。2.2 FSMC初始化代码与参数对照下面这段初始化代码基于STM32标准外设库SPL是当前F4系列项目里最常见的写法。使用HAL库的朋友可以对照功能逐行转换。void FSMC_LCD_Init(void) { GPIO_InitTypeDef GPIO_InitStructure; FSMC_NORSRAMInitTypeDef FSMC_NORSRAMInitStructure; FSMC_NORSRAMTimingInitTypeDef p; // 使能相关GPIO时钟FSMC数据线、地址线、控制线 RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD | RCC_AHB1Periph_GPIOE, ENABLE); RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB | RCC_AHB1Periph_GPIOG, ENABLE); RCC_AHB3PeriphClockCmd(RCC_AHB3Periph_FSMC, ENABLE); // PD0-PD15 作为FSMC数据线D0-D15 GPIO_InitStructure.GPIO_Pin GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10 | GPIO_Pin_11 | GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15; GPIO_InitStructure.GPIO_Mode GPIO_Mode_AF; GPIO_InitStructure.GPIO_Speed GPIO_Speed_100MHz; GPIO_InitStructure.GPIO_OType GPIO_OType_PP; GPIO_InitStructure.GPIO_PuPd GPIO_PuPd_NOPULL; GPIO_Init(GPIOD, GPIO_InitStructure); // 地址线、控制线复用配置此处省略部分引脚声明 GPIO_PinAFConfig(GPIOD, GPIO_PinSource0, GPIO_AF_FSMC); // 以D0为例 // ... 其余引脚同理 // FSMC时序参数这是3.5寸ILI9488屏常见的配置 p.FSMC_AddressSetupTime 2; // 地址建立时间单位HCLK周期 p.FSMC_AddressHoldTime 0; // 地址保持时间设为0即可 p.FSMC_DataSetupTime 5; // 数据建立时间影响读写速率 p.FSMC_BusTurnAroundDuration 0; p.FSMC_CLKDivision 0; p.FSMC_DataLatency 0; p.FSMC_AccessMode FSMC_AccessMode_B; FSMC_NORSRAMInitStructure.FSMC_Bank FSMC_Bank1_NORSRAM1; FSMC_NORSRAMInitStructure.FSMC_DataAddressMux FSMC_DataAddressMux_Disable; FSMC_NORSRAMInitStructure.FSMC_MemoryType FSMC_MemoryType_SRAM; FSMC_NORSRAMInitStructure.FSMC_MemoryDataWidth FSMC_MemoryDataWidth_16b; FSMC_NORSRAMInitStructure.FSMC_BurstAccessMode FSMC_BurstAccessMode_Disable; FSMC_NORSRAMInitStructure.FSMC_AsynchronousWait FSMC_AsynchronousWait_Disable; FSMC_NORSRAMInitStructure.FSMC_WriteOperation FSMC_WriteOperation_Enable; FSMC_NORSRAMInitStructure.FSMC_ExtMode FSMC_ExtMode_Disable; FSMC_NORSRAMInitStructure.FSMC_WriteBurst FSMC_WriteBurst_Disable; FSMC_NORSRAMInitStructure.FSMC_ReadWriteTimingStruct p; FSMC_NORSRAMInitStructure.FSMC_WriteTimingStruct p; FSMC_NORSRAMInit(FSMC_NORSRAMInitStructure); FSMC_NORSRAMCmd(FSMC_Bank1_NORSRAM1, ENABLE); }上面的代码里FSMC_AddressSetupTime和FSMC_DataSetupTime是两个需要重点关注的参数。AddressSetupTime是地址线有效到写使能拉低之间的时间DataSetupTime是数据建立时间。对于ILI9488这类控制器读写周期典型值在几十纳秒量级。FSMC时钟在F407上等于HCLK分频后的值通常为168MHz/284MHz一个周期约12ns。AddressSetupTime2、DataSetupTime5意味着整个读/写周期大约是(25)*1284ns这个速度对3.5寸屏来说是安全的。如果屏幕刷新出现花屏或边缘闪烁优先把这两个值调大不要一上来就追求极限速度。2.3 从ILI9488到ST7789寄存器初始化表怎么抄3.5寸、320x480的TFT屏市面上常见的控制器有ILI9488、ILI9486、ST7796等几种。它们的基本接口都是16位8080并口但寄存器初始化序列不完全相同。拿到一块屏时最稳妥的做法是找屏厂提供的初始化代码或者从购买页面下载例程。这些初始化代码通常是几百行的寄存器写值序列核心逻辑并不难理解void LCD_InitReg(void) { LCD_WriteCmd(0x11); // 退出睡眠模式 Delay_ms(120); // 等待电源稳定 LCD_WriteCmd(0x36); // 显存访问控制 LCD_WriteData(0x48); // 设置扫描方向和RGB顺序 LCD_WriteCmd(0x3A); // 像素格式 LCD_WriteData(0x55); // 16位色深RGB565 LCD_WriteCmd(0x29); // 开启显示 LCD_WriteCmd(0x2C); // 写入GRAM后续所有数据写入都指向该命令 }这段代码里最关键的是三条命令0x11退出睡眠、0x3A设置RGB565格式、0x2C准备写GRAM。实际项目中屏厂给的初始化序列可能长达上百条命令里面包含电源时序、伽马校正、VCOM电压等设置。有些寄存器值在不同批次屏幕上表现不一样比如伽马曲线调得过大会偏色调得过小会发白。我的建议是先用屏厂初始化的原值跑通不要随意修改如果显示效果不理想再用单个寄存器的调整来做微调每次只改一个参数观察屏幕变化。3. 电阻触摸屏驱动XPT2046读取与FSMC的协作3.1 电阻触摸屏的读数是电压不是坐标电阻触摸屏的工作原理是电压分压。四线电阻屏引出的X1、X2、Y1、Y2四根线分别连接两层ITO导电层。点击屏幕时上下两层接触在某一层上施加驱动电压从另一层上读到的电压值就反映了触摸点的某个方向位置。因为这个读数是模拟电压所以需要一个ADC来采样这就是XPT2046或ADS7843这类触摸控制芯片存在的意义。XPT2046通过SPI接口与MCU通信它内部集成了多路模拟开关和12位ADC。MCU通过SPI写入控制字选择采样通道X方向或Y方向和参考电压源然后读出12位ADC结果。在STM32F407的工程里SPI挂载触摸芯片会让代码结构变复杂——LCD走FSMC触摸走SPI两个外设的初始化、中断优先级的配合都需要仔细安排。3.2 触摸板初始化与读取代码SPI示例下面这段代码展示了XPT2046的SPI初始化和单点坐标读取流程。这个代码可以从标准SPI例程改过来但要注意F407的SPI引脚复用配置。// 触摸芯片引脚定义SPI1_NSS(PA4), SPI1_SCK(PA5), SPI1_MISO(PA6), SPI1_MOSI(PA7) #define TP_CS_LOW() GPIO_ResetBits(GPIOA, GPIO_Pin_4) #define TP_CS_HIGH() GPIO_SetBits(GPIOA, GPIO_Pin_4) void TP_Init(void) { SPI_InitTypeDef SPI_InitStructure; GPIO_InitTypeDef GPIO_InitStructure; // 使能SPI1时钟和GPIOA时钟 RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE); // PA5-SCK, PA6-MISO, PA7-MOSI 复用推挽输出 GPIO_InitStructure.GPIO_Pin GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7; GPIO_InitStructure.GPIO_Mode GPIO_Mode_AF; GPIO_InitStructure.GPIO_Speed GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_OType GPIO_OType_PP; GPIO_InitStructure.GPIO_PuPd GPIO_PuPd_NOPULL; GPIO_Init(GPIOA, GPIO_InitStructure); GPIO_PinAFConfig(GPIOA, GPIO_PinSource5, GPIO_AF_SPI1); GPIO_PinAFConfig(GPIOA, GPIO_PinSource6, GPIO_AF_SPI1); GPIO_PinAFConfig(GPIOA, GPIO_PinSource7, GPIO_AF_SPI1); // PA4作为片选输出 GPIO_InitStructure.GPIO_Pin GPIO_Pin_4; GPIO_InitStructure.GPIO_Mode GPIO_Mode_OUT; GPIO_InitStructure.GPIO_Speed GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_OType GPIO_OType_PP; GPIO_InitStructure.GPIO_PuPd GPIO_PuPd_UP; GPIO_Init(GPIOA, GPIO_InitStructure); TP_CS_HIGH(); SPI_InitStructure.SPI_Direction SPI_Direction_2Lines_FullDuplex; SPI_InitStructure.SPI_Mode SPI_Mode_Master; SPI_InitStructure.SPI_DataSize SPI_DataSize_8b; SPI_InitStructure.SPI_CPOL SPI_CPOL_High; // XPT2046要求SCK空闲为高 SPI_InitStructure.SPI_CPHA SPI_CPHA_2Edge; // 第二个边沿采样 SPI_InitStructure.SPI_NSS SPI_NSS_Soft; SPI_InitStructure.SPI_BaudRatePrescaler SPI_BaudRatePrescaler_16; // 84MHz/16≈5.25MHz SPI_InitStructure.SPI_FirstBit SPI_FirstBit_MSB; SPI_Init(SPI1, SPI_InitStructure); SPI_Cmd(SPI1, ENABLE); }读取坐标时分两个步骤写控制字、读ADC结果。uint16_t TP_ReadADC(uint8_t cmd) { uint16_t adc_value 0; TP_CS_LOW(); SPI_SendByte(cmd); // 发送控制字选择X或Y通道 // 第一个字节读到的数据无效ADC转换需要时间 SPI_RecvByte(); // 读取12位有效数据 adc_value SPI_RecvByte(); // 高8位 adc_value (adc_value 8) | SPI_RecvByte(); // 低8位 TP_CS_HIGH(); return adc_value 3; // 12位有效数据右移3位 } uint16_t TP_ReadX(void) { // 控制字0xD0S1, A2-A0选择Y通道实际对应X坐标测量 // 详细通道选择请查看XPT2046数据手册 return TP_ReadADC(0xD0); } uint16_t TP_ReadY(void) { return TP_ReadADC(0x90); }这里有一个常见的迷惑点控制字选择Y通道读出来的是X坐标选择X通道读出来的是Y坐标。这是因为XPT2046内部的模拟开关切换方式决定的。初次接触这个概念容易搞反导致触摸点和显示位置完全对不上。如果发现触摸方向全部镜像或转了90度优先检查这里。3.3 触摸坐标为什么抖得厉害电阻触摸屏的ADC读数有一个特点噪声大而且不同力度按压读到的电压值不完全相同。直接拿单次ADC结果做触摸反馈屏幕上会出现光标乱跳的现象。常见的处理办法是多次采样后取平均值或取中值。#define TP_SAMPLE_COUNT 8 uint16_t TP_ReadX_Average(void) { uint32_t sum 0; uint16_t samples[TP_SAMPLE_COUNT]; uint8_t i; for (i 0; i TP_SAMPLE_COUNT; i) { samples[i] TP_ReadX(); } // 去掉最大值和最小值然后取平均 // ... 排序求均值逻辑省略 return (uint16_t)(sum / (TP_SAMPLE_COUNT - 2)); }滤波的关键不是平均次数越多越好而是要在响应速度和稳定性之间取平衡。8次采样大约消耗1~2ms肉眼基本无感。如果发现平均后仍然抖动需要考虑硬件层面的问题比如触摸屏的ITO走线阻抗是否过大、电源纹波是否明显。我在实际项目里遇到过一种情况屏幕点亮后触摸读数波动比屏幕熄灭时大很多排查后发现是LCD背光的PWM频率落在ADC采样的敏感频段上调整背光频率后问题消失。4. 坐标映射与触摸校准从ADC值到320x480像素坐标4.1 线性映射公式为什么不够用拿到XPT2046读出的ADC值后下一步是把它们映射到LCD的像素坐标。理论上触摸屏的X轴和LCD的X轴是同一方向线性映射就够了。但实际情况要复杂得多。触摸屏和LCD在贴合时存在角度偏移ITO层的电阻率并不完全均匀而且屏幕边缘区域的电场会畸变。直接做线性映射的结果是屏幕中间区域触摸准确四角位置偏差可能达到20~40个像素。这就是触摸校准存在的意义。校准的本质是测出触摸屏坐标系到LCD坐标系之间的变换关系。最常用的校准方式是两点校准缩放平移和三点校准仿射变换。三点校准可以处理X轴和Y轴之间的轻微旋转在3.5寸屏上用两点校准往往已经足够但如果追求四角精度三点校准是更好的选择。4.2 两点校准实现步骤两点校准的原理很简单屏幕上先显示一个“”字光标用户点击一次记录ADC值再显示另一个“”字光标再点击一次记录第二组ADC值。利用这两组数据可以计算出缩放比例和偏移量。假设屏幕上的两个校准点坐标为(x1_pixel, y1_pixel)和(x2_pixel, y2_pixel)对应的ADC读数为(adc1_x, adc1_y)和(adc2_x, adc2_y)。那么映射系数为float scale_x (float)(x2_pixel - x1_pixel) / (float)(adc2_x - adc1_x); float offset_x x1_pixel - adc1_x * scale_x; float scale_y (float)(y2_pixel - y1_pixel) / (float)(adc2_y - adc1_y); float offset_y y1_pixel - adc1_y * scale_y;实际点击位置的计算uint16_t TP_GetX(void) { uint16_t adc_x TP_ReadX_Average(); uint16_t pixel_x (uint16_t)(adc_x * scale_x offset_x); if (pixel_x 320) pixel_x 319; return pixel_x; }两点校准虽然只能处理线性关系但代码简单计算开销极小。对3.5寸屏来说这是最合适的选择。4.3 三点校准解决旋转和梯形失真三点校准使用仿射变换公式需要计算6个系数。虽然计算量大一些但能修正触摸屏与LCD之间的旋转角度以及非正交偏差。实现方式是在屏幕左上、右上、左下三个位置显示校准点记录三组数据然后求解方程组。以X坐标为例假设仿射变换为x_pixel a * adc_x b * adc_y c三个校准点可以列出三个方程// 三个校准点(adc_x1, adc_y1) - (x1_pixel) // (adc_x2, adc_y2) - (x2_pixel) // (adc_x3, adc_y3) - (x3_pixel) // 求解系数a, b, c这个方程组可以用克莱姆法则求解代码量不大。实际项目中我一般把校准参数以浮点数形式保存在一个全局结构体里同时允许用户在设置界面里重新校准系统启动时从EEPROM或Flash加载参数。有一点需要注意电阻触摸屏的校准参数会随着时间漂移尤其是经常在户外高温环境下使用的设备。如果用户反馈触控不灵先让他重新校准一次比换屏更靠谱。5. 性能优化与常见问题排查5.1 刷新率的瓶颈不在FSMC而在初始化方式FSMC接口的写入速度足够快理论上320x480全屏写入一帧RGB565数据约需要3204802307200字节。在84MHz的FSMC时钟下不考虑等待周期理论时间约7ms实际加上命令和数据切换全屏刷一帧大约在20~30ms。但很多工程里刷新率远达不到这个水平卡在像素写入函数的设计上。常见的低效写法是每次写入一个像素前都发送写GRAM命令0x2C。ILI9488这类控制器其实只需要在切换写入目标时发送一次命令之后连续写入的数据会自动按顺序填充GRAM。正确的批量填充方式是void LCD_Clear(uint16_t color) { uint32_t i; LCD_WriteCmd(0x2C); // 设置写GRAM命令 for (i 0; i 320 * 480; i) { LCD_WriteData(color); } }另一个优化点是使用FSMC的16位数据线宽度时可以把两个像素拼成一个32位写入操作前提是MCU的总线支持。F407的FSMC支持外设存储宽度16位不支持32位宽所以这个优化在F407上做不了。实战中最有效的优化是减少无效的写操作比如在窗口裁剪模式下只更新需要变化的区域。5.2 5个避坑经验现象、原因、解决坑一屏幕白屏背光亮但无字符。从FSMC初始化到LCD初始化之间的时序没有处理好。ILI9488需要在上电后等待一定时间再发送命令特别是退出睡眠模式后必须延时120ms。解决方法是严格按照数据手册规定的延时执行不要在延时上偷工减料。坑二画面颜色偏红或偏蓝完全显示正常。这个现象常出现在RGB565和RGB666格式混用的情况下。屏厂初始化代码可能设置了18位色深0x66而MCU端发送的是16位RGB565数据。解决方法是检查LCD_WriteCmd(0x3A)后面的参数IL9488的0x55是16位0x66是18位。坑三触摸X轴方向反了。这不是接线错误而是控制字的通道选择和屏幕扫描方向对不上。结合LCD的0x36寄存器显存访问控制设置的扫描方向来判断把XPT2046的控制字通道换一下即可。如果软件上换通道不方便也可以把屏幕的Y和Y-引线对调来反转方向。坑四触摸读数正常但点击位置漂移严重。这往往是屏的电阻层老化了。初期可以通过重新校准解决但如果用户设备使用环境恶劣高温、高湿、频繁机械按压电阻屏寿命一般在1~2年。遇到这种问题先排查硬件不要反复调软件算法。坑五FSMC写时序不稳定导致花屏。系统时钟调到168MHz后FSMC时序参数没有同步调整。F407刚上电时主频可能是16MHz内部RC初始化时钟后到了168MHzFSMC时序参数如果沿用16MHz时的设置在高速时钟下会出现偶发花屏。解决方法是在时钟切换后重新初始化FSMC。5.3 触控响应速度的取舍电阻触摸屏的响应速度受限于ADC采样时间和软件滤波。XPT2046的最高采样率约125kHz实际使用时SPI时钟设在2~5MHz即可。如果项目里对触控响应要求较高可以通过“快速扫描慢速滤波”的方式处理先做一次快速采样判断是否有触摸确认有触摸后再进行多次采样和滤波。这样可以避免在无触摸状态下反复进入完整滤波流程降低CPU占用。TP_Scan函数里通常需要处理按下和抬起两个动作。常见的处理方式是记录上一次的按下状态如果当前读到触摸且上一次没有触摸则触发一次“按下事件”如果当前没有触摸且上一次有触摸触发“抬起事件”。这个状态机虽然在裸机环境下实现起来简单但对后续的界面交互比如按钮点击、滑块拖动非常重要。6. 进阶用法DMA加速刷新与多级菜单界面框架当基础驱动跑通之后值得花精力做的事情是把LCD刷新从CPU繁忙循环中解放出来。F407支持FSMC配合DMA进行内存到外设的搬运也就是说可以事先在内存中准备好一帧图像数据然后用DMA一次性写入LCD的GRAM。这样CPU只需要发起DMA传输不需要干预每个像素的写入过程。DMA配置的核心是把内存地址设为源地址FSMC的LCD数据寄存器地址设为目的地址传输长度设为像素字节数。注意FSMC的地址映射在DMA外设看来是一个普通的外设地址所以不需要特殊处理。void LCD_ShowImage_DMA(uint16_t *image, uint32_t size) { // 假设DMA2_Stream0已经配置为Memory-to-Memory模式 DMA_InitTypeDef DMA_InitStructure; DMA_InitStructure.DMA_Channel DMA_Channel_0; DMA_InitStructure.DMA_PeripheralBaseAddr (uint32_t)LCD-LCD_RAM; // FSMC写RAM地址 DMA_InitStructure.DMA_Memory0BaseAddr (uint32_t)image; DMA_InitStructure.DMA_DIR DMA_DIR_MemoryToPeripheral; DMA_InitStructure.DMA_BufferSize size; 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_InitStructure.DMA_FIFOMode DMA_FIFOMode_Disable; DMA_Init(DMA2_Stream0, DMA_InitStructure); DMA_Cmd(DMA2_Stream0, ENABLE); }DMA传输完成后的中断可以用来驱动“双缓冲”机制一个缓冲区在DMA搬运时显示另一个缓冲区在后台由CPU填充数据传输完成后再交换。这在显示动态曲线、波形图时效果非常明显也是从“能显示”迈向“流畅显示”的关键一步。最后一个建议是界面结构。320x480的分辨率足够显示一个带图标和按钮的完整界面但如果界面逻辑全部写在一个主循环里代码会迅速膨胀到难以维护。我会把每个界面定义成一个结构体里面包含绘制函数指针、事件处理函数指针和进入/退出回调。这样每新增一个界面只需要注册一个结构体变量不破坏已有逻辑。这套框架在裸机上运行良好也给后来迁移到RTOS留了空间。回看这些年做过的串口屏替代项目STM32F407驱动3.5寸电阻触摸屏这条技术路线最大的价值在于把屏幕和触摸的硬件成本压到极低同时保留了对底层驱动的完全控制。第一次做FSMC时序配置花了大半个晚上后来用同一套代码换不同厂商的屏只需要修改初始化寄存器表。希望这篇笔记能帮你少走一些弯路。如果你在调试过程中遇到具体的时序问题检查FSMC参数和液晶初始化序列时不妨从最保守的时序开始逐步提速。祝你调机顺利。本文还有配套的精品资源点击获取

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑