/*
*********************************************************************************************************
* 函 数 名: LCD_gpioFSMCInit
* 功能说明: 初始化LCD
* 形 参:无
* 返 回 值: 无
*********************************************************************************************************
*/
void LCD_gpioFSMCInit(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
FSMC_NORSRAMTimingInitTypeDef WriteTiming;
FSMC_NORSRAMInitTypeDef FSMC_NORSRAMInitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOD
| RCC_APB2Periph_GPIOE |RCC_APB2Periph_AFIO, ENABLE);
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_FSMC, ENABLE);
/* 设置
T_PEN  

A1
T_CS PA4
T_SCK  

A5
T_MISO PA6
T_MOSI PA7 为复用推挽输出 */
GPIO_InitStructure.GPIO_Pin =GPIO_Pin_1| GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOA, &GPIO_InitStructure);
/* 设置
D0-D1  

D14 PD15
D2-D3  

D0  

D1
D13-D15  

D8-PD10
nOE  

D4
nWE  

D5
nCS2 PD7
RS PD11(FSMC A16) 为复用推挽输出 */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3
| GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_7 | GPIO_Pin_8
| GPIO_Pin_9 | GPIO_Pin_10|GPIO_Pin_11| GPIO_Pin_14| GPIO_Pin_15 ;
/* */
GPIO_Init(GPIOD, &GPIO_InitStructure);
/* 设置
D4-D12  

E7-PE15 为复用推挽输出 */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7 | 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_Init(GPIOE, &GPIO_InitStructure);
/*
// PD11 推挽输出 复位、数据命令区分线
GPIO_InitStructure.GPIO_Pin =GPIO_Pin_11;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOD, &GPIO_InitStructure);
*/
// RCC_AHBPeriphClockCmd(RCC_AHBPeriph_FSMC, ENABLE);
WriteTiming.FSMC_AddressSetupTime = 0x02; //地址建立时间
WriteTiming.FSMC_AddressHoldTime = 0x00; //地址保持时间
WriteTiming.FSMC_DataSetupTime = 0x05; //数据建立时间
WriteTiming.FSMC_BusTurnAroundDuration = 0x00; //总线恢复时间
WriteTiming.FSMC_CLKDivision = 0x00; //时钟分频
WriteTiming.FSMC_DataLatency = 0x00; //数据保持时间
WriteTiming.FSMC_AccessMode = FSMC_AccessMode_A; //在地址\数据线不复用的情况下,ABCD模式的区别不大
FSMC_NORSRAMInitStructure.FSMC_Bank = FSMC_Bank1_NORSRAM4; //NOR FLASH的BANK4
FSMC_NORSRAMInitStructure.FSMC_DataAddressMux = FSMC_DataAddressMux_Disable; //数据与地址总线不复用
FSMC_NORSRAMInitStructure.FSMC_MemoryType = FSMC_MemoryType_NOR; //存储器类型NOR FLASH
FSMC_NORSRAMInitStructure.FSMC_MemoryDataWidth = FSMC_MemoryDataWidth_16b; //数据宽度为16位
FSMC_NORSRAMInitStructure.FSMC_BurstAccessMode = FSMC_BurstAccessMode_Disable; //使用异步写模式,禁止突发模式
FSMC_NORSRAMInitStructure.FSMC_WaitSignalPolarity = FSMC_WaitSignalPolarity_Low; //只在突发模式下有效,等待信号极性为低
FSMC_NORSRAMInitStructure.FSMC_WrapMode = FSMC_WrapMode_Disable; //禁止非对齐性突发模式
FSMC_NORSRAMInitStructure.FSMC_WaitSignalActive = FSMC_WaitSignalActive_BeforeWaitState; //仅在突发模式下有效,NWAIT信号在什么周期产生
FSMC_NORSRAMInitStructure.FSMC_WriteOperation = FSMC_WriteOperation_Enable; //写使能
FSMC_NORSRAMInitStructure.FSMC_WaitSignal = FSMC_WaitSignal_Disable; //仅在突发模式下有效,禁用NWAIT信号
FSMC_NORSRAMInitStructure.FSMC_ExtendedMode = FSMC_ExtendedMode_Disable; //禁止扩展模式,扩展模式可以使用独立的读、写模式
FSMC_NORSRAMInitStructure.FSMC_WriteBurst = FSMC_WriteBurst_Disable; //禁止突发写操作
FSMC_NORSRAMInitStructure.FSMC_ReadWriteTimingStruct = &WriteTiming; //配置读写时序
FSMC_NORSRAMInitStructure.FSMC_WriteTimingStruct = &WriteTiming; //配置写时序
FSMC_NORSRAMInit(&FSMC_NORSRAMInitStructure); //初始化FSMC配置
FSMC_NORSRAMCmd(FSMC_Bank1_NORSRAM4, ENABLE); //使能FSMC Bank1_SRAM Bank
}
/*-----------------------------------------------------------------------------------*/
//LCD地址结构体
typedef struct
{
u16 LCD_REG; //地址寄存器
u16 LCD_RAM; //数据寄存器
} LCD_TypeDef;
/*
TFTLCD通过RS信号来决定传送的数据是数据还是命令,本质上可以理解为一个地址信号,
比如我们把RS接在A0上面,那么当FSMC控制器写地址0的时候,会使得A0变为0,对TFTLCD来说,就是写命令。而FSMC写地址1的时候,A0将会变为1,对TFTLCD来说,就是写数据了。这样,就把数据和命令区分开了,他们其实就是对应SRAM操作的两个连续地址。当然RS也可以接在其他地址线上,战舰STM32开发板是把RS连接在A10上面的。
BANK1 第一区 0x6000 0000 --0x63FF FFFF
第二区 0x6400 0000 --0x64FF FFFF
第三区 0x6800 0000 --0x68FF FFFF
第四区 0x6C00 0000 --0x6CFF FFFF
BANK2 0x7000 0000 -- 0x7FFF FFFF
BANK3 0x8000 0000 -- 0x8FFF FFFF
BANK4 0x9000 0000 -- 0x9FFF FFFF
其中LCD_BASE,必须根据我们外部电路的连接来确定,我们使用Bank1.sector4就是从地址0X6C000000开始,而0X000007FE,则是A10的偏移量。我们将这个地址强制转换为LCD_TypeDef结构体地址,那么可以得到LCD->LCD_REG的地址就是0X6C00,07FE,对应A10的状态为0(即RS=0),而LCD-> LCD_RAM的地址就是0X6C00,0800(结构体地址自增),对应A10的状态为1(即RS=1)。
所以,有了这个定义,当我们要往LCD写命令/数据的时候,可以这样写:
LCD->LCD_REG=CMD; //写命令
LCD->LCD_RAM=DATA; //写数据
而读的时候反过来操作就可以了,如下所示:
CMD= LCD->LCD_REG;//读LCD寄存器
DATA = LCD->LCD_RAM;//读LCD数据
*/
#define LCD_BASE ((u32)(0x6C000000|0x0001FFFE)) // A16
#define LCD ((LCD_TypeDef *) LCD_BASE) // 对应LCD->LCD_REG 地址0x6C01 FFFE
// LCD->LCD_RAM 地址0x6001FFFE
/*-----------------------------------------------------------------------------------*/
//初始化lcd
//该初始化函数可以初始化各种ILI93XX液晶,但是其他函数是基于ILI9320的!!!
//在其他型号的驱动芯片上没有测试!
void LCD_Init(void)
{
LCD_gpioFSMCInit();
// mdelay(50);
// LCD_Reset();
mdelay(50);//
// Light = 1;
// LCD_WriteRAM(0xffff); //作用?????
DeviceCode=LCD_ReadReg(0X0000);
printf(" LCD ID:%x\n",DeviceCode); //打印LCD ID 十六进制
。
。
。
问题: 全速运行时,设备ID为 0x0000 , 单步时位 0x FFFE 错误!
原子哥能不能帮忙看看呢?