欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

STM32F429驱动外部SDRAM

程序员文章站 2022-03-06 08:05:44
...

STM32F429的一个很大优势就是可以直接驱动SDRAM,这样一下子就可以外扩可观的运存,很诱惑。
这里用到的SDRAM 为W9825G6KH, 256Mbit, 32MByte

  1. 配置CubeMX
    STM32F429驱动外部SDRAM
    这里不展开这里面的数值的具体计算过程,主要是按照手册来算的,感兴趣的可以网上寻找,有很多相关的资料。
  2. SDRAM 初始化,SDRAM不像SRAM配置好了就可以用,他需要初始化
#include "stm32f4xx_hal.h"

extern SDRAM_HandleTypeDef hsdram1;

#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_BANK1_BASE_ADDRESS    0XC0000000  
#define SDRAM_HALF_WORD_SIZE        0x1000000      //0x1000000 - 16M*16bit =32Mbyte
 
void SDRAM_Initialization_Sequence(SDRAM_HandleTypeDef *hsdram);
void SDRAM_TEST(void);

typedef uint16_t u16;
typedef uint8_t u8;
typedef uint32_t u32;
/**
  * @brief  Perform the SDRAM exernal memory inialization sequence
  * @param  hsdram: SDRAM handle
  * @param  Command: Pointer to SDRAM command structure
  * @retval None
	  SDRAM刷新周期是64ms,行数是8192行,时钟频率是180MHz/2=90MHz
    所有COUNT = (64ms/8192)/(1/90us)-20 = 64000*90/8192-20 = 683
  */
void SDRAM_Initialization_Sequence(SDRAM_HandleTypeDef *hsdram)
{
    __IO uint32_t tmpmrd = 0;
    FMC_SDRAM_CommandTypeDef Command;
 
    /* Configure a clock configuration enable command */
    Command.CommandMode 		 = FMC_SDRAM_CMD_CLK_ENABLE;
    Command.CommandTarget 		 = FMC_SDRAM_CMD_TARGET_BANK1;
    Command.AutoRefreshNumber 	 = 1;
    Command.ModeRegisterDefinition = 0;
 
    /* Send the command */
    HAL_SDRAM_SendCommand(hsdram, &Command, 0x1000);
 
    /* Insert 10 ms delay */
    HAL_Delay(10);
 
    /* Configure a PALL (precharge all) command */
    Command.CommandMode 		 = FMC_SDRAM_CMD_PALL;
    Command.CommandTarget 	     = FMC_SDRAM_CMD_TARGET_BANK1;
    Command.AutoRefreshNumber 	 = 1;
    Command.ModeRegisterDefinition = 0;
 
    /* Send the command */
    HAL_SDRAM_SendCommand(hsdram, &Command, 0x1000);
 
    /* Configure a Auto-Refresh command */
    Command.CommandMode 		 = FMC_SDRAM_CMD_AUTOREFRESH_MODE;
    Command.CommandTarget 		 = FMC_SDRAM_CMD_TARGET_BANK1;
    Command.AutoRefreshNumber 	 = 8;
    Command.ModeRegisterDefinition = 0;
 
    /* Send the command */
    HAL_SDRAM_SendCommand(hsdram, &Command, 0x1000);
 
    /* Program the external memory mode register */
    tmpmrd = (uint32_t)SDRAM_MODEREG_BURST_LENGTH_8|
             SDRAM_MODEREG_BURST_TYPE_SEQUENTIAL   |
             SDRAM_MODEREG_CAS_LATENCY_3           |
             SDRAM_MODEREG_OPERATING_MODE_STANDARD |
             SDRAM_MODEREG_WRITEBURST_MODE_SINGLE;
 
    Command.CommandMode = FMC_SDRAM_CMD_LOAD_MODE;
    Command.CommandTarget 		 = FMC_SDRAM_CMD_TARGET_BANK1;
    Command.AutoRefreshNumber 	 = 1;
    Command.ModeRegisterDefinition = tmpmrd;
 
    /* Send the command */
    HAL_SDRAM_SendCommand(hsdram, &Command, 0x1000);
 
    /* Set the refresh rate counter */
    /* (7.81us x Freq) - 20 */
    /* Set the device refresh counter */
    HAL_SDRAM_ProgramRefreshRate(hsdram, 683);
}
void SDRAM_TEST(void)
{
	uint32_t temp = 0;
	uint16_t err=0;
	for(i=0;i<SDRAM_HALF_WORD_SIZE;i++)
	{
		*(__IO uint16_t*)(SDRAM_BANK1_BASE_ADDRESS+2*i) = (uint16_t)i;
	}
	for(i=0;i<SDRAM_HALF_WORD_SIZE;i++)
	{
		temp = 0;
		temp = *(__IO uint16_t*)(SDRAM_BANK1_BASE_ADDRESS+2*i);
		if(temp!=(uint16_t)i)
		{
			err++;
		}
	}
	printf("Total error =%d\n",err);
}

3.MAIN函数中加入即可

SDRAM_Initialization_Sequence();
SDRAM_TEST();//optioanl
相关标签: STM32 SDRAM