话说stm32f10x-FSMC的配置与频率
2013-08-28 10:56 居安 阅读(5321) 评论(0) 编辑 收藏 举报1.存储器,从例子说起
存储器读写,cpu与芯片同步等等都需要参考设备的读写时序,并通过参考cpu系统时钟,给出合理的读写周期。
这里以stm32f103zeT6读写外部CSRAM为例子加以说明。
选用用的CSRAM芯片的读写模式为同步非复用,频率为36MHz,芯片挂在cpu的FSMC的BANK1 SRAM4区,其同步非复用
模式就不多讲,具体参考《STM32F103ZET6》p51~p52。至于这个36MHz则需要进行对FSMC的读写时序进行控制。如何
控制呢?网上很多资料在这里都没有详细的说明,估计是很多网友觉得这个比较容易吧。但是当时我真是被这个问题
给搞的半死不活。后来沉下心来悉心研究了一段时间,终于知道是怎么配置这个36MHz了。
首先需要明确的是,stm32f10x固件库提供了简便的FSMC配置过程,我们可以利用一个结构体就进行配置,而不用
对具体的寄存器进行一位一位的填写。具体的配置如下:
FSMC_NORSRAMInitTypeDef FSMC_NORSRAMInitStructure;
FSMC_NORSRAMTimingInitTypeDef FSMC_NORSRAMTimingInitStructure;
//
FSMC_NORSRAMTimingInitStructure.FSMC_AddressSetupTime = 1;
FSMC_NORSRAMTimingInitStructure.FSMC_AddressHoldTime = 0;
FSMC_NORSRAMTimingInitStructure.FSMC_DataSetupTime = 2;
FSMC_NORSRAMTimingInitStructure.FSMC_BusTurnAroundDuration = 0; //总线恢复时间-19:16
/*系统选用PLL作为时钟输出源,而PLL频率为72MHz,CRAM读写频率为36MHz,所以采用2分频*/
FSMC_NORSRAMTimingInitStructure.FSMC_CLKDivision = 1; //bit-23:20,分频比为1,则存储器读写周期为 1/2 SYSCLK
FSMC_NORSRAMTimingInitStructure.FSMC_DataLatency = 0; //bit27:24,(数据保持时间)对于CRAM这个参数必须为0
FSMC_NORSRAMTimingInitStructure.FSMC_AccessMode = FSMC_AccessMode_A; //访问模式-只对FSMC_BCR1中EXTMOD位为1时起作用
//以下是配置FSMC_BCR1寄存器的各个位
FSMC_NORSRAMInitStructure.FSMC_Bank = FSMC_Bank1_NORSRAM4;
FSMC_NORSRAMInitStructure.FSMC_DataAddressMux = FSMC_DataAddressMux_Disable; //非复用MUXEN:bit1
FSMC_NORSRAMInitStructure.FSMC_MemoryType = FSMC_MemoryType_PSRAM; //MTYP-bit3:2存储器类型
FSMC_NORSRAMInitStructure.FSMC_MemoryDataWidth = FSMC_MemoryDataWidth_16b; //存储器数据总线宽度-bit5:4
FSMC_NORSRAMInitStructure.FSMC_BurstAccessMode = FSMC_BurstAccessMode_Disable;//BURSTEN-bit8 成组模式使能
FSMC_NORSRAMInitStructure.FSMC_AsynchronousWait = FSMC_AsynchronousWait_Disable; //bit15这一位手册里面保留...
FSMC_NORSRAMInitStructure.FSMC_WaitSignalPolarity = FSMC_WaitSignalPolarity_Low; //WAITPOL-bit9-等待信号极性
FSMC_NORSRAMInitStructure.FSMC_WrapMode = FSMC_WrapMode_Disable; //WRAPMOD-bit10是否支持费对其成组模式
FSMC_NORSRAMInitStructure.FSMC_WaitSignalActive = FSMC_WaitSignalActive_BeforeWaitState; //WAITCFG-bit11
FSMC_NORSRAMInitStructure.FSMC_WriteOperation = FSMC_WriteOperation_Enable; //WREN-bit12
FSMC_NORSRAMInitStructure.FSMC_WaitSignal = FSMC_WaitSignal_Disable; //WAITEN-bit13-等待使能
FSMC_NORSRAMInitStructure.FSMC_ExtendedMode = FSMC_ExtendedMode_Disable; //EXTMOD-bit14 读写时序不一致时设置
FSMC_NORSRAMInitStructure.FSMC_WriteBurst = FSMC_WriteBurst_Enable; //同步写-CBURSTRW(bit19)
FSMC_NORSRAMInitStructure.FSMC_ReadWriteTimingStruct = &FSMC_NORSRAMTimingInitStructure;
FSMC_NORSRAMInitStructure.FSMC_WriteTimingStruct = &FSMC_NORSRAMTimingInitStructure;
FSMC_NORSRAMInit(&FSMC_NORSRAMInitStructure);
/* Enable FSMC Bank1_SRAM4 Bank */
//根据PCB原理图 CSRAM的片选信号ARM_325T_CS与PG12连接,而PG12则是FSMC_NE4
FSMC_NORSRAMCmd(FSMC_Bank1_NORSRAM4, ENABLE);
上面的配置大部分都给出了明确的解释,有些解释比较书面化,如不能理解透彻还是参照《STM32F10XXX参考手册》18章具体的
寄存器说明进行查阅。
这里只重点讲下,时钟配置,FSMC_NORSRAMTimingInitStructure.FSMC_CLKDivision = 1;这条语句,为什么配置为1?首先知
道这条命令的含义。FSMC_CLKDivision表示分频比,而这个分频的参考是SYSCLK,而我的初始化程序中将系统时钟设置为72MHZ。
而这里CRAM读写频率是36MHZ,所以要进行二分频,根据手册,二分频则需要将FSMC_BTRx寄存器的CLKDIV(bit23~bit20)位配置为
1,即FSMC_NORSRAMTimingInitStructure.FSMC_CLKDivision = 1;这样就ok了~
2.时钟,从启动程序说起
另外要说的是,我的开发工具是keil-uVersion4+rt-thread,这个非常好用,boot程序都已经写好了的。查看其启动程序,发现中
断向量表的第二个向量放的是复位中断,片段如下:
__Vectors DCD __initial_sp ; Top of Stack
DCD Reset_Handler ; Reset Handler //复位中断
系统一旦复位便进入复位中断,并调用复位中断处理程序,处理如下:
Reset_Handler PROC
EXPORT Reset_Handler [WEAK]
IMPORT __main
IMPORT SystemInit
LDR R0, =SystemInit
BLX R0
LDR R0, =__main
BX R0
ENDP
我们可以看到,复位中断处理首先调用的是SystemIint程序,再调用c库函数_main,SystemInit也就是初始化我们的板子的运行环境,
包括时钟,SRAM,FLASH等等,主要是时钟这一块。这个函数对HSE,HSI,PLL,以及系统时钟进行配置。
这里只列出关于PLL和系统时钟的配置
/*
硬件电路中HSE给的是12MHz(其实默认是8MHz,在stm32f10x中其取值范围为4~16MHz,具体参考《STM32F103ZET6中文》p42)
*/
RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_PLLSRC | RCC_CFGR_PLLXTPRE |
RCC_CFGR_PLLMULL));
//PLL 时钟配置: PLLCLK = HSE * 6 = 72 MHz
RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_HSE | RCC_CFGR_PLLMULL6);
系统复位后,HSI被选为系统时钟(HSI),而我们这里要选择PLL作为SYSCLK的时钟源,代码如下:
/* Select PLL as system clock source */
RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));
RCC->CFGR |= (uint32_t)RCC_CFGR_SW_PLL;
这样系统时钟就是72MHz。