FSMC驱动液晶屏TFT LCD原理与代码
FSMC是STM32的一种外设,英文全称是“ Flexible static memory controller”,翻译成中文,就是“灵活的静态存储控制器”。
这个接口可以被用来驱动TFT LCD、PC卡、CF卡、SRAM、PSRAM、NAND FLASH、NOR FLASH。这里我们介绍的是如何驱动TFT LCD。
我们从硬件设计和程序设计两个方面来说。
一、硬件设计
- 数据引脚:TFT一般是16位数据接口DB0~DB15,需要用到FSMC_D0~FSMC_D15来连接。
- 控制引脚:TFT的控制引脚一般有4个。LCD_CS片选引脚,接到FSMC_NE1~4的任意一个引脚都行。LCD_RS数据/命令选择引脚,连接到FSMC_A0~25的任意一个引脚都行。RD读使能引脚,连接到FSMC_NOE。WR写使能引脚,连接到FSMC_NWE。
二、程序设计
- 第1步:把上面提到的20个单片机引脚设置为复用FSMC模式。
- 第2步:配置FSMC_NORSRAMInit()函数。
- 第3步:使用FSMC_NORSRAMCmd()使能BANK。
- 第4步:使用FSMC通信配置TFT寄存器,进行初始化。
下面是已经做好的程序代码,已验证,其中LCD_CS用的是FSMC_NE1,LCD_RS用的是FSMC_A16。
三、要点
1、关于LCD_CS引脚,我们可以选择4个引脚,即FSMC_NE1~4。选择好硬件连接引脚之后,在程序中的3个地方需要和硬件对应。
第1个地方是FSMC_NORSRAMInitTypeDef结构体成员FSMC_Bank的值,第2个地方是使用FSMC_NORSRAMCmd()使能函数的参数。
FSMC_NORSRAMInitStructure.FSMC_Bank = FSMC_Bank1_NORSRAM1;// 使用FSMC_NE1
......
FSMC_NORSRAMCmd(FSMC_Bank1_NORSRAM1, ENABLE);//使用FSMC_NE1
上面代码是使用FSMC_NE1连接LCD_CS的情况,如果是使用FSMC_NE2,这里的值就应该改为FSMC_Bank1_NORSRAM2,就是把最后的数字改过来,其它以此类推。

第3个地方是地址的基址,BANK1的起始地址是0x60000000,BANK1被划分成了4个区,每个区的大小是64M,即64x1024x1024=0x4000000。所以:
- FSMC_Bank1_NORSRAM1的 基址为0x60000000
- FSMC_Bank1_NORSRAM2的 基址为0x64000000
- FSMC_Bank1_NORSRAM3的 基址为0x68000000
- FSMC_Bank1_NORSRAM4的 基址为0x6C000000
2、关于LCD_RS引脚,当使用FSMC的8位数据模式时,我们可以选择FSMC_A0~A25的任意一个引脚,当使用FSMC的16位数据模式时,不能选择FSMC_A25,只能从FSMC_A0~A24中选择。这是因为在16位模式时,HADDR[25:1]和FSMC_A[24:0]对应。

同样,程序代码中,也需要和选择的引脚相对应。如果你用的是FSMC_A0连接到了LCD_RS,那么“写寄存器地址”和“给寄存器写数据”的代码就是:
/* 写TFT寄存器地址(写命令) */
#define LCD_WR_REG(add) ((*(volatile u16 *)((uint32_t)0x60000000)) = ((u16)add))
/* 给TFT寄存器写数据(写数据) */
#define LCD_WR_DATA(val) ((*(volatile u16 *) ((uint32_t)0x60000002)) = ((u16)(val)))
上面代码有个规律,写命令的数值就是对应的基址数值,写数据的数值是基址数值加上“1左移(地址序号+1)位”。如上面,地址是A0,就左移1位。最后的地址数值就是0x60000002。
如果用的是A16,那么,地址就是(1<<17)位,即0x20000,如果是用的BANK1的第1个区域,结果就是0x60000000 + 0x20000 = 0x60020000。