STM32F1系列单片机有多种外设,外设配置方式比较一致,一般是使能外设所在GPIO口时钟、使能外设的时钟,在禁止外设的情况下配置外设的时序以及中断和DMA等。大部分的外设配置相对简单,但是FSMC接口因为配置比较复杂,往往让一些初学者一头雾水。本文记录了本人在STM32F103ZET6的FSMC接口配置调试TFT LCD屏相关注意事项。
1 FSMC接口GPIO配置
/** FSMC GPIOConfiguration PF0 ------>
FSMC_A0 ------>
LCD_RS: 0: Reg,1:Data PE7 ------>
FSMC_D4 PE8 ------>
FSMC_D5 PE9 ------>
FSMC_D6 PE10 ------>
FSMC_D7 PE11 ------>
FSMC_D8 PE12 ------>
FSMC_D9 PE13 ------>
FSMC_D10 PE14 ------>
FSMC_D11 PE15 ------>
FSMC_D12 PD8 ------>
FSMC_D13 PD9 ------>
FSMC_D14 PD10 ------>
FSMC_D15 PD14 ------>
FSMC_D0 PD15 ------>
FSMC_D1 PD0 ------>
FSMC_D2 PD1 ------>
FSMC_D3 PD4 ------>
FSMC_NOE ------>
LCD_RD Default:1,Value:0 PD5 ------>
FSMC_NWE ------>
LCD_WR Default:1,Value:0 PG12 ------>
FSMC_NE4 ------>
LCD_CS Default:1,Value:0
2 初始化FSMC时序
/* FSMC initializationfunction */
FSMC_NORSRAM_TimingTypeDef Timing;SRAM_HandleTypeDef hsram1;
hsram1.Instance = FSMC_NORSRAM_DEVICE;
hsram1.Extended =FSMC_NORSRAM_EXTENDED_DEVICE;
/* hsram1.Init */
hsram1.Init.NSBank = FSMC_NORSRAM_BANK4;hsram1.Init.DataAddressMux =FSMC_DATA_ADDRESS_MUX_DISABLE;
hsram1.Init.MemoryType=FSMC_MEMORY_TYPE_NOR;hsram1.Init.MemoryDataWidth =FSMC_NORSRAM_MEM_BUS_WIDTH_16;hsram1.Init.BurstAccessMode =FSMC_BURST_ACCESS_MODE_DISABLE;hsram1.Init.WaitSignalPolarity =FSMC_WAIT_SIGNAL_POLARITY_LOW;hsram1.Init.WrapMode =FSMC_WRAP_MODE_DISABLE;hsram1.Init.WaitSignalActive =FSMC_WAIT_TIMING_BEFORE_WS;hsram1.Init.WriteOperation =FSMC_WRITE_OPERATION_ENABLE;hsram1.Init.WaitSignal =FSMC_WAIT_SIGNAL_DISABLE;hsram1.Init.ExtendedMode =FSMC_EXTENDED_MODE_DISABLE;hsram1.Init.AsynchronousWait =FSMC_ASYNCHRONOUS_WAIT_DISABLE;hsram1.Init.WriteBurst =FSMC_WRITE_BURST_DISABLE;
/* Timing */ Timing.AddressSetupTime = 0x04;
Timing.AddressHoldTime = 0x02; Timing.
DataSetupTime = 0x08;
Timing.BusTurnAroundDuration = 0x00; Timing.CLKDivision = 0x00; Timing.DataLatency = 0x00; Timing.AccessMode = FSMC_ACCESS_MODE_B;
后面数值决定读写屏快慢。
注意点:
1 因为STM32的地址是32bit的,数据是按照8bit组织的,如果lcd的数据选择8bit的话,地址A0就是正常的输出,如0x60000000输出A0=0; 0x6000 0001输出A0=1;对应数据是byte;如果lcd的数据选择16bit的话,地址A0就,如0x60000000输出A0=0; 而0x60000002对应A0=1;对应数据是word,也就是说每两个原来基于byte结构的地址对应一个地址线上实际的word长度的地址;
#define Bank1_LCD_D ((uint32_t)0x6C000002)
//DispData ADDR#define Bank1_LCD_C ((uint32_t)0x6C000000)
//DispReg ADDR
void LCD_WR_REG(uint16_t index){
*(__IOuint16_t *) (Bank1_LCD_C) = index
;}
uint16_t LCD_READ_DATA(void){
uint16_ta = 0;
a=*(__IOuint16_t *) (Bank1_LCD_D);
//L return a;}
2 Image2LCD软件转换时注意扫描方式和数据位宽度,以及高低为顺序。
实际效果: