关于FSMC的介绍请参考STM32中文参考手册,第9章“灵活的静态存储控制器”
问题1.
为什么使用FSMC连接ILI93xxLCD驱动?
答:
①.ILI93xx使用的是16位并口接口传数据,而FSMC可以实现总线方式传送,比单纯的IO口操作速度更快。同时这个16位并口采用的是intel8080时序,FSMC中也也有类似的时序,只是某些方面有区别。
简单一点说就是:
8080通过双总线控制,数据线,控制线(包括读使能
信号,写使能信号,片选信号,复位信号,数据/命令选择信号)
FSMC通过三总线控制,数据线,地址线,控制线(包括读使能信号,写使能信号,片选信号)
相比8080时序,FSMC少了复位信号和数据/命令选择信号。(由于FSMC比8080时序多了地址线,所以可以通过地址线存放数据/命令选择信号)
问题2:
为什么在FSMC 使用bank1 ,区域1,A16做数据/命令选择信号 的情况下,LCD_REG的地址是0x6000 0000,而LCD_RAM的地址是0x6002 0000 ?
为什么给LCD_REG这个地址0x6000 0000中写数据就是向ILI93xx控制器写命令(或者直接说写寄存器),而向LCD_RAM这个地址0x6002 0000中写数据就是向控制器写数据?
答:
首先要清楚几个概念:
1.数据/命令选择信号是在A16线上的,只有它的值 [0:1]可以设置是写数据还是写命令。
2.无论命令还是数据都是通过数据线D[15:0] 传过来的
明白这两点再开始后面的讲解,首先看源码,现在网上公开的代码主要有这两种形式来写命令和数据,这里都展示一下
第一种,结构体类的
<span style="font-size:14px;">//LCD地址结构体
typedef struct
{
u16 LCD_REG;
u16 LCD_RAM;
} LCD_TypeDef;
//使用NOR/SRAM的 Bank1.sector4,地址位HADDR[27,26]=11 A10作为数据命令区分线
//注意设置时STM32内部会右移一位对其! 111110=0X3E
#define LCD_BASE ((u32)(0x6C000000 | 0x000007FE))
#define LCD ((LCD_TypeDef *) LCD_BASE)</span>
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
第二种,直接赋地址
#define Bank1_LCD_D (u32)0x60020000
#define Bank1_LCD_C (u32)0x60000000
//使用NOR/SRAM的 Bank1.sector1,地址位HADDR[27,26]=11 A16作为数据命令区分线
void LCD_WR_REG(u16 index)
{
*(__IO u16 *)(Bank1_LCD_C)=index;
}
void LCD_WR_Data(u16 val)
{
*(__IO u16 *)(Bank1_LCD_D)=val;
}
void LCD_WR_CMD(u16 index,u16 val)
{
*(__IO u16 *)(Bank1_LCD_C)=index;
*(__IO u16 *)(Bank1_LCD_D)=val;
}
总结一下,要使得数据命令选择位(D/C位)至1,即Ax位为1(x取0~24),首先确定基地址,就是bankX的首地址,然后根据所选Ax的偏移量来确定。
举个例子:使用NOR/SRAM的 Bank1.sector1, A16作为数据命令选择位
bank1的首地址为0x6000 0000 (可通过手册知道)
Ax作为数据命令选择位,偏移量的算法是 2*(2^x) +0x6000 0000 = 0x2 0000 + 0x6000 0000 = 0x6002 0000(原理是 25根地址线将 bank1区域1 中的64M分成了26份),0x6002 0000代表在A16这个位上置1(请将思维转换至二进制),
同时,只要这个32位的数(0x6002 0000)中2那个位置上不为2(其他地方不管是什么够可以,但是要保证在当前所使用的区域的地址区间内),即代表A16这个位置不为1。(这可以解释结构体程序中为什么LCD_REG= ((u32)(0x6C000000 | 0x000007FE)),要使数据命令位为1,地址应为0x6c00 0800)
接下来解释为什么向这两个地址写数据就能相应的写数据写命令呢
我一开始说明了要搞清楚数据是从D15~D0口传进的,而这些IO口是由FSMC复用输出的(也就是说,无论你给的地址是哪里,数据输出的地方不变,不会给其他的地方),
前面已经说过虽然对于FSMC来说地址线有很多条但是我们用的只有一条,而这一条又控制了输入的数是给寄存器还是给RAM,而0x6002 0000这个地址上A16就是等于1,其他地址就不是等于1,这样就做到了省去写A16的过程,既然前面已经确认了A16的值,那后面的值自然就给相应的寄存器或者RAM。*(也就是说LCD_REG,LCD_RAM地址也相当于赋值,只是隐式的,给A16赋值)
未完,以后再更新
来源:CSDN
作者:izayl
链接:https://blog.csdn.net/izayl/article/details/45510627