概述
功能框图
这是一种型号为 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的读写流程
读时序和写时序的命令过程很类似,下面我们统一解说:
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("rn野火STM32F429 SDRAM 读写测试例程rn");
/*初始化SDRAM模块*/
SDRAM_Init();
SDRAM_Test();
/*蓝灯亮,表示正在读写SDRAM测试*/
LED_BLUE;
/*使能RNG时钟*/
__RNG_CLK_ENABLE();
/*初始化RNG模块产生随机数*/
hrng.Instance = RNG;
HAL_RNG_Init(&hrng);
printf("开始生成10000个SDRAM测试随机数rn");
for(count=0;count<10000;count++)
{
RadomBuffer[count]=HAL_RNG_GetRandomNumber(&hrng);
}
printf("10000个SDRAM测试随机数生成完毕rn");
SDRAM_Check();
while(1)
{
}
}
void SDRAM_Check(void)
{
pSDRAM=(uint32_t*)SDRAM_BANK_ADDR;
count=0;
printf("开始写入SDRAMrn");
for(sdram_count=0;sdram_count<SDRAM_SIZE;sdram_count++)
{
*pSDRAM=RadomBuffer[count];
count++;
pSDRAM++;
if(count>=10000)
{
count=0;
}
}
printf("写入总字节数:%drn",(uint32_t)pSDRAM-SDRAM_BANK_ADDR);
count=0;
pSDRAM=(uint32_t*)SDRAM_BANK_ADDR;
printf("开始读取SDRAM并与原随机数比较rn");
sdram_count=0;
for(;sdram_count<SDRAM_SIZE;sdram_count++)
{
if(*pSDRAM != RadomBuffer[count])
{
printf("数据比较错误——退出~rn");
break;
}
count++;
pSDRAM++;
if(count>=10000)
{
count=0;
}
}
printf("比较通过总字节数:%drn",(uint32_t)pSDRAM-SDRAM_BANK_ADDR);
if(sdram_count == SDRAM_SIZE)
{
LED_GREEN;
printf("SDRAM测试成功rn");
}
else
{
LED_RED;
printf("SDRAM测试失败rn");
}
}
/**
* @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****/
最后
以上就是迷人楼房为你收集整理的stm32f429FMC外设学习的全部内容,希望文章能够帮你解决stm32f429FMC外设学习所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复