STM32F429驱动外部SDRAM
程序员文章站
2022-03-06 08:05:44
...
STM32F429的一个很大优势就是可以直接驱动SDRAM,这样一下子就可以外扩可观的运存,很诱惑。
这里用到的SDRAM 为W9825G6KH, 256Mbit, 32MByte
- 配置CubeMX
这里不展开这里面的数值的具体计算过程,主要是按照手册来算的,感兴趣的可以网上寻找,有很多相关的资料。 - 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
上一篇: Linux环境变量和进程地址空间介绍
下一篇: nginx容器配置文件独立的实现