STM32F10xx 通过 FSMC 与 ILI93xxTFTLCD驱动的通信的若干问题

怎甘沉沦 提交于 2019-12-01 07:00:26

关于FSMC的介绍请参考STM32中文参考手册,第9章“灵活的静态存储控制器”


问题1.

为什么使用FSMC连接ILI93xxLCD驱动?

答:

①.ILI93xx使用的是16位并口接口传数据,而FSMC可以实现总线方式传送,比单纯的IO口操作速度更快。同时这个16位并口采用的是intel8080时序,FSMC中也也有类似的时序,只是某些方面有区别。

简单一点说就是:

8080通过双总线控制,数据线,控制线(包括读使能
信号,写使能信号,片选信号,复位信号,数据/命令选择信号) 

FSMC通过三总线控制,数据线,地址线,控制线(包括读使能信号,写使能信号,片选信号)

相比8080时序,FSMC少了复位信号和数据/命令选择信号。(由于FSMC8080时序多了地址线,所以可以通过地址线存放数据/命令选择信号)


问题2

为什么在FSMC 使用bank1 ,区域1A16做数据/命令选择信号 的情况下,LCD_REG的地址是0x6000 0000,LCD_RAM的地址是0x6002 0000 ?

为什么给LCD_REG这个地址0x6000 0000中写数据就是向ILI93xx控制器写命令(或者直接说写寄存器),而向LCD_RAM这个地址0x6002 0000中写数据就是向控制器写数据?

 

答:

首先要清楚几个概念:

1.数据/命令选择信号是在A16线上的,只有它的值 [01]可以设置是写数据还是写命令。

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位为1x0~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区域中的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_REGLCD_RAM地址也相当于赋值,只是隐式的,给A16赋值)



未完,以后再更新













标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!