一、测试环境
野火stm32f407开发板
电路原理图以及对应的引脚
二、stm32单片机FSMC介绍
stm32单片机关于FSMC的介绍,部分截图。
数据手册部分:
参考手册部分:
FSMC框架
这里的 HADDR 是需要转移到外部设备的内部 AHB 地址线,HADDR 是字节地址,而存储器访问不都是按字节访问,因此接到存储器的地址线根据存储器的数据宽度有所不同。如果数据宽度为 8 位,则 HADDR[25:0]与 FSMC_A[25:0]相连;如果数据宽度为 16 位,那么 HADDR[25:1]与 FSMC_A[24:0]相连,HADDR[0]不接(这句话很重要,在 STM32 地址映射到 FSMC 接口的结构中,HADDR 信号线是需要转换到外部存储器的内部 AHB 地址线,是字节地址。在 16bit 数据宽度下,实际访问地址为右移一位之后的地址。可参考lcd显示屏(显示屏的地址设置需要移位(和结构设计有关,自动移位。所以fsmc模拟8080接口,数据/命令选择相当于地址线,需要实际地址进行移位。),sram存储设置的地址不用移位(和结构设计有关,自动移位)))。
lcd液晶地址的计算:
需要注意的是,HADDR[27:26]的设置,我们是不用干预的,例如当我们选择Bank 的第 2 区,对应的就是 FSMC_NE2 连接外部设备,也就是对应了HADDR[27:26]=01,连接好后,我们需要做的就是配置第 2 区的寄存器组,来适应外部设备。
地址已经选好了,接下来就是读写的问题了,这其中,涉及到一个很重要的点,就是时序。对于 NOR FLASH 控制器,主要是通过 FSMC_BCRx、FSMC_BTRx 和FSMC_BWTTx 寄存器设置(其中 x=1~4,对应 4 个区)。通过这 3 个寄存器,可以设置 FSMC 访问外部存储器的时序参数,也就是说在硬件允许的范围内,可以自己对读写速度进行配置。
FSMC 的 NOR FLASH 控制器分为异步模式和同步突发模式,异步模式分为普通模式 1 和 2,还有在两个普通模式下的 4 种扩展模式(A、B、C、D)。FSMC 主要设置了 3 个时间参数:地址建立时间(ADDSET)、数据建立时间(DATAST)和地址保存时间(ADDHLD)。当我们选用异步模式的不同时序模型时,须设置不同的时序参数。
外部 SRAM 芯片与 STM32 相连的引脚非常多,主要是地址线和数据线及控制线。
根据本硬件设计,SRAM 芯片的使能信号与 FSMC_NE4 连接,所以它会被映射到 STM32 中的BANK1 NOR/SRAM 4 区域,该区域的地址范围为 0x6C000000-0x6FFFFFFF,因此,当内核访问从基地址 0x6C000000 开始的 1MB 空间时,FSMC 外设会自动控制原理图中的引脚产生访问时序,访问这个外部 SRAM 存储器。
三、STM32CubeIDE
使用stm32官方开发工具进行测试,配置sram的引脚参数。可参考以前的文章<CubeMX系列教程——23 外部SRAM>。
程序设计步骤:
①使能 FSMC 时钟,并配置 FSMC 相关的 IO 及其时钟使能
要使用 FSMC,当然首先得开启其时钟。然后需要把 FSMC_D0~15,FSMCA0~18 等相关IO 口,全部配置为复用输出,并使能各 IO 组的时钟。
②设置 FSMC BANK1 区域 4 的相关寄存器。
此部分包括设置区域 4 的存储器的工作模式、位宽和读写时序等。使用模式 A、16 位宽,读写共用一个时序寄存器。
③使能 BANK1 区域 4。
最后,需要通过 FSMC_BCR 寄存器使能 BANK1 的区域 4,使 FSMC 工作起来。通过以上几个步骤,我们就完成了 FSMC 的配置,初始化 FSMC 后就可以访问 SRAM 芯片进行读写操作了,这里还需要注意,因为我们使用的是 BANK1 的区域 4,所以HADDR[27:26]=11,故外部内存的首地址为 0X6C000000。
直接使用cubeMX配置生成工程,模式A,读写采用同一时序。
工程中添加测试代码,如下:
#define Bank1_SRAM4_ADDR ((uint32_t)(0x6C000000))
#define IS62WV51216_SIZE 0x100000 //512*16/2bits = 0x100000
uint8_t SRAM_Test(void)
{
uint32_t counter=0;
uint8_t ubWritedata_8b = 0, ubReaddata_8b = 0;
uint16_t uhWritedata_16b = 0, uhReaddata_16b = 0;
//8位数据读写测试
for (counter = 0x00; counter < IS62WV51216_SIZE; counter++)
{
*(__IO uint8_t*) (Bank1_SRAM4_ADDR + counter) = (uint8_t)0x0;
}
for (counter = 0; counter < IS62WV51216_SIZE; counter++)
{
*(__IO uint8_t*) (Bank1_SRAM4_ADDR + counter) = (uint8_t)(ubWritedata_8b + counter);
}
for(counter = 0; counter<IS62WV51216_SIZE;counter++ )
{
ubReaddata_8b = *(__IO uint8_t*)(Bank1_SRAM4_ADDR + counter);
if(ubReaddata_8b != (uint8_t)(ubWritedata_8b + counter))
{
SRAM_ERROR('8λÊý¾Ý¶Áд´íÎó£¡');
return 0;
}
}
//16位数据读写测试
for (counter = 0x00; counter < IS62WV51216_SIZE/2; counter++)
{
*(__IO uint16_t*) (Bank1_SRAM4_ADDR + 2*counter) = (uint16_t)0x00;
}
for (counter = 0; counter < IS62WV51216_SIZE/2; counter++)
{
*(__IO uint16_t*) (Bank1_SRAM4_ADDR + 2*counter) = (uint16_t)(uhWritedata_16b + counter);
}
for(counter = 0; counter<IS62WV51216_SIZE/2;counter++ )
{
uhReaddata_16b = *(__IO uint16_t*)(Bank1_SRAM4_ADDR + 2*counter);
if(uhReaddata_16b != (uint16_t)(uhWritedata_16b + counter))
{
return 0;
}
}
return 1;
}
四、测试结果
使用STM32CubeIDE官方IDE开发,在线仿真,查看memory中的信息,如下:
符合预期,说明正常对sram进行了读和写。
补充:
正点原子电路设计进行了部分引脚进行了交换。
设计时结合手册,参考现成电路原理图。
联系客服