stm32f429FMC外设学习

功能框图

这是一种型号为 W9825G6KH 的 SDRAM 芯片内部结构框图,以它为模型进行学习
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

CLK -- FMC_SDCLK  //同步时钟信号
CKE -- FMC_SDCKE[1:0]    //SDCKE0: SDRAM 存储区域 1 时钟使能,;SDCKE1: SDRAM 存储区域 2 时钟使能.这里表示的是单片机的存储区域
CS  -- FMC_SDNE[1:0]     //SDCKE0: SDRAM 存储区域 1 时钟使能; SDCKE1: SDRAM 存储区域 2 时钟使能
CAS -- FMC_NCAS    //列地址选通信号
RAS -- FMC_NRAS    //行地址选通信号
WE  -- FMC_SDNWE   //写入使能
DQM[0:1] -- FMC_NBL[0:3]  //数据掩码信号
BA[1:0]  -- FMC_A[15:14]  //Bank 地址线
A[12:0]  -- FMC_A[12:0]  //行/列地址线
DQ[0:15] -- FMC_D[0:31] //数据线

地址控制

SDRAM 包含有“A”以及“BA”两类地址线, A 类地址线是行(Row)与列(Column)共用的地址总线, BA 地址线是独立的用于指定 SDRAM 内部存储阵列号(Bank)。在命令模式下, A 类地址线还用于某些命令输入参数。
在这里插入图片描述
通讯时当 RAS 线为低电平, 则“行地址选通器”被选通,地址线 A[12:0]表示的地址会被输入到“行地址译码及锁存器”中,作为存储阵列中选定的行地址,同时地址线 BA[1:0]表示的 Bank 也被锁存,选中了要操作的 Bank 号;接着控制 CAS 线为低电平,“列地址选通器”被选通,地址线 A[11:0]表示的地址会被锁存到“列地址译码器”中作为列地址,完成寻址过程。

数据输入输出

若是写 SDRAM 内容,寻址完成后, DQ[15:0]线表示的数据进入输入数据寄存器,然后传输到存储器阵列中,数据被保存;数据输出过程相反。数据输入输出时,还会使用 DQM[1:0]线来配合,每根 DQM 线对应 8 位数据,如“DQM0(LDQM)”为低电平, “DQM1(HDQM)” 为高电平时,数据线 DQ[7:0]表示的数据有效,而 DQ[15:8]表示的数据无效。

行有效

进行存储单元寻址时,需要先选中要访问的 Bank 和行,使它处于激活状态。该操作通过“行有效” (ACTIVE)命令实现。发送行有效命令时, RAS 线为低电平,同时通过 BA 线以及 A 线发送 Bank 地址和行地址。
行有效命令时序图

列读写

行地址通过“行有效”命令确定后,就要对列地址进行寻址了。“读命令” (READ)和“写命令” (WRITE)的时序很相似,见图 26-6,通过共用的地址线 A 发送列地址,同时使用 WE 引脚表示读/写方向, WE 为低电平时表示写,高电平时表示读。数据读写时,使用DQM 线表示有效的 DQ 数据线
读取命令时序
本型号的 SDRAM 芯片表示列地址时仅使用 A[8:0]线,而 A10 线用于控制是否“自动预充电”,该线为高电平时使能,低电平时关闭

SDRAM的初始化流程

在这里插入图片描述
在这里插入图片描述

SDRAM的读写流程

CL=2 时,带 AUTO PRECHARGE 的读时序
在这里插入图片描述
读时序和写时序的命令过程很类似,下面我们统一解说:
在这里插入图片描述

FMC简介

在这里插入图片描述在这里插入图片描述
在这里插入图片描述
其中比较特殊的是 FMC_A[15:14]引脚用作 Bank 的寻址线; 而 FMC_SDCKE 线和FMC_SDNE 都各有 2 条, FMC_SDCKE 用于控制 SDRAM 的时钟使能, FMC_SDNE 用于控制 SDRAM 芯片的片选使能。它们用于控制 STM32 使用不同的存储区域驱动 SDRAM,使用编号为 0 的信号线组会使用 STM32 的存储器区域 1,使用编号为 1 的信号线组会使用存储器区域 2。 使用不同存储区域时, STM32 访问 SDRAM 的地址不一样.

时钟控制逻辑

FMC 外设挂载在 AHB3 总线上,时钟信号来自于 HCLK(默认 180MHz),控制器的时钟输出就是由它分频得到。如 SDRAM 控制器的 FMC_SDCLK 引脚输出的时钟,是用于与SDRAM 芯片进行同步通讯,它的时钟频率可通过 FMC_SDCR1 寄存器的 SDCLK 位配置,可以配置为 HCLK 的 1/2 或 1/3,也就是说,与 SDRAM 通讯的同步时钟最高频率为90MHz。
在这里插入图片描述

SDRAM的存储区域

FMC 把 SDRAM 的存储区域分成了 Bank1 和 Bank2 两块,这里的 Bank 与 SDRAM 芯片内部的 Bank 是不一样的概念,只是 FMC 的地址区域划分而已。每个 Bank 有不一样的起始地址,且有独立的 FMC_SDCR 控制寄存器和 FMC_SDTR 时序寄存器,还有独立的FMC_SDCKE 时钟使能信号线和 FMC_SDCLK 信号线。 FMC_SDCKE0 和 FMC_SDCLK0对应的存储区域 1 的地址范围是 0xC000 0000-0xCFFF FFFF,而 FMC_SDCKE1 和FMC_SDCLK1 对应的存储区域 2 的地址范围是 0xD000 0000- 0xDFFF FFFF。 当程序里控制内核访问这些地址的存储空间时, FMC 外设会即会产生对应的时序,对它外接的SDRAM 芯片进行读写

SDRAM 时序结构体

 /* @brief 控制 SDRAM 的时序参数,这些参数的单位都是“周期”
 * 各个参数的值可设置为 1-16 个周期。 */
 typedef struct
 {
 uint32_t LoadToActiveDelay; /*TMRD:加载模式寄存器命令后的延迟*/
 uint32_t ExitSelfRefreshDelay; /*TXSR:自刷新命令后的延迟 */
 uint32_t SelfRefreshTime; /*TRAS:自刷新时间*/
 uint32_t RowCycleDelay; /*TRC:行循环延迟*/
 uint32_t WriteRecoveryTime; /*TWR:恢复延迟 */
 uint32_t RPDelay; /*TRP:行预充电延迟*/
 uint32_t RCDDelay; /*TRCD:行到列延迟*/
 } FMC_SDRAM_TimingTypeDef;

这个结构体成员定义的都是 SDRAM 发送各种命令后必须的延迟,它的配置对应到FMC_SDTR 中的寄存器位。所有成员参数值的单位是周期,参数值大小都可设置成“1-16”。

SDRAM 初始化结构体

 typedef struct
 {
 uint32_t Bank; /*选择 FMC 的 SDRAM 存储区域*/
 uint32_t ColumnBitsNumber; /*定义 SDRAM 的列地址宽度 */
 uint32_t RowBitsNumber; /*定义 SDRAM 的行地址宽度 */
 uint32_t MemoryDataWidth; /*定义 SDRAM 的数据宽度 */
 uint32_t InternalBankNumber; /*定义 SDRAM 内部的 Bank 数目 */
 uint32_t CASLatency; /*定义 CASLatency 的时钟个数*/
 uint32_t WriteProtection; /*定义是否使能写保护模式 */
 uint32_t SDClockPeriod; /*配置同步时钟 SDCLK 的参数*/
 uint32_t ReadBurst; /*是否使能突发读模式*/
 uint32_t ReadPipeDelay; /*定义在 CAS 个延迟后再等待多少个 HCLK 时钟才读取数据 */
 } FMC_SDRAM_InitTypeDef;

SDRAM 命令结构体

 typedef struct
 {
 uint32_t CommandMode; /*要发送的命令 */
 uint32_t CommandTarget; /*目标存储器区域 */
 uint32_t AutoRefreshNumber; /*若发送的是自动刷新命令,此处为发送的刷新次数,其它命令时无效 */
 uint32_t ModeRegisterDefinition; /*若发送的是加载模式寄存器命令,此处为要写入 SDRAM 模式寄存器的参数 */
 } FMC_SDRAM_CommandTypeDef;

在这里插入图片描述

FSMC_A0 -- PF0
FSMC_A1 -- PF1
FSMC_A2 -- PF2
FSMC_A3 -- PF3
FSMC_A4 -- PF4
FSMC_A5 -- PF5
FSMC_A6 -- PF12
FSMC_A7 -- PF13
FSMC_A8 -- PF14
FSMC_A9 -- PF15
FSMC_A10 -- PG0
FSMC_A11 -- PG1
FSMC_A12 -- PG2
FSMC_BA0 -- PG4
FSMC_BA1 -- PG5
FSMC_D0  -- PD14
FSMC_D1  -- PD15
FSMC_D2  -- PD0
FSMC_D3  -- PD1
FSMC_D4  -- PE7
FSMC_D5  -- PE8
FSMC_D6  -- PE9
FSMC_D7  -- PE10
FSMC_D8  -- PE11
FSMC_D9  -- PE12
FSMC_D10 -- PE13
FSMC_D11 -- PE14
FSMC_D12 -- PE15
FSMC_D13 -- PD8
FSMC_D14 -- PD9
FSMC_D15 -- PD10
FSMC_SDCKE0 -- PC3
FSMC_SDCLK  -- PG8
FSMC_NBL0   -- PE0
FSMC_NBL1   -- PE1
FSMC_SDNCAS -- PG15
FSMC_SDNRAS -- PF11
FSMC_SDNWE  -- PC0
FSMC_SDNE0  -- PC2

```c
#ifndef __SDRAM_H
#define	__SDRAM_H

#include "stm32f4xx.h"
#include <stdio.h>



#define IS42S16400J_SIZE     (32 * 1024 * 1024)    //,32M字节


/*SDRAM 的bank选择*/  
#define FMC_BANK_SDRAM            FMC_Bank1_SDRAM  
#define FMC_COMMAND_TARGET_BANK   FMC_SDRAM_CMD_TARGET_BANK1

/**
  * @brief  FMC SDRAM 数据基地址
  */   
#define SDRAM_BANK_ADDR     ((uint32_t)0xC0000000)
  
/**
  * @brief  FMC SDRAM 数据宽度
  */  
/* #define SDRAM_MEMORY_WIDTH   FMC_SDMemory_Width_8b  */
#define SDRAM_MEMORY_WIDTH    FMC_SDRAM_MEM_BUS_WIDTH_16 

/**
  * @brief  FMC SDRAM CAS Latency
  */  
/* #define SDRAM_CAS_LATENCY   FMC_CAS_Latency_2  */
#define SDRAM_CAS_LATENCY    FMC_SDRAM_CAS_LATENCY_3

/**
  * @brief  FMC SDRAM SDCLK时钟分频因子
  */  
#define SDCLOCK_PERIOD    FMC_SDRAM_CLOCK_PERIOD_2        /* Default configuration used with LCD */
/* #define SDCLOCK_PERIOD    FMC_SDClock_Period_3 */

/**
  * @brief  FMC SDRAM 突发读取特性
  */  
#define SDRAM_READBURST    FMC_SDRAM_RBURST_DISABLE    /* Default configuration used with LCD */
/* #define SDRAM_READBURST    FMC_Read_Burst_Enable  */

/**
  * @brief  FMC SDRAM Bank Remap
  */    
/* #define SDRAM_BANK_REMAP */   

#define SDRAM_TIMEOUT                    ((uint32_t)0xFFFF)



/**
  * @brief  FMC SDRAM 模式配置的寄存器相关定义
  */
#define SDRAM_MODEREG_BURST_LENGTH_1             ((uint16_t)0x0000)
#define SDRAM_MODEREG_BURST_LENGTH_2             ((uint16_t)0x0001)
#define SDRAM_MODEREG_BURST_LENGTH_4             ((uint16_t)0x0002)
#define SDRAM_MODEREG_BURST_LENGTH_8             ((uint16_t)0x0004)
#define SDRAM_MODEREG_BURST_TYPE_SEQUENTIAL      ((uint16_t)0x0000)
#define SDRAM_MODEREG_BURST_TYPE_INTERLEAVED     ((uint16_t)0x0008)
#define SDRAM_MODEREG_CAS_LATENCY_2              ((uint16_t)0x0020)
#define SDRAM_MODEREG_CAS_LATENCY_3              ((uint16_t)0x0030)
#define SDRAM_MODEREG_OPERATING_MODE_STANDARD    ((uint16_t)0x0000)
#define SDRAM_MODEREG_WRITEBURST_MODE_PROGRAMMED ((uint16_t)0x0000) 
#define SDRAM_MODEREG_WRITEBURST_MODE_SINGLE     ((uint16_t)0x0200)      


/*信息输出*/
#define SDRAM_DEBUG_ON         1

#define SDRAM_INFO(fmt,arg...)           printf("<<-SDRAM-INFO->> "fmt"\n",##arg)
#define SDRAM_ERROR(fmt,arg...)          printf("<<-SDRAM-ERROR->> "fmt"\n",##arg)
#define SDRAM_DEBUG(fmt,arg...)          do{\
                                          if(SDRAM_DEBUG_ON)\
                                          printf("<<-SDRAM-DEBUG->> [%d]"fmt"\n",__LINE__, ##arg);\
                                          }while(0)
/**
  * @}
  */  
 
/*地址信号线*/  
#define FMC_A0_GPIO_PORT        GPIOF
#define FMC_A0_GPIO_CLK         __HAL_RCC_GPIOF_CLK_ENABLE()
#define FMC_A0_GPIO_PIN         GPIO_PIN_0
#define FMC_A0_PINSOURCE        GPIO_PinSource0
#define FMC_A0_AF               GPIO_AF_FMC

#define FMC_A1_GPIO_PORT        GPIOF
#define FMC_A1_GPIO_CLK         __HAL_RCC_GPIOF_CLK_ENABLE()
#define FMC_A1_GPIO_PIN         GPIO_PIN_1
#define FMC_A1_PINSOURCE        GPIO_PinSource1
#define FMC_A1_AF               GPIO_AF_FMC

#define FMC_A2_GPIO_PORT        GPIOF
#define FMC_A2_GPIO_CLK         __HAL_RCC_GPIOF_CLK_ENABLE()
#define FMC_A2_GPIO_PIN         GPIO_PIN_2
#define FMC_A2_PINSOURCE        GPIO_PinSource2
#define FMC_A2_AF               GPIO_AF_FMC

#define FMC_A3_GPIO_PORT        GPIOF
#define FMC_A3_GPIO_CLK         __HAL_RCC_GPIOF_CLK_ENABLE()
#define FMC_A3_GPIO_PIN         GPIO_PIN_3
#define FMC_A3_PINSOURCE        GPIO_PinSource3
#define FMC_A3_AF               GPIO_AF_FMC

#define FMC_A4_GPIO_PORT        GPIOF
#define FMC_A4_GPIO_CLK         __HAL_RCC_GPIOF_CLK_ENABLE()
#define FMC_A4_GPIO_PIN         GPIO_PIN_4
#define FMC_A4_PINSOURCE        GPIO_PinSource4
#define FMC_A4_AF               GPIO_AF_FMC

#define FMC_A5_GPIO_PORT        GPIOF
#define FMC_A5_GPIO_CLK         __HAL_RCC_GPIOF_CLK_ENABLE()
#define FMC_A5_GPIO_PIN         GPIO_PIN_5
#define FMC_A5_PINSOURCE        GPIO_PinSource5
#define FMC_A5_AF               GPIO_AF_FMC

#define FMC_A6_GPIO_PORT        GPIOF
#define FMC_A6_GPIO_CLK         __HAL_RCC_GPIOF_CLK_ENABLE()
#define FMC_A6_GPIO_PIN         GPIO_PIN_12
#define FMC_A6_PINSOURCE        GPIO_PinSource12
#define FMC_A6_AF               GPIO_AF_FMC

#define FMC_A7_GPIO_PORT        GPIOF
#define FMC_A7_GPIO_CLK         __HAL_RCC_GPIOF_CLK_ENABLE()
#define FMC_A7_GPIO_PIN         GPIO_PIN_13
#define FMC_A7_PINSOURCE        GPIO_PinSource13
#define FMC_A7_AF               GPIO_AF_FMC

#define FMC_A8_GPIO_PORT        GPIOF
#define FMC_A8_GPIO_CLK         __HAL_RCC_GPIOF_CLK_ENABLE()
#define FMC_A8_GPIO_PIN         GPIO_PIN_14
#define FMC_A8_PINSOURCE        GPIO_PinSource14
#define FMC_A8_AF               GPIO_AF_FMC

#define FMC_A9_GPIO_PORT        GPIOF
#define FMC_A9_GPIO_CLK         __HAL_RCC_GPIOF_CLK_ENABLE()
#define FMC_A9_GPIO_PIN         GPIO_PIN_15
#define FMC_A9_PINSOURCE        GPIO_PinSource15
#define FMC_A9_AF               GPIO_AF_FMC


#define FMC_A10_GPIO_PORT        GPIOG
#define FMC_A10_GPIO_CLK         __HAL_RCC_GPIOG_CLK_ENABLE()
#define FMC_A10_GPIO_PIN         GPIO_PIN_0
#define FMC_A10_PINSOURCE        GPIO_PinSource0
#define FMC_A10_AF               GPIO_AF_FMC


#define FMC_A11_GPIO_PORT        GPIOG
#define FMC_A11_GPIO_CLK         __HAL_RCC_GPIOG_CLK_ENABLE()
#define FMC_A11_GPIO_PIN         GPIO_PIN_1
#define FMC_A11_PINSOURCE        GPIO_PinSource1
#define FMC_A11_AF               GPIO_AF_FMC

#define FMC_A12_GPIO_PORT        GPIOG
#define FMC_A12_GPIO_CLK         __HAL_RCC_GPIOG_CLK_ENABLE()
#define FMC_A12_GPIO_PIN         GPIO_PIN_2
#define FMC_A12_PINSOURCE        GPIO_PinSource1
#define FMC_A12_AF               GPIO_AF_FMC

/*数据信号线*/
#define FMC_D0_GPIO_PORT        GPIOD
#define FMC_D0_GPIO_CLK         __HAL_RCC_GPIOD_CLK_ENABLE()
#define FMC_D0_GPIO_PIN         GPIO_PIN_14
#define FMC_D0_PINSOURCE        GPIO_PinSource14
#define FMC_D0_AF               GPIO_AF_FMC

#define FMC_D1_GPIO_PORT        GPIOD
#define FMC_D1_GPIO_CLK         __HAL_RCC_GPIOD_CLK_ENABLE()
#define FMC_D1_GPIO_PIN         GPIO_PIN_15
#define FMC_D1_PINSOURCE        GPIO_PinSource15
#define FMC_D1_AF               GPIO_AF_FMC

#define FMC_D2_GPIO_PORT        GPIOD
#define FMC_D2_GPIO_CLK         __HAL_RCC_GPIOD_CLK_ENABLE()
#define FMC_D2_GPIO_PIN         GPIO_PIN_0
#define FMC_D2_PINSOURCE        GPIO_PinSource0
#define FMC_D2_AF               GPIO_AF_FMC

#define FMC_D3_GPIO_PORT        GPIOD
#define FMC_D3_GPIO_CLK         __HAL_RCC_GPIOD_CLK_ENABLE()
#define FMC_D3_GPIO_PIN         GPIO_PIN_1
#define FMC_D3_PINSOURCE        GPIO_PinSource1
#define FMC_D3_AF               GPIO_AF_FMC

#define FMC_D4_GPIO_PORT        GPIOE
#define FMC_D4_GPIO_CLK         __HAL_RCC_GPIOE_CLK_ENABLE()
#define FMC_D4_GPIO_PIN         GPIO_PIN_7
#define FMC_D4_PINSOURCE        GPIO_PinSource7
#define FMC_D4_AF               GPIO_AF_FMC

#define FMC_D5_GPIO_PORT        GPIOE
#define FMC_D5_GPIO_CLK         __HAL_RCC_GPIOE_CLK_ENABLE()
#define FMC_D5_GPIO_PIN         GPIO_PIN_8
#define FMC_D5_PINSOURCE        GPIO_PinSource8
#define FMC_D5_AF               GPIO_AF_FMC

#define FMC_D6_GPIO_PORT        GPIOE
#define FMC_D6_GPIO_CLK         __HAL_RCC_GPIOE_CLK_ENABLE()
#define FMC_D6_GPIO_PIN         GPIO_PIN_9
#define FMC_D6_PINSOURCE        GPIO_PinSource9
#define FMC_D6_AF               GPIO_AF_FMC

#define FMC_D7_GPIO_PORT        GPIOE
#define FMC_D7_GPIO_CLK         __HAL_RCC_GPIOE_CLK_ENABLE()
#define FMC_D7_GPIO_PIN         GPIO_PIN_10
#define FMC_D7_PINSOURCE        GPIO_PinSource10
#define FMC_D7_AF               GPIO_AF_FMC

#define FMC_D8_GPIO_PORT        GPIOE
#define FMC_D8_GPIO_CLK         __HAL_RCC_GPIOE_CLK_ENABLE()
#define FMC_D8_GPIO_PIN         GPIO_PIN_11
#define FMC_D8_PINSOURCE        GPIO_PinSource11
#define FMC_D8_AF               GPIO_AF_FMC

#define FMC_D9_GPIO_PORT        GPIOE
#define FMC_D9_GPIO_CLK         __HAL_RCC_GPIOE_CLK_ENABLE()
#define FMC_D9_GPIO_PIN         GPIO_PIN_12
#define FMC_D9_PINSOURCE        GPIO_PinSource12
#define FMC_D9_AF               GPIO_AF_FMC

#define FMC_D10_GPIO_PORT        GPIOE
#define FMC_D10_GPIO_CLK         __HAL_RCC_GPIOE_CLK_ENABLE()
#define FMC_D10_GPIO_PIN         GPIO_PIN_13
#define FMC_D10_PINSOURCE        GPIO_PinSource13
#define FMC_D10_AF               GPIO_AF_FMC

#define FMC_D11_GPIO_PORT        GPIOE
#define FMC_D11_GPIO_CLK         __HAL_RCC_GPIOE_CLK_ENABLE()
#define FMC_D11_GPIO_PIN         GPIO_PIN_14
#define FMC_D11_PINSOURCE        GPIO_PinSource14
#define FMC_D11_AF               GPIO_AF_FMC

#define FMC_D12_GPIO_PORT        GPIOE
#define FMC_D12_GPIO_CLK         __HAL_RCC_GPIOE_CLK_ENABLE()
#define FMC_D12_GPIO_PIN         GPIO_PIN_15
#define FMC_D12_PINSOURCE        GPIO_PinSource15
#define FMC_D12_AF               GPIO_AF_FMC

#define FMC_D13_GPIO_PORT        GPIOD
#define FMC_D13_GPIO_CLK         __HAL_RCC_GPIOD_CLK_ENABLE()
#define FMC_D13_GPIO_PIN         GPIO_PIN_8
#define FMC_D13_PINSOURCE        GPIO_PinSource8
#define FMC_D13_AF               GPIO_AF_FMC

#define FMC_D14_GPIO_PORT        GPIOD
#define FMC_D14_GPIO_CLK         __HAL_RCC_GPIOD_CLK_ENABLE()
#define FMC_D14_GPIO_PIN         GPIO_PIN_9
#define FMC_D14_PINSOURCE        GPIO_PinSource9
#define FMC_D14_AF               GPIO_AF_FMC

#define FMC_D15_GPIO_PORT        GPIOD
#define FMC_D15_GPIO_CLK         __HAL_RCC_GPIOD_CLK_ENABLE()
#define FMC_D15_GPIO_PIN         GPIO_PIN_10
#define FMC_D15_PINSOURCE        GPIO_PinSource10
#define FMC_D15_AF               GPIO_AF_FMC


/*控制信号线*/  
#define FMC_CS_GPIO_PORT        GPIOC
#define FMC_CS_GPIO_CLK         __HAL_RCC_GPIOC_CLK_ENABLE()
#define FMC_CS_GPIO_PIN         GPIO_PIN_2
#define FMC_CS_PINSOURCE        GPIO_PinSource2
#define FMC_CS_AF               GPIO_AF_FMC

#define FMC_BA0_GPIO_PORT        GPIOG
#define FMC_BA0_GPIO_CLK         __HAL_RCC_GPIOG_CLK_ENABLE()
#define FMC_BA0_GPIO_PIN         GPIO_PIN_4
#define FMC_BA0_PINSOURCE        GPIO_PinSource4
#define FMC_BA0_AF               GPIO_AF_FMC

#define FMC_BA1_GPIO_PORT        GPIOG
#define FMC_BA1_GPIO_CLK         __HAL_RCC_GPIOG_CLK_ENABLE()
#define FMC_BA1_GPIO_PIN         GPIO_PIN_5
#define FMC_BA1_PINSOURCE        GPIO_PinSource5
#define FMC_BA1_AF               GPIO_AF_FMC

#define FMC_WE_GPIO_PORT        GPIOC
#define FMC_WE_GPIO_CLK         __HAL_RCC_GPIOC_CLK_ENABLE()
#define FMC_WE_GPIO_PIN         GPIO_PIN_0
#define FMC_WE_PINSOURCE        GPIO_PinSource0
#define FMC_WE_AF               GPIO_AF_FMC

#define FMC_RAS_GPIO_PORT        GPIOF
#define FMC_RAS_GPIO_CLK         __HAL_RCC_GPIOF_CLK_ENABLE()
#define FMC_RAS_GPIO_PIN         GPIO_PIN_11
#define FMC_RAS_PINSOURCE        GPIO_PinSource11
#define FMC_RAS_AF               GPIO_AF_FMC

#define FMC_CAS_GPIO_PORT        GPIOG
#define FMC_CAS_GPIO_CLK         __HAL_RCC_GPIOG_CLK_ENABLE()
#define FMC_CAS_GPIO_PIN         GPIO_PIN_15
#define FMC_CAS_PINSOURCE        GPIO_PinSource15
#define FMC_CAS_AF               GPIO_AF_FMC

#define FMC_CLK_GPIO_PORT        GPIOG
#define FMC_CLK_GPIO_CLK         __HAL_RCC_GPIOG_CLK_ENABLE()
#define FMC_CLK_GPIO_PIN         GPIO_PIN_8
#define FMC_CLK_PINSOURCE        GPIO_PinSource8
#define FMC_CLK_AF               GPIO_AF_FMC

#define FMC_CKE_GPIO_PORT        GPIOC
#define FMC_CKE_GPIO_CLK         __HAL_RCC_GPIOC_CLK_ENABLE()
#define FMC_CKE_GPIO_PIN         GPIO_PIN_3
#define FMC_CKE_PINSOURCE        GPIO_PinSource3
#define FMC_CKE_AF               GPIO_AF_FMC

/*UDQM LDQM*/
#define FMC_UDQM_GPIO_PORT        GPIOE
#define FMC_UDQM_GPIO_CLK         __HAL_RCC_GPIOE_CLK_ENABLE()
#define FMC_UDQM_GPIO_PIN         GPIO_PIN_1
#define FMC_UDQM_PINSOURCE        GPIO_PinSource1
#define FMC_UDQM_AF               GPIO_AF_FMC

#define FMC_LDQM_GPIO_PORT        GPIOE
#define FMC_LDQM_GPIO_CLK         __HAL_RCC_GPIOE_CLK_ENABLE()
#define FMC_LDQM_GPIO_PIN         GPIO_PIN_0
#define FMC_LDQM_PINSOURCE        GPIO_PinSource0
#define FMC_LDQM_AF               GPIO_AF_FMC


/** @defgroup STM32429 SDRAM函数
  * @{
  */ 
void  SDRAM_Init(void);
void  SDRAM_WriteBuffer(uint32_t* pBuffer, uint32_t uwWriteAddress, uint32_t uwBufferSize);
void  SDRAM_ReadBuffer(uint32_t* pBuffer, uint32_t uwReadAddress, uint32_t uwBufferSize);
uint8_t SDRAM_Test(void);
void Disable_NAND_CS(void);

#endif /* __SDRAM_H */


```c
/**
  ******************************************************************************
  * @file    bsp_sdram.c
  * @author  fire
  * @version V1.0
  * @date    2015-xx-xx
  * @brief   sdram应用函数接口
  ******************************************************************************
  * @attention
  *
  * 实验平台:野火  STM32 F767 开发板  
  * 论坛    :http://www.firebbs.cn
  * 淘宝    :http://fire-stm32.taobao.com
  *
  ******************************************************************************
  */
  
#include "./sdram/bsp_sdram.h"  
static FMC_SDRAM_CommandTypeDef Command;
SDRAM_HandleTypeDef hsdram1;
#define sdramHandle hsdram1
/**
  * @brief  延迟一段时间
  * @param  延迟的时间长度
  * @retval None
  */
static void SDRAM_delay(__IO uint32_t nCount)
{
  __IO uint32_t index = 0; 
  for(index = (100000 * nCount); index != 0; index--)
  {
  }
}

/**
  * @brief  初始化控制SDRAM的IO
  * @param  无
  * @retval 无
  */
static void SDRAM_GPIO_Config(void)
{		
  GPIO_InitTypeDef GPIO_InitStructure;
  
  /* 使能SDRAM相关的GPIO时钟 */

  /*地址信号线*/
  FMC_A0_GPIO_CLK;  FMC_A1_GPIO_CLK;  FMC_A2_GPIO_CLK;
  FMC_A3_GPIO_CLK;FMC_A4_GPIO_CLK;FMC_A5_GPIO_CLK;
  FMC_A6_GPIO_CLK; FMC_A7_GPIO_CLK; FMC_A8_GPIO_CLK;
  FMC_A9_GPIO_CLK; FMC_A10_GPIO_CLK;FMC_A11_GPIO_CLK; 
  FMC_A12_GPIO_CLK;
  /*数据信号线*/
  FMC_D0_GPIO_CLK; FMC_D1_GPIO_CLK ; FMC_D2_GPIO_CLK ; 
  FMC_D3_GPIO_CLK ; FMC_D4_GPIO_CLK ; FMC_D5_GPIO_CLK ;
  FMC_D6_GPIO_CLK; FMC_D7_GPIO_CLK ; FMC_D8_GPIO_CLK ;
  FMC_D9_GPIO_CLK ;FMC_D10_GPIO_CLK; FMC_D11_GPIO_CLK;
  FMC_D12_GPIO_CLK; FMC_D13_GPIO_CLK; FMC_D14_GPIO_CLK;
  FMC_D15_GPIO_CLK;  
  /*控制信号线*/
  FMC_CS_GPIO_CLK ; FMC_BA0_GPIO_CLK; FMC_BA1_GPIO_CLK ;
  FMC_WE_GPIO_CLK ; FMC_RAS_GPIO_CLK ; FMC_CAS_GPIO_CLK;
  FMC_CLK_GPIO_CLK ; FMC_CKE_GPIO_CLK; FMC_UDQM_GPIO_CLK;
  FMC_LDQM_GPIO_CLK;


  
  /*-- GPIO 配置 -----------------------------------------------------*/

  /* 通用 GPIO 配置 */       
  GPIO_InitStructure.Mode      = GPIO_MODE_AF_PP;//配置为复用功能
  GPIO_InitStructure.Pull      = GPIO_PULLUP;
  GPIO_InitStructure.Speed     = GPIO_SPEED_FAST;
  GPIO_InitStructure.Alternate = GPIO_AF12_FMC;
  
  
  /*地址信号线 针对引脚配置*/
  GPIO_InitStructure.Pin = FMC_A0_GPIO_PIN; 
  HAL_GPIO_Init(FMC_A0_GPIO_PORT, &GPIO_InitStructure);
  
  GPIO_InitStructure.Pin = FMC_A1_GPIO_PIN; 
  HAL_GPIO_Init(FMC_A1_GPIO_PORT, &GPIO_InitStructure);
  
  GPIO_InitStructure.Pin = FMC_A2_GPIO_PIN; 
  HAL_GPIO_Init(FMC_A2_GPIO_PORT, &GPIO_InitStructure);
  
  GPIO_InitStructure.Pin = FMC_A3_GPIO_PIN; 
  HAL_GPIO_Init(FMC_A3_GPIO_PORT, &GPIO_InitStructure);
  
  GPIO_InitStructure.Pin = FMC_A4_GPIO_PIN; 
  HAL_GPIO_Init(FMC_A4_GPIO_PORT, &GPIO_InitStructure);
  
  GPIO_InitStructure.Pin = FMC_A5_GPIO_PIN; 
  HAL_GPIO_Init(FMC_A5_GPIO_PORT, &GPIO_InitStructure);

  
  GPIO_InitStructure.Pin = FMC_A6_GPIO_PIN; 
  HAL_GPIO_Init(FMC_A6_GPIO_PORT, &GPIO_InitStructure);

  
  GPIO_InitStructure.Pin = FMC_A7_GPIO_PIN; 
  HAL_GPIO_Init(FMC_A7_GPIO_PORT, &GPIO_InitStructure);

  
  GPIO_InitStructure.Pin = FMC_A8_GPIO_PIN; 
  HAL_GPIO_Init(FMC_A8_GPIO_PORT, &GPIO_InitStructure);

  
  GPIO_InitStructure.Pin = FMC_A9_GPIO_PIN; 
  HAL_GPIO_Init(FMC_A9_GPIO_PORT, &GPIO_InitStructure);

  
  GPIO_InitStructure.Pin = FMC_A10_GPIO_PIN; 
  HAL_GPIO_Init(FMC_A10_GPIO_PORT, &GPIO_InitStructure);

  
  GPIO_InitStructure.Pin = FMC_A11_GPIO_PIN; 
  HAL_GPIO_Init(FMC_A11_GPIO_PORT, &GPIO_InitStructure);

  GPIO_InitStructure.Pin = FMC_A12_GPIO_PIN; 
  HAL_GPIO_Init(FMC_A12_GPIO_PORT, &GPIO_InitStructure);
  
  
  /*数据信号线 针对引脚配置*/
  GPIO_InitStructure.Pin = FMC_D0_GPIO_PIN; 
  HAL_GPIO_Init(FMC_D0_GPIO_PORT, &GPIO_InitStructure);

  
  GPIO_InitStructure.Pin = FMC_D1_GPIO_PIN; 
  HAL_GPIO_Init(FMC_D1_GPIO_PORT, &GPIO_InitStructure);

    
  GPIO_InitStructure.Pin = FMC_D2_GPIO_PIN; 
  HAL_GPIO_Init(FMC_D2_GPIO_PORT, &GPIO_InitStructure);

  
  GPIO_InitStructure.Pin = FMC_D3_GPIO_PIN; 
  HAL_GPIO_Init(FMC_D3_GPIO_PORT, &GPIO_InitStructure);

  
  GPIO_InitStructure.Pin = FMC_D4_GPIO_PIN; 
  HAL_GPIO_Init(FMC_D4_GPIO_PORT, &GPIO_InitStructure);

  
  GPIO_InitStructure.Pin = FMC_D5_GPIO_PIN; 
  HAL_GPIO_Init(FMC_D5_GPIO_PORT, &GPIO_InitStructure);

  
  GPIO_InitStructure.Pin = FMC_D6_GPIO_PIN; 
  HAL_GPIO_Init(FMC_D6_GPIO_PORT, &GPIO_InitStructure);

  
  GPIO_InitStructure.Pin = FMC_D7_GPIO_PIN; 
  HAL_GPIO_Init(FMC_D7_GPIO_PORT, &GPIO_InitStructure);

  
  GPIO_InitStructure.Pin = FMC_D8_GPIO_PIN; 
  HAL_GPIO_Init(FMC_D8_GPIO_PORT, &GPIO_InitStructure);

  
  GPIO_InitStructure.Pin = FMC_D9_GPIO_PIN; 
  HAL_GPIO_Init(FMC_D9_GPIO_PORT, &GPIO_InitStructure);

  
  GPIO_InitStructure.Pin = FMC_D10_GPIO_PIN; 
  HAL_GPIO_Init(FMC_D10_GPIO_PORT, &GPIO_InitStructure);

  
  GPIO_InitStructure.Pin = FMC_D11_GPIO_PIN; 
  HAL_GPIO_Init(FMC_D11_GPIO_PORT, &GPIO_InitStructure);

  
  GPIO_InitStructure.Pin = FMC_D12_GPIO_PIN; 
  HAL_GPIO_Init(FMC_D12_GPIO_PORT, &GPIO_InitStructure);

  
  GPIO_InitStructure.Pin = FMC_D13_GPIO_PIN; 
  HAL_GPIO_Init(FMC_D13_GPIO_PORT, &GPIO_InitStructure);

  
  GPIO_InitStructure.Pin = FMC_D14_GPIO_PIN; 
  HAL_GPIO_Init(FMC_D14_GPIO_PORT, &GPIO_InitStructure);

  
  GPIO_InitStructure.Pin = FMC_D15_GPIO_PIN; 
  HAL_GPIO_Init(FMC_D15_GPIO_PORT, &GPIO_InitStructure);

  
  /*控制信号线*/
  GPIO_InitStructure.Pin = FMC_CS_GPIO_PIN; 
  HAL_GPIO_Init(FMC_CS_GPIO_PORT, &GPIO_InitStructure);

  
  GPIO_InitStructure.Pin = FMC_BA0_GPIO_PIN; 
  HAL_GPIO_Init(FMC_BA0_GPIO_PORT, &GPIO_InitStructure);

  
  GPIO_InitStructure.Pin = FMC_BA1_GPIO_PIN;
  HAL_GPIO_Init(FMC_BA1_GPIO_PORT, &GPIO_InitStructure);

    
  GPIO_InitStructure.Pin = FMC_WE_GPIO_PIN; 
  HAL_GPIO_Init(FMC_WE_GPIO_PORT, &GPIO_InitStructure);

  
  GPIO_InitStructure.Pin = FMC_RAS_GPIO_PIN; 
  HAL_GPIO_Init(FMC_RAS_GPIO_PORT, &GPIO_InitStructure);

    
  GPIO_InitStructure.Pin = FMC_CAS_GPIO_PIN; 
  HAL_GPIO_Init(FMC_CAS_GPIO_PORT, &GPIO_InitStructure);

  
  GPIO_InitStructure.Pin = FMC_CLK_GPIO_PIN; 
  HAL_GPIO_Init(FMC_CLK_GPIO_PORT, &GPIO_InitStructure);

  
  GPIO_InitStructure.Pin = FMC_CKE_GPIO_PIN; 
  HAL_GPIO_Init(FMC_CKE_GPIO_PORT, &GPIO_InitStructure);

  
  GPIO_InitStructure.Pin = FMC_UDQM_GPIO_PIN; 
  HAL_GPIO_Init(FMC_UDQM_GPIO_PORT, &GPIO_InitStructure);

  
  GPIO_InitStructure.Pin = FMC_LDQM_GPIO_PIN; 
  HAL_GPIO_Init(FMC_LDQM_GPIO_PORT, &GPIO_InitStructure);

		
}

/**
  * @brief  对SDRAM芯片进行初始化配置
  * @param  None. 
  * @retval None.
  */
static void SDRAM_InitSequence(void)
{
  uint32_t tmpr = 0;
  
/* Step 3 --------------------------------------------------------------------*/
  /* 配置命令:开启提供给SDRAM的时钟 */
  Command.CommandMode = FMC_SDRAM_CMD_CLK_ENABLE;
  Command.CommandTarget = FMC_COMMAND_TARGET_BANK;
  Command.AutoRefreshNumber = 1;
  Command.ModeRegisterDefinition = 0;
/* Send the command */
  HAL_SDRAM_SendCommand(&sdramHandle, &Command, SDRAM_TIMEOUT);

  /* Step 2: Insert 100 us minimum delay */ 
  /* Inserted delay is equal to 1 ms due to systick time base unit (ms) */
  SDRAM_delay(1);
    
/* Step 5 --------------------------------------------------------------------*/
  /* 配置命令:对所有的bank预充电 */ 
  Command.CommandMode = FMC_SDRAM_CMD_PALL;
  Command.CommandTarget = FMC_COMMAND_TARGET_BANK;
  Command.AutoRefreshNumber = 1;
  Command.ModeRegisterDefinition = 0;
/* Send the command */
  HAL_SDRAM_SendCommand(&sdramHandle, &Command, SDRAM_TIMEOUT);   
  
/* Step 6 --------------------------------------------------------------------*/
  /* 配置命令:自动刷新 */   
  Command.CommandMode = FMC_SDRAM_CMD_AUTOREFRESH_MODE;
  Command.CommandTarget = FMC_COMMAND_TARGET_BANK;
  Command.AutoRefreshNumber = 4;
  Command.ModeRegisterDefinition = 0;
 /* Send the command */
  HAL_SDRAM_SendCommand(&sdramHandle, &Command, SDRAM_TIMEOUT);
  
/* Step 7 --------------------------------------------------------------------*/
  /* 设置sdram寄存器配置 */
  tmpr = (uint32_t)SDRAM_MODEREG_BURST_LENGTH_2          |
                   SDRAM_MODEREG_BURST_TYPE_SEQUENTIAL   |
                   SDRAM_MODEREG_CAS_LATENCY_3           |
                   SDRAM_MODEREG_OPERATING_MODE_STANDARD |
                   SDRAM_MODEREG_WRITEBURST_MODE_SINGLE;
  
  /* 配置命令:设置SDRAM寄存器 */
  Command.CommandMode = FMC_SDRAM_CMD_LOAD_MODE;
  Command.CommandTarget = FMC_COMMAND_TARGET_BANK;
  Command.AutoRefreshNumber = 1;
  Command.ModeRegisterDefinition = tmpr;
  /* Send the command */
  HAL_SDRAM_SendCommand(&sdramHandle, &Command, SDRAM_TIMEOUT);
  
/* Step 8 --------------------------------------------------------------------*/

  /* 设置刷新计数器 */
  /*刷新速率 = (COUNT + 1) x SDRAM 频率时钟
    COUNT =( SDRAM 刷新周期/行数) - 20*/
  /* 64ms/8192=7.813us  (7.813 us x FSDCLK) - 20 =683 */
  HAL_SDRAM_ProgramRefreshRate(&sdramHandle, 683); 
//  FMC_SetRefreshCount(1386);
//  /* 发送上述命令*/
//  while(FMC_GetFlagStatus(FMC_BANK_SDRAM, FMC_FLAG_Busy) != RESET)
//  {
//  }
}


/**
  * @brief  初始化配置使用SDRAM的FMC及GPIO接口,
  *         本函数在SDRAM读写操作前需要被调用
  * @param  None
  * @retval None
  */
void SDRAM_Init(void)
{
  //FMC_SDRAMInitTypeDef  FMC_SDRAMInitStructure;
//  FMC_SDRAMTimingInitTypeDef  FMC_SDRAMTimingInitStructure; 
  
  /* 配置FMC接口相关的 GPIO*/
  SDRAM_GPIO_Config();
  
  /* 使能 FMC 时钟 */
	__HAL_RCC_FMC_CLK_ENABLE();
//  RCC_AHB3PeriphClockCmd(RCC_AHB3Periph_FMC, ENABLE);
 
//  /* 配置 FMC 相关参数 ---------------------------------------------------------*/
//  /* SDCLK: 90 Mhz (HCLK/2 :180Mhz/2) */
//  /* TMRD: 2 Clock cycles */
//  FMC_SDRAMTimingInitStructure.FMC_LoadToActiveDelay    = 2;      
//  /* TXSR: min=70ns (7x11.11ns) */
//  FMC_SDRAMTimingInitStructure.FMC_ExitSelfRefreshDelay = 7;
//  /* TRAS: min=42ns (4x11.11ns) max=120k (ns) */
//  FMC_SDRAMTimingInitStructure.FMC_SelfRefreshTime      = 4;
//  /* TRC:  min=70 (7x11.11ns) */        
//  FMC_SDRAMTimingInitStructure.FMC_RowCycleDelay        = 7;         
//  /* TWR:  min=1+ 7ns (1+1x11.11ns) */
//  FMC_SDRAMTimingInitStructure.FMC_WriteRecoveryTime    = 2;      
//  /* TRP:  20ns => 2x11.11ns */
//  FMC_SDRAMTimingInitStructure.FMC_RPDelay              = 2;                
//  /* TRCD: 20ns => 2x11.11ns */
//  FMC_SDRAMTimingInitStructure.FMC_RCDDelay             = 2;

///* FMC SDRAM 控制配置 */
//  FMC_SDRAMInitStructure.FMC_Bank = FMC_BANK_SDRAM;
//  /* 行地址线宽度: [7:0] */
//  FMC_SDRAMInitStructure.FMC_ColumnBitsNumber = FMC_ColumnBits_Number_8b;
//  /* 列地址线宽度: [11:0] */
//  FMC_SDRAMInitStructure.FMC_RowBitsNumber = FMC_RowBits_Number_12b;
//  /* 数据线宽度 */
//  FMC_SDRAMInitStructure.FMC_SDMemoryDataWidth = SDRAM_MEMORY_WIDTH;
//  /* SDRAM内部bank数量*/
//  FMC_SDRAMInitStructure.FMC_InternalBankNumber = FMC_InternalBank_Number_4;
//  /* CAS潜伏期 */
//  FMC_SDRAMInitStructure.FMC_CASLatency = SDRAM_CAS_LATENCY; 
//  /* 禁止写保护*/
//  FMC_SDRAMInitStructure.FMC_WriteProtection = FMC_Write_Protection_Disable;
//  /* SDCLK时钟分频因子,SDCLK = HCLK/SDCLOCK_PERIOD*/
//  FMC_SDRAMInitStructure.FMC_SDClockPeriod = SDCLOCK_PERIOD; 
//  /* 突发读模式设置*/  
//  FMC_SDRAMInitStructure.FMC_ReadBurst = SDRAM_READBURST;
//  /* 读延迟配置 */
//  FMC_SDRAMInitStructure.FMC_ReadPipeDelay = FMC_ReadPipe_Delay_1;
//  /* SDRAM时序参数 */
//  FMC_SDRAMInitStructure.FMC_SDRAMTimingStruct = &FMC_SDRAMTimingInitStructure;
//  
//  /* FMC SDRAM bank initialization */
//  FMC_SDRAMInit(&FMC_SDRAMInitStructure); 
  FMC_SDRAM_TimingTypeDef SdramTiming;

  /** Perform the SDRAM1 memory initialization sequence
  */
  hsdram1.Instance = FMC_SDRAM_DEVICE;
  /* hsdram1.Init */
  hsdram1.Init.SDBank = FMC_SDRAM_BANK1;
  hsdram1.Init.ColumnBitsNumber = FMC_SDRAM_COLUMN_BITS_NUM_9;
  hsdram1.Init.RowBitsNumber = FMC_SDRAM_ROW_BITS_NUM_13;
  hsdram1.Init.MemoryDataWidth = FMC_SDRAM_MEM_BUS_WIDTH_16;
  hsdram1.Init.InternalBankNumber = FMC_SDRAM_INTERN_BANKS_NUM_4;
  hsdram1.Init.CASLatency = FMC_SDRAM_CAS_LATENCY_3;
  hsdram1.Init.WriteProtection = FMC_SDRAM_WRITE_PROTECTION_DISABLE;
  hsdram1.Init.SDClockPeriod = FMC_SDRAM_CLOCK_PERIOD_2;
  hsdram1.Init.ReadBurst = FMC_SDRAM_RBURST_DISABLE;
  hsdram1.Init.ReadPipeDelay = FMC_SDRAM_RPIPE_DELAY_1;
  /* SdramTiming */
  SdramTiming.LoadToActiveDelay = 2;
  SdramTiming.ExitSelfRefreshDelay = 7;
  SdramTiming.SelfRefreshTime = 4;
  SdramTiming.RowCycleDelay = 7;
  SdramTiming.WriteRecoveryTime = 2;
  SdramTiming.RPDelay = 2;
  SdramTiming.RCDDelay = 2;

  HAL_SDRAM_Init(&hsdram1, &SdramTiming);  
  /* FMC SDRAM device initialization sequence */
  SDRAM_InitSequence(); 
  
}



/**
  * @brief  以“字”为单位向sdram写入数据 
  * @param  pBuffer: 指向数据的指针 
  * @param  uwWriteAddress: 要写入的SDRAM内部地址
  * @param  uwBufferSize: 要写入数据大小
  * @retval None.
  */
void SDRAM_WriteBuffer(uint32_t* pBuffer, uint32_t uwWriteAddress, uint32_t uwBufferSize)
{
  __IO uint32_t write_pointer = (uint32_t)uwWriteAddress;

  /* 禁止写保护 */
  HAL_SDRAM_WriteProtection_Disable(&hsdram1);
  /* 检查SDRAM标志,等待至SDRAM空闲 */ 
  while(HAL_SDRAM_GetState(&hsdram1) != RESET)
  {
  }

  /* 循环写入数据 */
  for (; uwBufferSize != 0; uwBufferSize--) 
  {
    /* 发送数据到SDRAM */
    *(uint32_t *) (SDRAM_BANK_ADDR + write_pointer) = *pBuffer++;

    /* 地址自增*/
    write_pointer += 4;
  }
    
}

/**
  * @brief  从SDRAM中读取数据 
  * @param  pBuffer: 指向存储数据的buffer
  * @param  ReadAddress: 要读取数据的地十
  * @param  uwBufferSize: 要读取的数据大小
  * @retval None.
  */
void SDRAM_ReadBuffer(uint32_t* pBuffer, uint32_t uwReadAddress, uint32_t uwBufferSize)
{
  __IO uint32_t write_pointer = (uint32_t)uwReadAddress;
  
   
  /* 检查SDRAM标志,等待至SDRAM空闲 */  
  while ( HAL_SDRAM_GetState(&hsdram1) != RESET)
  {
  }
  
  /*读取数据 */
  for(; uwBufferSize != 0x00; uwBufferSize--)
  {
   *pBuffer++ = *(__IO uint32_t *)(SDRAM_BANK_ADDR + write_pointer );
    
   /* 地址自增*/
    write_pointer += 4;
  } 
}


/**
  * @brief  测试SDRAM是否正常 
  * @param  None
  * @retval 正常返回1,异常返回0
  */
uint8_t SDRAM_Test(void)
{
  /*写入数据计数器*/
  uint32_t counter=0;
  
  /* 8位的数据 */
  uint8_t ubWritedata_8b = 0, ubReaddata_8b = 0;  
  
  /* 16位的数据 */
  uint16_t uhWritedata_16b = 0, uhReaddata_16b = 0; 
  
  SDRAM_INFO("正在检测SDRAM,以8位、16位的方式读写sdram...");


  /*按8位格式读写数据,并校验*/
  
  /* 把SDRAM数据全部重置为0 ,IS42S16400J_SIZE是以8位为单位的 */
  for (counter = 0x00; counter < IS42S16400J_SIZE; counter++)
  {
    *(__IO uint8_t*) (SDRAM_BANK_ADDR + counter) = (uint8_t)0x0;
  }
  
  /* 向整个SDRAM写入数据  8位 */
  for (counter = 0; counter < IS42S16400J_SIZE; counter++)
  {
    *(__IO uint8_t*) (SDRAM_BANK_ADDR + counter) = (uint8_t)(ubWritedata_8b + counter);
  }
  
  /* 读取 SDRAM 数据并检测*/
  for(counter = 0; counter<IS42S16400J_SIZE;counter++ )
  {
    ubReaddata_8b = *(__IO uint8_t*)(SDRAM_BANK_ADDR + counter);  //从该地址读出数据
    
    if(ubReaddata_8b != (uint8_t)(ubWritedata_8b + counter))      //检测数据,若不相等,跳出函数,返回检测失败结果。
    {
      SDRAM_ERROR("8位数据读写错误!");
      return 0;
    }
  }
	
  
  /*按16位格式读写数据,并检测*/
  
  /* 把SDRAM数据全部重置为0 */
  for (counter = 0x00; counter < IS42S16400J_SIZE/2; counter++)
  {
    *(__IO uint16_t*) (SDRAM_BANK_ADDR + 2*counter) = (uint16_t)0x00;
  }
  
  /* 向整个SDRAM写入数据  16位 */
  for (counter = 0; counter < IS42S16400J_SIZE/2; counter++)
  {
    *(__IO uint16_t*) (SDRAM_BANK_ADDR + 2*counter) = (uint16_t)(uhWritedata_16b + counter);
  }
  
    /* 读取 SDRAM 数据并检测*/
  for(counter = 0; counter<IS42S16400J_SIZE/2;counter++ )
  {
    uhReaddata_16b = *(__IO uint16_t*)(SDRAM_BANK_ADDR + 2*counter);  //从该地址读出数据
    
    if(uhReaddata_16b != (uint16_t)(uhWritedata_16b + counter))      //检测数据,若不相等,跳出函数,返回检测失败结果。
    {
      SDRAM_ERROR("16位数据读写错误!");

      return 0;
    }
  }

  
  SDRAM_INFO("SDRAM读写测试正常!"); 
  /*检测正常,return 1 */
  return 1;
  

}




void Disable_NAND_CS(void)
{		
    /*定义一个GPIO_InitTypeDef类型的结构体*/
    GPIO_InitTypeDef  GPIO_InitStruct;

    /*开启GPIO外设时钟*/
    __GPIOG_CLK_ENABLE();

    /*选择要控制的GPIO引脚*/															   
    GPIO_InitStruct.Pin = GPIO_PIN_9;	

    /*设置引脚的输出类型为推挽输出*/
    GPIO_InitStruct.Mode  = GPIO_MODE_OUTPUT_PP;  

    /*设置引脚为上拉模式*/
    GPIO_InitStruct.Pull  = GPIO_PULLUP;

    /*设置引脚速率为高速 */   
    GPIO_InitStruct.Speed = GPIO_SPEED_HIGH; 

    /*调用库函数,使用上面配置的GPIO_InitStructure初始化GPIO*/
    HAL_GPIO_Init(GPIOG, &GPIO_InitStruct);	

		HAL_GPIO_WritePin(GPIOG,GPIO_PIN_9,GPIO_PIN_SET);	
}










/*********************************************END OF FILE**********************/


/**
  ******************************************************************************
  * @file    main.c
  * @author  fire
  * @version V1.0
  * @date    2017-xx-xx
  * @brief   GPIO输出--使用固件库点亮LED灯
  ******************************************************************************
  * @attention
  *
  * 实验平台:野火 STM32 F429 开发板 
  * 论坛    :http://www.firebbs.cn
  * 淘宝    :http://fire-stm32.taobao.com
  *
  ******************************************************************************
  */

/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "stm32f4xx.h"
#include "./usart/bsp_debug_usart.h" 
#include "./sdram/bsp_sdram.h"
#include <stdlib.h>
#include "./led/bsp_led.h" 

void Delay(__IO uint32_t nCount); 

void SDRAM_Check(void);
uint32_t RadomBuffer[10000];

uint32_t ReadBuffer[10000];

#define SDRAM_SIZE (IS42S16400J_SIZE/4)

uint32_t *pSDRAM;

long long count=0,sdram_count=0;

RNG_HandleTypeDef hrng;

/**
  * @brief  主函数
  * @param  无
  * @retval 无
  */
int main(void)
{
    /* 系统时钟初始化成216 MHz */
    SystemClock_Config();
    /* LED 端口初始化 */
    //LED_GPIO_Config();	 
    /* 初始化串口 */
    DEBUG_USART_Config();

	  /*防止NAND对共用脚影响*/
	  Disable_NAND_CS();
	
    printf("\r\n野火STM32F429 SDRAM 读写测试例程\r\n");
      
    /*初始化SDRAM模块*/
    SDRAM_Init();
	  SDRAM_Test();
    /*蓝灯亮,表示正在读写SDRAM测试*/
    LED_BLUE;
	
	/*使能RNG时钟*/
    __RNG_CLK_ENABLE();
	/*初始化RNG模块产生随机数*/
    hrng.Instance = RNG;
    HAL_RNG_Init(&hrng);

    printf("开始生成10000个SDRAM测试随机数\r\n");   
    for(count=0;count<10000;count++)

    {
        RadomBuffer[count]=HAL_RNG_GetRandomNumber(&hrng);

    }    
    printf("10000个SDRAM测试随机数生成完毕\r\n");

    SDRAM_Check();

    while(1)
	{
		
	}		
}

void SDRAM_Check(void)
{
  pSDRAM=(uint32_t*)SDRAM_BANK_ADDR;
	count=0;
	printf("开始写入SDRAM\r\n");
	for(sdram_count=0;sdram_count<SDRAM_SIZE;sdram_count++)
	{
		*pSDRAM=RadomBuffer[count];
		count++;
		pSDRAM++;
		if(count>=10000)

		{
			count=0;
		}
	}
	printf("写入总字节数:%d\r\n",(uint32_t)pSDRAM-SDRAM_BANK_ADDR);

	count=0;
	pSDRAM=(uint32_t*)SDRAM_BANK_ADDR;
	printf("开始读取SDRAM并与原随机数比较\r\n");
	sdram_count=0;
	for(;sdram_count<SDRAM_SIZE;sdram_count++)
	{
		if(*pSDRAM != RadomBuffer[count])
		{
			printf("数据比较错误——退出~\r\n");
			break;
		}
		count++;
		pSDRAM++;
		if(count>=10000)
		{
			count=0;
		}
	}

	printf("比较通过总字节数:%d\r\n",(uint32_t)pSDRAM-SDRAM_BANK_ADDR);

	if(sdram_count == SDRAM_SIZE)
	{
		LED_GREEN;
		printf("SDRAM测试成功\r\n");
	}
	else
	{
		LED_RED;
		printf("SDRAM测试失败\r\n");
	}   
}

/**
  * @brief  系统时钟配置 
  *            System Clock source            = PLL (HSE)
  *            SYSCLK(Hz)                     = 180000000
  *            HCLK(Hz)                       = 180000000
  *            AHB Prescaler                  = 1
  *            APB1 Prescaler                 = 4
  *            APB2 Prescaler                 = 2
  *            HSE Frequency(Hz)              = 25000000
  *            PLL_M                          = 25
  *            PLL_N                          = 360
  *            PLL_P                          = 2
  *            PLL_Q                          = 7
  *            VDD(V)                         = 3.3
  *            Main regulator output voltage  = Scale1 mode
  *            Flash Latency(WS)              = 5
  * @param  无
  * @retval 无
  */
static void SystemClock_Config(void)
{
  RCC_ClkInitTypeDef RCC_ClkInitStruct;
  RCC_OscInitTypeDef RCC_OscInitStruct;

  /* Enable Power Control clock */
  __HAL_RCC_PWR_CLK_ENABLE();
  
  /* 使能HSE,配置HSE为PLL的时钟源,配置PLL的各种分频因子M N P Q 
	 * PLLCLK = HSE/M*N/P = 25M / 25 *432 / 2 = 216M
	 */
  __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
  
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
  RCC_OscInitStruct.HSEState = RCC_HSE_ON;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
  RCC_OscInitStruct.PLL.PLLM = 25;
  RCC_OscInitStruct.PLL.PLLN = 360;
  RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
  RCC_OscInitStruct.PLL.PLLQ = 7;
  if(HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
   while(1) {}
  }

  /* 激活 OverDrive 模式 */
  HAL_PWREx_EnableOverDrive();
 
  /* 选择PLLCLK作为SYSCLK,并配置 HCLK, PCLK1 and PCLK2 的时钟分频因子 
	 * SYSCLK = PLLCLK     = 180M
	 * HCLK   = SYSCLK / 1 = 180M
	 * PCLK2  = SYSCLK / 2 = 90M
	 * PCLK1  = SYSCLK / 4 = 45M
	 */
  RCC_ClkInitStruct.ClockType = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2);
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;  
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;  
  if(HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5) != HAL_OK)
  {
    while(1) {}
  }
}


/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

大文梅

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值