MM32系列微控制器為用戶提供了豐富的選擇,可適用于工業控制、智能家電、建筑安防、醫療設備以及消費類電子產品等多方位嵌入式系統設計。在某些應用中,需要較大容量的存儲空間用于存儲數據;這時可以通過SPI 外擴NOR Flash,NAND Flash, 或者通過SDIO擴展SD Card或TF-Card。但有些需要高速存儲數據,上述方式還是不夠快速,這時可以使用MM32F3270系列的FSMC來外擴并行NOR Flash來實現。
并行NOR Flash與并行SRAM和PSRAM的讀寫接口大部分相同,但NOR Flash的寫入速度與SRAM和PSRAM比較,相對較慢,需要通過NWAIT 信號檢查NOR Flash的操作狀態,并做一些等待,相應的時序需要根據不同的NOR Flash芯片所規定的參數而做相應的設置即可。
本文接下來就使用MM32F3270外掛S29GL128P NOR Flash芯片來演示FSMC對NOR Flash芯片的設置與讀寫。
前文已經介紹了MM32F3270的FSMC的接口功能與特色。結合MM32F3270 的FSMC外部接口信號,可使用異步方式訪問NOR Flash,可以選用復用或非復用方式擴展NOR Flash,還可以通過配置實現外擴8位總線或16位總線接口的NOR Flash。
表1:FSMC控制器外部信號
MM32F3270系列MCU因為封裝的原因,導致只有部分MCU產品可以通過硬件復用出全部或部分的FSMC接口的相關GPIO;外擴NOR Flash也只有使用 LQFP144引腳封裝MCU芯片才能支持連接地址數據非復用和復用方式外擴并行NOR Flash;而LQFP100引腳封裝芯片因地址線縮減,僅支持連接地址數據復用方式外擴并行NOR Flash。LQFP64因為無法引出足夠的地址與數據總線,同樣不支持外擴并行NOR Flash。
表2:MM32F3270不同封裝芯片與NOR Flash接口
目前市場上非復用型16位數據總線接口的NOR Flash也是較為普遍,下面針對非復用方式,介紹MCU與NOR Flash的硬件原理圖設計和軟件寄存器配置。
在此用MM32F3270的FSMC接口擴展S29GL128P NOR Flash,其原理框圖如下:
圖1:NOR Flash原理框圖
S29GL128P的數據按 16 位的Half Word尋址,容量128M Bit, 16M字節,從芯片手冊中可以查詢到S29GL128P的引腳功能描述如下:
表3:NOR Flash引腳信號
S29GL128P可以通過CS, OE, WR, WP#, RY/BY#控制電路,結合Address與Data I/O實現對NOR Flash的讀寫操作。
1、FSMC非復用方式控制NOR Flash的硬件設計
表4:NOR Flash數據, 地址, 讀寫信號與MCU接口的引腳說明
外部設備地址映像從FSMC的角度看,FSMC外擴尋址空間用于訪問最多4個FSMC地址映射空間,可以用于訪問4個NOR閃存或SRAM/PSRAM存儲設備,并對應的有4個專用的片選FSMC_NE[4:1]。
外部存儲器劃分為固定大小為64M字節的四個存儲塊,見下圖。
存儲區塊與片選信號對應關系:
HADDR是需要轉換到外部存儲器的內部AHB地址線。HADDR[25:0]包含外部存儲器地址。HADDR是字節地址,而存儲器訪問不都是按字節訪問,因此接到存儲器的地址線依存儲器的數據寬度有所不同,如下表:
對于16位寬度的外部存儲器,FSMC將在內部使用HADDR[25:1]產生外部存儲器的地址FSMC_A[24:0]。不論外部存儲器的寬度是多少(16位或8位),FSMC_A[0]始終應該連到外部存儲器的地址線A[0]。
根據外部NOR Flash設計原理圖:
2、FSMC非復用方式控制NOR Flash的程序設計
根據配置的接口電路配置GPIO初始化程序與FSMC初始化程序。
void FSMC_NOR_Init(void) { FSMC_InitTypeDef FSMC_InitStructure; FSMC_NORSRAM_Bank_InitTypeDef FSMC_BankInitStructure; FSMC_NORSRAM_BankStructInit( FSMC_BankInitStructure); FSMC_NORSRAMStructInit( FSMC_InitStructure); RCC_AHB3PeriphClockCmd(RCC_AHB3ENR_FSMC, ENABLE); FSMC_BankInitStructure.FSMC_SMReadPipe = 0; FSMC_BankInitStructure.FSMC_ReadyMode = 0; FSMC_BankInitStructure.FSMC_WritePeriod = 15; FSMC_BankInitStructure.FSMC_WriteHoldTime = 3; FSMC_BankInitStructure.FSMC_AddrSetTime = 3; FSMC_BankInitStructure.FSMC_ReadPeriod = 15; FSMC_BankInitStructure.FSMC_DataWidth = FSMC_DataWidth_16bits; FSMC_NORSRAM_Bank_Init( FSMC_BankInitStructure, FSMC_NORSRAM_BANK1); FSMC_InitStructure.FSMC_Mode = FSMC_Mode_NorFlash; FSMC_InitStructure.FSMC_TimingRegSelect = FSMC_TimingRegSelect_0; FSMC_InitStructure.FSMC_MemSize = FSMC_MemSize_64MB; FSMC_InitStructure.FSMC_MemType = FSMC_MemType_FLASH; FSMC_InitStructure.FSMC_AddrDataMode = FSMC_AddrDataDeMUX; FSMC_NORSRAMInit( FSMC_InitStructure); }
GPIO初始化
void FSMC_GPIO_Init(void) { GPIO_InitTypeDef GPIO_InitStructure; GPIO_StructInit( GPIO_InitStructure); RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE); RCC_AHBPeriphClockCmd(RCC_AHBENR_GPIOB | RCC_AHBENR_GPIOC | RCC_AHBENR_GPIOA | RCC_AHBENR_GPIOD | RCC_AHBENR_GPIOE | RCC_AHBENR_GPIOF | RCC_AHBENR_GPIOG, ENABLE); GPIO_PinAFConfig(GPIOD, GPIO_PinSource4, GPIO_AF_12); //NOE GPIO_PinAFConfig(GPIOD, GPIO_PinSource5, GPIO_AF_12); //NWE GPIO_PinAFConfig(GPIOD, GPIO_PinSource6, GPIO_AF_12); //NWAIT GPIO_PinAFConfig(GPIOD, GPIO_PinSource11, GPIO_AF_12); //A16 GPIO_PinAFConfig(GPIOD, GPIO_PinSource12, GPIO_AF_12); //A17 GPIO_PinAFConfig(GPIOD, GPIO_PinSource13, GPIO_AF_12); //A18 GPIO_PinAFConfig(GPIOD, GPIO_PinSource14, GPIO_AF_12); //D0 GPIO_PinAFConfig(GPIOD, GPIO_PinSource15, GPIO_AF_12); //D1 //省略部分代碼 GPIO_PinAFConfig(GPIOF, GPIO_PinSource0, GPIO_AF_12); //A0 GPIO_PinAFConfig(GPIOF, GPIO_PinSource1, GPIO_AF_12); //A1 GPIO_PinAFConfig(GPIOF, GPIO_PinSource2, GPIO_AF_12); //A2 GPIO_PinAFConfig(GPIOF, GPIO_PinSource3, GPIO_AF_12); //A3 //省略部分代碼 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_All; 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_6; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_FLOATING; GPIO_Init(GPIOD, GPIO_InitStructure); //省略部分代碼 }
從選擇的片選信號與FSMC外擴存儲映像空間可以得出Bank2地址為0x64000000,使用該地址作為讀寫外部NOR Flash的基地址。
#define NOR_FLASH_START_ADDR ((u32)0x64000000) #define NOR_FLASH_END_ADDR ((u32)0x67FFFFFF) //讀一個半字 u16 FSMC_NOR_ReadHalfWord(u32 ReadAddr) { NOR_WRITE(ADDR_SHIFT(0x00555), 0x00AA); NOR_WRITE(ADDR_SHIFT(0x002AA), 0x0055); NOR_WRITE((NOR_FLASH_START_ADDR + ReadAddr), 0x00F0 ); /* exit autoselect (write reset command) */ return (*(vu16*)((NOR_FLASH_START_ADDR + ReadAddr))); } //連續讀一塊半字數據 void FSMC_NOR_ReadBuffer(u16* pBuffer, u32 ReadAddr, u32 NumHalfwordToRead) { NOR_WRITE(ADDR_SHIFT(0x0555), 0x00AA); NOR_WRITE(ADDR_SHIFT(0x02AA), 0x0055); NOR_WRITE((NOR_FLASH_START_ADDR + ReadAddr), 0x00F0); /* exit autoselect (write reset command) */ for(; NumHalfwordToRead != 0x00; NumHalfwordToRead--) { // Read a Halfword from the NOR *pBuffer++ = *(vu16*)((NOR_FLASH_START_ADDR + ReadAddr)); ReadAddr = ReadAddr + 2; } }
讀寫外部NOR Flash與讀寫外部SRAM的操作,地址尋址方式是一樣的,但NOR Flash的寫數據有較大的不同。
以單個Word編程為例,如下為寫單個Word的流程圖與實現代碼:
NOR_Status FSMC_NOR_WriteHalfWord(u32 WriteAddr, u16 Data) { NOR_WRITE(ADDR_SHIFT(0x0555), 0x00AA); NOR_WRITE(ADDR_SHIFT(0x02AA), 0x0055); NOR_WRITE(ADDR_SHIFT(0x0555), 0x00A0); NOR_WRITE((NOR_FLASH_START_ADDR + WriteAddr), Data); return (FSMC_NOR_GetStatus(Program_Timeout)); }
通過MindMotion的官網下載MM32F3270 lib_Samples:
工程路徑如下:
~MM32F327x_SamplesLibSamplesFSMCFSMC_NOR
可以看到詳細的樣例與功能操作。
下章的題目為《使用MM32F3270 的FSMC驅動外部OLED》講解通過FSMC外擴并口OLED的實現。
來源:靈動MM32MCU
免責聲明:本文為轉載文章,轉載此文目的在于傳遞更多信息,版權歸原作者所有。本文所用視頻、圖片、文字如涉及作品版權問題,請聯系小編進行處理
審核編輯 黃宇
-
芯片
+關注
關注
455文章
50816瀏覽量
423613 -
NOR flash
+關注
關注
2文章
91瀏覽量
23017 -
FSMC
+關注
關注
0文章
55瀏覽量
38151
發布評論請先 登錄
相關推薦
評論