天天看點

STM32F429驅動外部SDRAM

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
           

繼續閱讀