Flexible static memory controller(FSMC)
今天在處理TFT彩屏的時候突然發現有人用FSMC控制器來處理,然后就認真的研究了下FSMC;

可見他分為4個塊,三個類型,我們可以根據自己的需要來選擇;這次我就直說FSMC 的Block 1;
首先,基地址BASE_ADDR = 6000 0000;至于片選,datasheet上也說了,我們可以通過控制HADDR(27,26)來選擇操作;

然后還有今天一直困擾我的問題,我要選擇A16,我用的是16位數據,他的數據地址為6000 0000 + 2^16*2 = 6002 0000;我一直都在疑惑:明明是A16,為什么是第17位被置1,后來終于在datasheet上發現這個問題的根源!

上面說的很清楚,數據寬度為16位時,HADDR[25:1]與FSMC_A[24:0]相連,那么這時候的FSMC_A16,就與HADDR[17]相連,所以地址就是6000 0000 + 2^17;
下面來看看FSMC如何與TFT聯系起來!

A16 --> RS -- 使能
D0~D15 數據線
FSMC_WE --> WE
FSMC_OE --> OE
這個連接方式讓我想起了微機原理上的8059;呵呵,如果你學過了微機原理,看到這個圖應該懂了80%;
代碼分析:
~~~
FSMC_NORSRAMInitTypeDef ?FSMC_NORSRAMInitStructure;
FSMC_NORSRAMTimingInitTypeDef ?p;
GPIO_InitTypeDef ?GPIO_InitStructure;?
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_FSMC, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOC |
? ? ? ? ? ? ? ? ? ? ? ?RCC_APB2Periph_GPIOD | RCC_APB2Periph_GPIOE , ENABLE); ?
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13;? ? ? ?
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOD, &GPIO_InitStructure); ? ?
GPIO_SetBits(GPIOD, GPIO_Pin_13);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOE, &GPIO_InitStructure); ?
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_4 | GPIO_Pin_5 |
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10 | GPIO_Pin_14 |?
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? GPIO_Pin_15;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOD, &GPIO_InitStructure);
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);?
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;?
GPIO_Init(GPIOD, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11 ;?
GPIO_Init(GPIOD, &GPIO_InitStructure);?
p.FSMC_AddressSetupTime = 0x02;
p.FSMC_AddressHoldTime = 0x02;
p.FSMC_DataSetupTime = 0x05;
p.FSMC_AccessMode = FSMC_AccessMode_B;
FSMC_NORSRAMInitStructure.FSMC_Bank = FSMC_Bank1_NORSRAM1;
FSMC_NORSRAMInitStructure.FSMC_DataAddressMux = FSMC_DataAddressMux_Disable;
FSMC_NORSRAMInitStructure.FSMC_MemoryType = FSMC_MemoryType_NOR;
FSMC_NORSRAMInitStructure.FSMC_MemoryDataWidth = FSMC_MemoryDataWidth_16b;
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;
FSMC_NORSRAMInitStructure.FSMC_WriteOperation = FSMC_WriteOperation_Enable;
FSMC_NORSRAMInitStructure.FSMC_WaitSignal = FSMC_WaitSignal_Disable;
FSMC_NORSRAMInitStructure.FSMC_ExtendedMode = FSMC_ExtendedMode_Disable;
FSMC_NORSRAMInitStructure.FSMC_WriteBurst = FSMC_WriteBurst_Disable;
FSMC_NORSRAMInitStructure.FSMC_ReadWriteTimingStruct = &p;
FSMC_NORSRAMInitStructure.FSMC_WriteTimingStruct = &p;
FSMC_NORSRAMInit(&FSMC_NORSRAMInitStructure);?
FSMC_NORSRAMCmd(FSMC_Bank1_NORSRAM1, ENABLE); ?
~~~
時鐘初始化是必須的!希望大家不要forget了!
另外gpio的初始化,要看兩個地方:1,數據手冊上,每種管腳初始化成什么模式;2,哪些管腳需要初始化;

管腳對應自己對著原理圖一個一個找!
FSMC_NORSRAMTimingInitTypeDef ?設置
p.FSMC_AddressSetupTime = 0x02;
p.FSMC_AddressHoldTime = 0x02;
p.FSMC_DataSetupTime = 0x05;
p.FSMC_AccessMode = FSMC_AccessMode_B;
這里我只設置了4項,因為其他幾項都是與norflash有關的,所以我們不用設置,因為TFT內部是RAM;
具體時間參考,在datasheet上也給了說明:

見網上有人設置FSMC_ADDressHoldTime = 0x0;發現也沒啥影響,但是我們還是最好按照這個標準來!因為畢竟是官方給的標準!
~~~
FSMC_NORSRAMInitStructure.FSMC_Bank = FSMC_Bank1_NORSRAM1;
~~~
選擇Bank1_NORSRAM1;因為我們本身就是選的他毋庸置疑;
~~~
FSMC_NORSRAMInitStructure.FSMC_DataAddressMux = FSMC_DataAddressMux_Disable;
~~~
我再TFT上也沒有用到多路復用,因為我就只是跟TFT通信,說到這,我們還可以用它來控制4個彩屏一起顯示!
~~~
FSMC_NORSRAMInitStructure.FSMC_MemoryType = FSMC_MemoryType_PSRAM;
~~~
這個參數是用來選擇到底是哪個類型的存儲器,他有三個option:
~~~
#define FSMC_MemoryType_SRAM ? ? ? ? ? ? ? ? ? ? ? ? ? ?((uint32_t)0x00000000)
#define FSMC_MemoryType_PSRAM ? ? ? ? ? ? ? ? ? ? ? ? ? ((uint32_t)0x00000004)
#define FSMC_MemoryType_NOR ? ? ? ? ? ? ? ? ? ? ? ? ? ? ((uint32_t)0x00000008)
~~~
因為我不知道彩屏的內存到底是哪種類型的,我測試了下,三個選項對彩屏都是一樣的效果,因為我對SRAM,NOR比較熟悉,所以就選了一個不熟悉的選項;
~~~
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;
FSMC_NORSRAMInitStructure.FSMC_WriteOperation = FSMC_WriteOperation_Enable;
FSMC_NORSRAMInitStructure.FSMC_WaitSignal = FSMC_WaitSignal_Disable;
FSMC_NORSRAMInitStructure.FSMC_ExtendedMode = FSMC_ExtendedMode_Disable;
FSMC_NORSRAMInitStructure.FSMC_WriteBurst = FSMC_WriteBurst_Disable;
FSMC_NORSRAMInitStructure.FSMC_ReadWriteTimingStruct = &p;
FSMC_NORSRAMInitStructure.FSMC_WriteTimingStruct = &p;
~~~
然后我的彩屏控制基地址為
~~~
#define Bank1_LCD_DATA ? ?((uint32_t)0x60020000)?
#define Bank1_LCD_CTL ? ? ((uint32_t)0x60000000)
~~~
使用方法:
~~~
*(__IO uint16_t *) (Bank1_LCD_C)= reg;
*(__IO uint16_t *) (Bank1_LCD_D)= cmd;
~~~
可能理解的還不是太好,請大家多多指點;
- 前言
- 【菜鳥入門】stm32的第一個程序--LED
- 【菜鳥入門】stm32 之 掃描按鍵
- 【菜鳥入門】stm32 之 中斷按鍵
- 【菜鳥入門】stm32 之 USART
- 【菜鳥入門】stm32 之 iic
- 【菜鳥入門】stm32 之 eeprom
- 【菜鳥入門】stm32 之 pwm
- 【菜鳥入門】stm32 之 ADC 模數轉換
- 【菜鳥入門】stm32 之 實時時鐘
- 【菜鳥入門】stm32 之 DMA
- 【菜鳥入門】stm32 之 DAC
- 【STM庫應用】stm32 之 USART
- 中斷源去抖辦法
- stm32 啟動代碼應用技巧
- 【STM庫應用】stm32 之 IIC應用
- 【STM庫應用】stm32 之 中斷按鍵初始化(注意事項)
- 關于結構體初始化
- 【STM庫應用】stm32 之 TIM (詳解一 通用定時器)
- 【STM庫應用】stm32 之 TIM (詳解二 脈沖寬度、周期測量)
- 【stm32庫應用】SD驅動移植(基于SDIO外設)
- SD卡fat文件系統移植
- stm32 DMA初始化選項研究
- stm32 靈活靜態存儲控制器(FSMC)(NORFLASH\PSRAM)
- 【stm32+uC/OS-II】ucosii移植簡單詳細步驟
- STM32 加入調試信息來調試代碼
- NRF24L01 無線通信模塊使用