STM32F4硬核实战:FSMC驱动TFTLCD从原理到代码全解析,附避坑指南+调试干货

序言

在嵌入式开发的世界里,STM32F4系列MCU因其强大的性能和灵活性,成为了无数工程师的首选。而当我们需要为项目添加一个直观的人机交互界面时,用FSMC(灵活静态存储器控制器)驱动TFTLCD几乎是绕不开的核心技能——这不仅是硬件接口的挑战,更是时序逻辑与代码实现的深度博弈。

你是否曾在配置FSMC时序时因参数匹配问题抓耳挠腮?是否在驱动LCD时被地址映射、数据宽度等细节搞得晕头转向?这篇文章将从底层原理出发,带你打通“FSMC驱动TFTLCD”的任督二脉:从FSMC的存储区块划分、信号引脚功能,到TFTLCD的接口类型、驱动芯片指令集,再到硬件电路与代码的深度耦合实现,每一个环节都配有原理图解析、时序图说明和调试案例。

特别值得一提的是,文中详细记录了“读取芯片ID时因指针类型错误导致调试失败”的真实踩坑经历——这些在官方手册里不会写明的细节,恰恰是开发中最容易卡壳的地方。无论是想系统学习STM32外设开发的新手,还是需要优化项目显示模块的资深工程师,都能从原理剖析、代码集成到实战调试中,找到提升开发效率的关键钥匙。

文末彩蛋:完整的代码片段、ILI9341手册关键时序图已整理完毕,关注作者即可获取更多嵌入式开发干货。如果你也曾在FSMC驱动LCD的路上踩过坑,或是有更高效的实现方案,欢迎在评论区交流——让我们一起把嵌入式开发的细节抠到极致!

📌 互动引导

  • 觉得内容实用?点击❤️点赞支持,让更多开发者看到!
  • 收藏本文,随时查阅FSMC与TFTLCD开发的核心要点。
  • 转发给团队伙伴,共同攻克嵌入式显示开发难题~
  • 关注作者,后续持续更新STM32外设实战、RTOS优化等硬核内容!

一、STM32F4的FSMC原理详解

1. FSMC概述

FSMC(Flexible Static Memory Controller,灵活静态存储器控制器)是STM32F4系列微控制器中的一个重要外设,主要用于连接外部存储器设备。它提供了与多种类型存储器的接口能力,包括:

  • NOR Flash/PSRAM存储器
  • NAND Flash/PC卡存储器
  • SRAM存储器
  • 16位或8位数据宽度的LCD接口(通过模拟8080时序)

2. FSMC主要特性

  1. 多种存储器支持:支持SRAM、ROM、NOR Flash、NAND Flash、PC卡等
  2. 大地址空间:最多可支持1GB的寻址空间(分为4个256MB的存储块)
  3. 可配置时序:可为不同速度的存储器配置不同的访问时序
  4. 数据宽度灵活:支持8位、16位数据宽度
  5. 写使能和字节选择:支持字节/半字/字访问
  6. 扩展模式:支持同步传输和扩展模式

3. STM32F4 FSMC结构图解析

在这里插入图片描述

图中展示了STM32F4系列微控制器中FSMC(灵活静态存储器控制器)的内部结构和相关信号引脚。下面我将详细解析图中的各个部分和引脚含义。

1. FSMC整体结构

从图中可以看出FSMC主要由以下几个部分组成:

  1. 与内核的连接

    • 通过AHB总线与内核通信
    • 中断信号连接到NVIC(嵌套向量中断控制器)
    • 时钟来自HCLK(高速时钟)
  2. 主要功能模块

    • 配置寄存器组
    • NOR/PSRAM存储器控制器
    • NAND/PC卡存储器控制器
  3. 外部信号引脚

    • NOR/PSRAM相关信号
    • NAND相关信号
    • PC卡相关信号
    • 共享信号

2. 引脚功能详解

2.1 NOR/PSRAM存储器相关信号
  1. FSMC_NE[4:1]

    • NOR Flash/PSRAM片选信号
    • 对应Bank1的4个子存储块(Bank1-1到Bank1-4)
    • 低电平有效
  2. FSMC_NL (或NADV):

    • 地址有效信号(Address Valid)
    • 用于锁存地址信号
  3. FSMC_NL[1:0]

    • 字节锁存信号(Byte Latch)
    • 用于16位模式下的字节选择
  4. FSMC_CLK

    • 时钟输出信号
    • 用于同步模式下的时钟提供
  5. FSMC_A[25:0]

    • 26位地址总线
    • 可寻址最大64MB空间(2^26)
  6. FSMC_D[15:0]

    • 16位数据总线
    • 支持8位或16位数据传输
  7. FSMC_NWE

    • 写使能信号(Write Enable)
    • 低电平有效
  8. FSMC_NOE

    • 输出使能信号(Output Enable)
    • 低电平有效
  9. FSMC_NWAIT

    • 等待信号
    • 用于插入等待状态,延长访问周期
2.2 NAND Flash相关信号
  1. FSMC_NCE[3:2]

    • NAND Flash片选信号
    • 对应Bank2和Bank3
  2. FSMC_INT[3:2]

    • 中断信号
    • 用于NAND Flash的中断通知
  3. FSMC_INTR

    • 中断请求信号
    • 连接到NVIC
2.3 PC卡相关信号
  1. FSMC_NCE[4:1]

    • PC卡片选信号
    • 对应Bank4
  2. FSMC_NIORD

    • I/O读信号(I/O Read)
    • 低电平有效
  3. FSMC_NIOWR

    • I/O写信号(I/O Write)
    • 低电平有效
  4. FSMC_NREG

    • 寄存器选择信号(Register Select)
    • 用于选择PC卡中的寄存器
  5. FSMC_CD

    • 卡检测信号(Card Detect)
    • 用于检测PC卡是否插入
2.4 共享信号

这些信号在不同模式下有不同的功能:

  1. FSMC_NBL[1:0]

    • 字节锁存信号(Byte Lane)
    • 在16位模式下用于选择高/低字节
    • FSMC_NBL0对应数据低字节(D[7:0])
    • FSMC_NBL1对应数据高字节(D[15:8])
  2. FSMC_NWAT

    • 等待信号(Wait)
    • 用于扩展访问周期

3. 功能模块解析

  1. NOR/PSRAM存储器控制器

    • 管理NOR Flash和PSRAM的访问
    • 支持异步和同步访问模式
    • 可配置不同的时序参数
  2. NAND/PC卡存储器控制器

    • 管理NAND Flash和PC卡的访问
    • 支持ECC(错误校验与纠正)功能
    • 提供特定的控制信号
  3. 配置寄存器

    • 存储FSMC的工作模式配置
    • 包括时序参数、数据宽度、存储器类型等设置

4. FSMC在整个MCU的位置

在这里插入图片描述

5. FSMC使用注意事项

  1. 地址对齐

    • 16位模式下,HADDR地址需要右移1位对应到FSMC_A[24:0]
    • 8位模式下,HADDR地址直接对应FSMC_A[25:0]
  2. 信号复用

    • 部分信号在不同模式下功能不同
    • 需要根据实际使用的存储器类型正确配置
  3. 时序配置

    • 必须根据外部存储器的时序要求
    • 设置正确的建立时间、保持时间等参数

4. FSMC存储区块划分

FSMC将1GB的地址空间划分为4个存储块(Bank):

  • Bank1:用于NOR Flash/PSRAM/SRAM,分为4个子块(每个64MB)

    • Bank1-1: 0x6000 0000 - 0x63FF FFFF
    • Bank1-2: 0x6400 0000 - 0x67FF FFFF
    • Bank1-3: 0x6800 0000 - 0x6BFF FFFF
    • Bank1-4: 0x6C00 0000 - 0x6FFF FFFF
  • Bank2/3:用于NAND Flash(各256MB)

    • Bank2: 0x7000 0000 - 0x7FFF FFFF
    • Bank3: 0x8000 0000 - 0x8FFF FFFF
  • Bank4:用于PC卡(256MB)

    • Bank4: 0x9000 0000 - 0x9FFF FFFF

5. FSMC主要信号引脚

FSMC使用以下主要信号线与外部存储器通信:

  • 地址总线:FSMC_A[25:0] (最多26位地址线)
  • 数据总线:FSMC_D[15:0] (16位数据线)
  • 控制信号
    • FSMC_NE[3:0]:片选信号(对应Bank1的4个子块)
    • FSMC_NWE:写使能
    • FSMC_NOE:读使能
    • FSMC_NBL[1:0]:字节选择(用于16位模式下的字节选择)
    • FSMC_NWAIT:等待信号(用于插入等待状态)

对于不同的存储器类型,还会使用其他特定信号线。

6. FSMC时序配置

FSMC的时序参数可通过寄存器配置,主要包括:

  1. 地址建立时间(ADDSET):地址建立到读/写信号有效的时间
  2. 地址保持时间(ADDHLD):仅用于同步突发访问模式
  3. 数据建立时间(DATAST):读/写信号有效到数据稳定的时间
  4. 总线恢复时间(BUSTURN):两次访问之间的最小间隔时间

这些参数需要根据外部存储器的时序要求进行配置。

7. FSMC配置步骤

配置FSMC通常包括以下步骤:

  1. 使能FSMC时钟:通过RCC_AHB3ENR寄存器
  2. 配置GPIO:将相关引脚配置为FSMC复用功能
  3. 配置FSMC寄存器
    • 选择存储器类型(SRAM、NOR、NAND等)
    • 设置数据宽度(8位或16位)
    • 配置时序参数
    • 使能相应的存储块
  4. 访问外部存储器:通过指针访问映射的地址空间

8. 注意事项

  1. 地址映射:FSMC使用固定的地址映射,访问外部存储器就像访问内部存储器一样。
  2. 时序匹配:必须根据外部存储器手册配置正确的时序参数
  3. 数据宽度:16位模式下地址需要左移1位(地址线A0连接存储器的A1)
  4. 功耗考虑:不使用时可以关闭FSMC时钟以节省功耗
  5. 干扰问题:高速操作时需要注意信号完整性和电磁兼容性问题

通过合理配置FSMC,STM32F4可以高效地与各种外部存储器或LCD模块通信,大大扩展了系统的存储和显示能力。

二、TFTLCD简介

1. 什么是 TFT LCD?

TFT LCD(Thin-Film Transistor Liquid Crystal Display,薄膜晶体管液晶显示器) 是一种 主动矩阵式液晶显示器,广泛应用于智能手机、平板电脑、电脑显示器、工业控制屏等领域。

  • TFT(薄膜晶体管):每个像素点由独立的晶体管控制,可实现 高刷新率、高对比度、快速响应
  • LCD(液晶显示器):利用液晶分子的光学特性显示图像,需要 背光源(LED 或 CCFL)。

2. TFT LCD 的基本结构

TFT LCD 主要由以下部分组成:

  1. 液晶层(Liquid Crystal):控制光线通过与否。
  2. TFT 阵列(像素驱动):每个像素点对应一个 TFT 开关。
  3. 彩色滤光片(Color Filter):生成 RGB 三原色,实现彩色显示。
  4. 背光模块(Backlight):提供光源(通常为 LED)。
  5. 偏光片(Polarizer):控制光线偏振方向。

3. TFT LCD 的工作原理

  1. 背光发射白光 → 穿过 偏光片(变成偏振光)。
  2. TFT 控制液晶分子旋转,改变光的偏振方向。
  3. 光线通过 彩色滤光片,形成 RGB 子像素。
  4. 最终光线通过 第二层偏光片,显示不同颜色。

优点

  • 高分辨率、色彩鲜艳。
  • 响应速度较快(适合视频播放)。
  • 可视角度较大(IPS 屏可达 178°)。

缺点

  • 需要背光,功耗较高(OLED 更省电)。
  • 黑色显示不如 OLED 纯粹(因为背光无法完全关闭)。

4. TFT LCD 的接口类型

TFT LCD 通常通过以下接口与控制器(如 STM32、ESP32)通信:

  1. SPI(串行接口)

    • 优点:引脚少(仅需 4-6 根线),适合低速显示。
    • 缺点:刷新率低,适合小屏(如 1.8 寸)。
  2. 8080 并行接口(MCU 模式)

    • 8/16 位数据总线 + 控制信号(WR, RD, CS, RS)。
    • 优点:速度快,适合 2.4~3.5 寸屏。
  3. RGB 接口

    • 直接传输 RGB 数据 + HSYNC/VSYNC 同步信号。
    • 优点:超高刷新率,适合大屏(如 4.3 寸以上)。
  4. MIPI DSI(移动设备专用)

    • 高速串行接口,用于手机、平板。

5. TFT LCD 的驱动芯片

常见的 TFT LCD 驱动 IC 包括:

  • ILI9341(240×320,SPI/8080,经典款)
  • ST7789(240×240/320,SPI,圆形屏常用)
  • ILI9488(320×480,8080,3.5 寸屏)
  • SSD1963(480×272,RGB,大屏驱动)

6. ILI9341常用命令

由于ILI9341驱动芯片很常用,而我的开发板配套的TFTLCD驱动芯片就是它,所以下面介绍一下ILI9341芯片的常用命令。比如读取芯片ID、控制显示模式、设置地址等。具体命令如下:

  1. 读取芯片ID指令:读ID指令(0XD3)用于读取LCD控制器的ID。该指令后面跟4个参数,最后2个参数读出来是0X93和0X41,恰好是控制器ILI9341的数字部分,借此可判别所用的LCD驱动器型号,以便根据型号执行对应驱动IC的初始化代码,实现一个代码兼容多款LCD的功能。
    在这里插入图片描述

  2. 存储访问控制指令:存储访问控制指令(0X36),可以控制ILI9341存储器的读写方向,即控制连续写GRAM时GRAM指针的增长方向,进而控制显示方式(读GRAM同理) 。该指令紧跟一个参数,主要关注MY、MX、MV这三个位,通过对这三个位的设置能控制整个ILI9341的全部扫描方向。
    在这里插入图片描述

  3. 列地址设置指令:列地址设置指令(0X2A),在默认的从左到右、从上到下扫描方式下,用于设置横坐标(x坐标) 。它带有4个参数,实际是2个坐标值:SC和EC,即列地址的起始值和结束值,其中SC必须小于等于EC,且0≤SC/EC≤239。通常设置x坐标时,设置SC即可,若EC无变化,在初始化ILI9341时设置一次便可提高速度。
    在这里插入图片描述

  4. 页地址设置指令:页地址设置指令(0X2B),在默认扫描方式下,用于设置纵坐标(y坐标)。它带有4个参数,实际为2个坐标值:SP和EP,即页地址的起始值和结束值,SP必须小于等于EP,且0≤SP/EP≤319 。一般设置y坐标时,设置SP即可,若EP无变化,在初始化时设置一次即可。
    在这里插入图片描述

  5. 写GRAM指令:写GRAM指令(0X2C),发送该指令后,便可以向LCD的GRAM中写入颜色数据。该指令支持连续写,收到指令后,数据有效位宽变为16位,GRAM的地址会根据MY/MX/MV设置的扫描方向自增。例如在从左到右、从上到下的扫描方式下,设置好起始坐标(通过SC,SP设置)后,每写入一个颜色值,GRAM地址自动自增1(SC++),碰到EC时回到SC,同时SP++,直至坐标(EC,EP)结束,期间无需再次设置坐标,可提高写入速度。
    在这里插入图片描述

  6. 读GRAM指令:读GRAM指令(0X2E)用于读取ILI9341的显存(GRAM) 。ILI9341收到该指令后,第一次输出的是无效的dummy数据,第二次开始输出的才是有效的GRAM数据(从坐标:SC,SP开始)。输出规律为:每个颜色分量占8个位,一次输出2个颜色分量。若只读取一个点的颜色值,接收参数3即可;若要连续读取(利用GRAM地址自增),则按相应规律接收颜色数据。
    在这里插入图片描述

三、使用FSMC驱动TFTLCD

1. 电路原理图

下面是我的开发板上LCD的接口图,明显采用8080 并行接口。下面着重关注一下RS引脚连接的地址线,LCD_CS引脚连接的片选信号线,BL引脚连接的MCU引脚。

在这里插入图片描述
先看LCD_CS引脚连接的片选信号线是PG12,复用为FSMC_NE4

在这里插入图片描述
RS引脚连接的地址线是FSMC_A6

在这里插入图片描述

FSMC_NOEFSMC_NWE连接到了STM32的PD4PD5,都是固定引脚,不用管他。

在这里插入图片描述
BL引脚连接的MCU引脚是PB15

在这里插入图片描述

2. 配置FSMC

根据以上的硬件连接图,我们可以配置FSMC。

1. 模式配置

由于前面说了,我们使用的是NE4,所以就选择NE4;内存类型直接选择LCD接口;RS引脚连接的是A6,所以选择A6;数据位是16位的。
在这里插入图片描述

2. 参数配置

选择LCD接口,使能写操作,对于时序配置,参考LCD的驱动芯片ILI9341手册来决定。
在这里插入图片描述

3. ILI9341手册中8080并行接口时序图

在这里插入图片描述
在这里插入图片描述

4. 时序配置

由于读时序,数据建立时间最长是450ns;写时序,数据建立时间最长是66ns,写数据的话,数据建立时间大于66纳秒就可以。而时钟频率是168MHz,所以每个时钟周期是1/168us,约等于6ns。所以配置地址建立时间数值=1,也就是6纳秒;数据建立时间数值=80,也就是480纳秒;总线读写操作切换间隔=1,也就是6ns。这样的设置足够满足要求。

3. 代码集成

初始化函数

STM32CubeIDE生成的代码中,会有初始化FSMC的函数,并且在初始化阶段自动调用,我们不用操心。

MX_FSMC_Init();

读取驱动芯片ID

在初始化之后,我们可以读取一下芯片ID,如果读取到了。如果正确读取到了,那就说明我们的驱动已经正常工作了。

1. 直接操作地址的方式实现
#define TFTLCD_BASE       0x6C000000
#define TFTLCD_COMMAND    (TFTLCD_BASE & ~(1 << (6 + 1)))
#define TFTLCD_COMMAND_OP ((uint16_t *)TFTLCD_COMMAND)
#define TFTLCD_DATA       (TFTLCD_BASE | (1 << (6 + 1)))/*0000 1000 0000*/
#define TFTLCD_DATA_OP    ((uint16_t *)TFTLCD_DATA)/*0000 1000 0000*/

  	/*初始化TFTLCD*/
	uint16_t * pcmd = TFTLCD_COMMAND_OP;
	uint16_t * pdata = TFTLCD_DATA_OP;
	uint32_t id = 0;
	
	*pcmd = 0xD3;
	id = *pdata;/*读取的东西撇弃掉*/
	id = *pdata;/*00*/
	id = *pdata;/*93*/
	id <<= 8;
	id |= *pdata;/*41*/

上面的(1 << (6 + 1)是因为PA6连接到RS引脚的缘故。而+1的原因是HADDR的右移一位造成的。只要控制PA6对应的地址线高低电平,就可以得到发送数据和命令的效果。

2. 调试验证

在这里插入图片描述

3. 定义结构体的方式实现(原子哥的实现方式)
//LCD地址结构体
typedef struct
{
	__IO uint16_t LCD_REG;
	__IO uint16_t LCD_RAM;
} LCD_TypeDef;

#define LCD_BASE        ((uint32_t)(0x6C000000 | 0x0000007E))
#define LCD             ((LCD_TypeDef *) LCD_BASE)

回顾上面第一章 4. FSMC存储区块划分,就可以理解上面的地址定义。
在MCU内部的地址是由HADDR决定的,它与FSMC有一一对应的关系,但根据FSMC使用的是8位宽,还是16位宽,HADDR决定是否右移一位与FSMC对应。
首先,0x6C000000的地址取决于下图,我们使用的是第4区,所以HADDR[27:26]=11,地址范围是0x6C000000起始的。
在这里插入图片描述
那后面的0x0000007E换算成二进制,最后面是0111 1110。而针对16bit位宽,HADDR[0]没有用到,所以HADDR[25:1]右移一位,对应到了芯片引脚的FSMC_A[24:0]。打比方,0000 0010这里只有第1位等于1,但对应到FSMC,就是0000 0001,也就是只有A[0] = 1。
于是,0111 1110右移一位,得到0011 1111,于是此时的PA6,也就是地址的Bit6 = 0。注意,这个时候,地址增加1,对应到实际的地址操作是增加了2个字节,因为是16位寻址。跨度是2个字节。这个时候,回头看下结构体LCD_TypeDef的定义,里面定义了2个uint16_t的整型变量。LCD_REG所在的地址是LCD_BASE,也就是PA6=0;而LCD_RAM对应的地址是LCD_BASE+2,对应的PA6=1。如此就区别了数据和命令的发送/接收。

在ILI9341芯片中,与数据/命令选择相关的信号是 D/CX(原理图显示为RS),其电平状态决定了传输内容的类型:

  • 当D/CX为高电平时:传输的内容为 数据(如显示数据、命令参数)。
  • 当D/CX为低电平时:传输的内容为 命令

对于RS引脚,高电平代表数据低电平代表命令。所以对LCD_REG写操作就是写命令;对LCD_RAM的读写操作就是读写数据。

下面调试一下,看看地址:
在这里插入图片描述
在这里插入图片描述
下面是具体的代码,对于TFTLCD读写操作:

/*写命令*/
void LCD_WR_REG(volatile uint16_t regval)
{   
	LCD->LCD_REG=regval;
}
/*读数据*/
uint16_t LCD_RD_DATA(void)
{
	volatile uint16_t ram;			
	ram = LCD->LCD_RAM;
    return ram;
}
void LCD_Init(void)
{
	uint32_t id = 0;
    LCD_WR_REG(0XD3);				   
	id = LCD_RD_DATA();	//dummy read 	
	id = LCD_RD_DATA();	//读到0X00
	id = LCD_RD_DATA();   	//读取93	
    id = id << 8;
    id |= LCD_RD_DATA();   	//读取41  
}
4. 调试验证

在这里插入图片描述

5. 记录踩的一个坑

在上面 1. 直接操作地址的方式实现章节,我踩了一个坑,导致读取显示屏驱动芯片的ID错误,百思不得其解……让我无心午休,一直检查到现在(15:03),终于找到了问题的根源,并解决了。

  1. 错误点
    将地址强转指针的时候,使用了uint32_t。我当时想,STM32不是32位的MCU吗?转换成的地址就应该是uint32_t
  #define TFTLCD_BASE       0x6C000000
  #define TFTLCD_COMMAND    (TFTLCD_BASE & ~(1 << (6 + 1)))
  #define TFTLCD_COMMAND_OP ((uint32_t *)TFTLCD_COMMAND)
  #define TFTLCD_DATA       (TFTLCD_BASE | (1 << (6 + 1)))/*0000 1000 0000*/
  #define TFTLCD_DATA_OP    ((uint32_t *)TFTLCD_DATA)/*0000 1000 0000*/
  1. 解决方法
    在LCD的访问上,LCD与FSMC是16位宽的地址线,所以只能使用uint16_t
  #define TFTLCD_BASE       0x6C000000
  #define TFTLCD_COMMAND    (TFTLCD_BASE & ~(1 << (6 + 1)))
  #define TFTLCD_COMMAND_OP ((uint16_t *)TFTLCD_COMMAND)
  #define TFTLCD_DATA       (TFTLCD_BASE | (1 << (6 + 1)))/*0000 1000 0000*/
  #define TFTLCD_DATA_OP    ((uint16_t *)TFTLCD_DATA)/*0000 1000 0000*/

绘制一个矩形

涉及的命令有0x2A、0x2B、0x2C,具体的使用方法请参考前面第二章:6. ILI9341常用命令章节内容。

void  LCD_Draw_Rectangle(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t color)
{
    LCD_WR_REG(0x2A);
    LCD_WR_DATA(x1 >> 8);
    LCD_WR_DATA(x1 & 0xff);
    LCD_WR_DATA(x2 >> 8);
    LCD_WR_DATA(x2 & 0xff);

    LCD_WR_REG(0x2B);
    LCD_WR_DATA(y1 >> 8);
    LCD_WR_DATA(y1 & 0xff);
    LCD_WR_DATA(y2 >> 8);
    LCD_WR_DATA(y2 & 0xff);

    LCD_WR_REG(0x2C);
    for (uint8_t i = 0; i < (x2 - x1 + 1) * (y2 - y1 + 1); i++)
    {
        LCD_WR_DATA(color);    /*只写进去一个点*/
    }    
}

在初始化之后调用此函数,可以在LCD上绘制实心矩形。分别给定两个坐标点(x1,y1)和(x2,y2),就确定了矩形的位置,之后给定颜色,就可以绘制出矩形。当然坐标点要在显示屏的范围内。

如果已经正确读取了芯片ID,也正确绘制了矩形,那么就已经实现了FSMC驱动LCD的功能。其余的操作就是移植开发板的驱动代码了。这里就不赘述了。

如果移植上遇到困难,欢迎留言。

四、参考文献

《ILI9341参考手册》
《STM32F4中文参考手册》
《正点原子 STM32F4开发手册》


全文完,如果对你有帮助,欢迎点赞、转发、收藏!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值