STM32_ FSMC

eg:STM32F407ZGT6

目录

1:FSMC的功能简介

2:FSMC框图

3:  FSMC HADDR与FSMC_A 的地址问题

4:FSMC寄存器介绍


前言:

从51学到STM32的FSMC 时候,我感觉很难,开始对着视频一顿猛刷,看的我雨里雾里。不知道这到底是个啥玩意。后来,慢慢往后学,我才顿悟了,说简单点,FSMC就是一个方便使用者来连接外挂设备的一个工具,比如你要用到TFTLCD彩屏,外扩的SRAM芯片,你当然可以用软件去配置引脚来模拟器件通信的时序,就像在51里面软件模拟IIC时序来驱动1302一样,但是这样无疑会很复杂,那么,为了方便使用,STM32就造出来个FSMC来硬件实现这个时序问题,你要做的就是配置寄存器即可。

1:FSMC的功能简介

灵活的静态存储控制器(FSMC),其主要用途:

  • 将AHB数据通信事务转换为适当的外部器件协议
  • 满足外部器件的访问时序要求

STM32的FSMC接口支持包括(连接静态存储器映射的器件)

  • 静态随机访问存储器(SRAM):是随机存取存储器的一种,所谓“静态”,是指这种存储器只要保持通电,就可以一直保持数据
  • 只读存储器(ROM):只读存储器,只读不可写,断电可以保持数据,更改数据只能在特定条件下
  • NOR Flash/OneNAND Flash:非易失闪存技术
  • PSRAM(4个存储区域):伪静态随机存储器

 

2:FSMC框图

FSMC包含四个主要模块:

STM32_ FSMC_第1张图片

  • AHB接口(包括FSMC配置寄存器)
  • NOR Flash/PSRAM 控制器
  • NAND Flash/PC卡控制器
  • 外部器件接口

1:AHB接口:CPU和其他AHB总线主设备可通过该AHB从设备接口访问外部静态存储器,我们所访问的外部存储器一般是16或8位宽,而AHB是32位宽,所以用AHB去访问时。会划分成多个16或8位访问。

 

2:NOR Flash/PSRAM  FSMC会生成适当的信号时序,以驱动以下类型的存储器

  • 异步SRAM和ROM : 8位,16位,32位
  • PSRAM :异步模式,突发模式,复用或非复用
  • NOR Flash :异步模式或突发模式,复用或非复用

至于各种模式下引脚的定义,数据手册中都有详细的概述,不多说

 

3:NAND Flash/PC卡控制器   FSMC会生成相应的信号时序,用于驱动以下类型的设备

  • NAND Flash :8位,16位
  • 16位PC卡兼容设备

 

4:外部器件接口

从FSMC的角度,外部存储器被划分为4个固定大小的存储区域,每个存储区域的大小位256M

  • 存储区域1可连接多达4个NOR Flash或PSRAM存储器器件,带4个专用片选信号
  • 存储区域2、3用于连接NAND Flash器件(每个存储区域一个器件)
  • 存储区域4用于连接PC卡设备

STM32_ FSMC_第2张图片

 Bank1也是我们最长使用的一个区

NOR/PSRAM地址映射:

Bank1的256M字节空间由28根地址线(HADDR[27:0])寻址,这里HADDR,是内部AHB地址总线,其中HADDR[25:0]来自外部存储器地址FSMC_A[25:0],而HADDR[26:27]对4个区进行寻址,详细的瞅数据手册,

这里有一个理解难点

当Bank1接的是16位宽度存储器的时候:HADDR[25:1]->FSMC_A[24:0]

当Bank1接的是8位宽度存储器的时候:HADDR[25:0]->FSMC_A[25:0]

why?

往下瞅

 

3:FSMC HADDR与FSMC_A 的地址问题

首先说一个前提:STM32 单片机的一个地址(如:0x2000 0000)对应的数据是一个字节

也就是说如果定义一个16位数组 u16 temp[5]  如果temp[0]对应的地址是0x0000 0000 那么temp[1]对应的地址是0x0000 0002 (地址是加2,因为前面说了,32一个地址对应一个字节,U16,是两个字节)、、

 

假设此时我们有一个 64K*8bit 的sram

那很简单 stm32的A0~A15 与存储器A0~A15连接 大家很容易理解

 

若此时是 64K*16bit 的sram

也就是此时sram的一个地址对应两个字节 但是stm32是一个地址一个字节 这就出现了对准的问题

如果我们的地址线依然是stm32A0~A15 和 存储器的A0~A15 连接 

如果stm32要从sram中读取前面提到数组中的temp[1]

stm32会给出0x0000002(二进制地址0000000000000010b) 可是对于我们这个sram来说 读到却是temp[2],因为sram一个地址就是一个16位数据,这个地方好好想一下,于32来说,要挪两下,而16位的SRAM不同,只需要挪一下。 

为了解决这个问题 我们只需要在给sram送地址时 右移一位 再送地址 即可(sram的一个地址对应stm32两个地址的数据)

比如读取0x0000002 右移一位(即除2)为0x0001(000000000000001b) 此时对应的就是temp[1]

 

此时会有另外一个问题 每次都右移一位 A0没用吗 也即只能读写偶地址的数据吗?

这也就是NBL0和NBL1的作用了 如果你要进行字节操作 

如stm32发送地址0x0000001读取一个字节 右移一位对应的是sram地址0x0000处的16位数据 FSMC会根据AO 来控制NBLO和NBL1若为10 读取高字节数据

所以呢  偶字节读写时仅NBL0有效,奇字节读写时仅NBL1有效 低电平有效

 

4:FSMC寄存器介绍

关于FSMC的一些访问模式,就不写了,太多了,可以去看数据手册

关于寄存器的描述,也不都贴出来,看数据手册比我这好多了,主要来说一下寄存器的组合

在ST官方库提供的寄存器定义里面,并没有定义FSMC_BCRx,FSMC_BTRx,FSMC_BWTRx等这些个单独的寄存器,而是进行了一些组合,规律如下 

FSMC_BCRx和FSMC_BTRx,组合成BTCR[8]寄存器组,他们的对应关系如下:

  • BTCR[0]对应FSMC_BCR1
  • BTCR[1]对应FSMC_BTR1
  • BTCR[2]对应FSMC_BCR2
  • BTCR[3]对应FSMC_BTR2
  • BTCR[4]对应FSMC_BCR3
  • BTCR[5]对应FSMC_BTR3
  • BTCR[6]对应FSMC_BCR4
  • BTCR[7]对应FSMC_BTR4

FSMC_BWTRx则组合成BWTR[7]他们的对应关系如下:

  • BWTR[0]对应FSMC_BWTR1
  • BWTR[2]对应FSMC_BWTR2
  • BWTR[4]对应FSMC_BWTR3
  • BWTR[6]对应FSMC_BWTR4
  • BWTR[1]、BWTR[3]和BWTR[5]保留,没有用到。
#define FSMC_Bank1          ((FSMC_Bank1_TypeDef *) FSMC_Bank1_R_BASE)

typedef struct
{
  __IO uint32_t BTCR[8];    /*!< NOR/PSRAM chip-select control register(BCR) and chip-select timing register(BTR), Address offset: 0x00-1C */   
} FSMC_Bank1_TypeDef; 


#define FSMC_Bank1E         ((FSMC_Bank1E_TypeDef *) FSMC_Bank1E_R_BASE)
typedef struct
{
  __IO uint32_t BWTR[7];    /*!< NOR/PSRAM write timing registers, Address offset: 0x104-0x11C */
} FSMC_Bank1E_TypeDef;

 要访问这些寄存器,就要访问这些数组中的元素了,这个还是很好理解

 

 

你可能感兴趣的:(STM32,stm32,嵌入式)