STM32f746gdiscovery SDRAM 驱动
程序员文章站
2024-02-25 10:36:52
...
STM32f746gdiscovery 开发板使用的是16MB的SDRAM,由于少了一根地址线,只有8MB可用。
/*************************************************************************************************************
* 文件名 : stm32f7_sdram.c
* 功能 : STM32F7 外部SDRAM驱动
* 作者 : aaa@qq.com
* 创建时间 : 2019-09-08
* 最后修改时间 : 2019-09-08
* 详细 : 2019-10-31 设置突发长度:4(可以是1/2/4/8)-测试过1/2/4发现都正常,唯独8的时候,屏幕会出现随机噪点
*************************************************************************************************************/
#include "stm32f7_sdram.h"
#include "SYSTEM.H"
//BANK选择
typedef enum
{
SDRAM_CMD_BANK1 = 2, //命令模板存储区域1
SDRAM_CMD_BANK2 = 1, //命令模板存储区域2
SDRAM_CMD_BANK1_2 = 3, //命令模板存储区域1与2
}SDRAM_CMD_BANK_SELECT;
//命令
typedef enum
{
SDRAM_CMD_NORMAL = 0, //正常模式
SDRAM_CMD_CLOCK_CONFIG = 1, //时钟配置使能
SDRAM_CMD_PALL = 2, //预充电所有存储区域
SDRAM_CMD_AR = 3, //自刷新命令
SDRAM_CMD_LOAD_MODE = 4, //加载模式寄存器
//SDRAM_CMD_AR = 5, //自刷新命令
SDRAM_CMD_POWER_DOWN = 6, //掉电命令
}SDRAM_CMD_TYPE;
bool SDRAM_SendCmd(SDRAM_CMD_BANK_SELECT BankSelect, u16 mode, u8 AutoRefresh, SDRAM_CMD_TYPE cmd);//SDRAM 命令模式设置
/*************************************************************************************************************************
* 函数 : void SDRAM_Init(void)
* 功能 : SDRAM 接口初始化
* 参数 : 无
* 返回 : 无
* 依赖 : 底层宏定义
* 作者 : aaa@qq.com
* 时间 : 2019-09-08
* 最后修改时间 : 2019-09-08
* 说明 : 用于初始化STM32F7 SDRAM 接口
*************************************************************************************************************************/
void SDRAM_Init(void)
{
u32 temp;
SYS_DeviceClockEnable(DEV_FSMC, TRUE); //FSMC时钟使能
SYS_DeviceClockEnable(DEV_GPIOC, TRUE); //使能GPIOC时钟
SYS_DeviceClockEnable(DEV_GPIOD, TRUE); //使能GPIOD时钟
SYS_DeviceClockEnable(DEV_GPIOE, TRUE); //使能GPIOE时钟
SYS_DeviceClockEnable(DEV_GPIOF, TRUE); //使能GPIOF时钟
SYS_DeviceClockEnable(DEV_GPIOG, TRUE); //使能GPIOG时钟
SYS_DeviceClockEnable(DEV_GPIOH, TRUE); //使能GPIOH时钟
//初始化IO
SYS_GPIOx_Init(GPIOC, BIT3, AF_PP_OPU, SPEED_100M); //PC3
SYS_GPIOx_Init(GPIOD, BIT0|BIT1|BIT8|BIT9|BIT10|BIT14|BIT15, AF_PP_OPU, SPEED_100M); //PD0/1/8/9/10/14/15
SYS_GPIOx_Init(GPIOE, BIT0|BIT1|(0X1FF<<7), AF_PP_OPU, SPEED_100M); //PE0/1/7~15
SYS_GPIOx_Init(GPIOF, BIT0|BIT1|BIT2|BIT3|BIT4|BIT5|BIT11|BIT12|BIT13|BIT14|BIT15, AF_PP_OPU, SPEED_100M); //PF0~5/11~15
SYS_GPIOx_Init(GPIOG, BIT0|BIT1|BIT4|BIT5|BIT8|BIT15, AF_PP_OPU, SPEED_100M); //PG0/1/4/5/8/15
SYS_GPIOx_Init(GPIOH, BIT3|BIT5, AF_PP_OPU, SPEED_100M);
SYS_GPIOx_SetAF(GPIOC, 3, AF12_FSMC); //PC3,AF12
SYS_GPIOx_SetAF(GPIOD, 0, AF12_FSMC); //PD0,AF12
SYS_GPIOx_SetAF(GPIOD, 1, AF12_FSMC); //PD1,AF12
SYS_GPIOx_SetAF(GPIOD, 8, AF12_FSMC); //PD8,AF12
SYS_GPIOx_SetAF(GPIOD, 9, AF12_FSMC); //PD9,AF12
SYS_GPIOx_SetAF(GPIOD, 10, AF12_FSMC); //PD10,AF12
SYS_GPIOx_SetAF(GPIOD, 14, AF12_FSMC); //PD14,AF12
SYS_GPIOx_SetAF(GPIOD, 15, AF12_FSMC); //PD15,AF12
SYS_GPIOx_SetAF(GPIOE, 0, AF12_FSMC); //PE0,AF12
SYS_GPIOx_SetAF(GPIOE, 1, AF12_FSMC); //PE1,AF12
SYS_GPIOx_SetAF(GPIOE, 7, AF12_FSMC); //PE7,AF12
SYS_GPIOx_SetAF(GPIOE, 8, AF12_FSMC); //PE8,AF12
SYS_GPIOx_SetAF(GPIOE, 9, AF12_FSMC); //PE9,AF12
SYS_GPIOx_SetAF(GPIOE, 10, AF12_FSMC); //PE10,AF12
SYS_GPIOx_SetAF(GPIOE, 11, AF12_FSMC); //PE11,AF12
SYS_GPIOx_SetAF(GPIOE, 12, AF12_FSMC); //PE12,AF12
SYS_GPIOx_SetAF(GPIOE, 13, AF12_FSMC); //PE13,AF12
SYS_GPIOx_SetAF(GPIOE, 14, AF12_FSMC); //PE14,AF12
SYS_GPIOx_SetAF(GPIOE, 15, AF12_FSMC); //PE15,AF12
SYS_GPIOx_SetAF(GPIOF, 0, AF12_FSMC); //PF0,AF12
SYS_GPIOx_SetAF(GPIOF, 1, AF12_FSMC); //PF1,AF12
SYS_GPIOx_SetAF(GPIOF, 2, AF12_FSMC); //PF2,AF12
SYS_GPIOx_SetAF(GPIOF, 3, AF12_FSMC); //PF3,AF12
SYS_GPIOx_SetAF(GPIOF, 4, AF12_FSMC); //PF4,AF12
SYS_GPIOx_SetAF(GPIOF, 5, AF12_FSMC); //PF5,AF12
SYS_GPIOx_SetAF(GPIOF, 11, AF12_FSMC); //PF11,AF12
SYS_GPIOx_SetAF(GPIOF, 12, AF12_FSMC); //PF12,AF12
SYS_GPIOx_SetAF(GPIOF, 13, AF12_FSMC); //PF13,AF12
SYS_GPIOx_SetAF(GPIOF, 14, AF12_FSMC); //PF14,AF12
SYS_GPIOx_SetAF(GPIOF, 15, AF12_FSMC); //PF15,AF12
SYS_GPIOx_SetAF(GPIOG, 0, AF12_FSMC); //PG0,AF12
SYS_GPIOx_SetAF(GPIOG, 1, AF12_FSMC); //PG1,AF12
SYS_GPIOx_SetAF(GPIOG, 4, AF12_FSMC); //PG4,AF12
SYS_GPIOx_SetAF(GPIOG, 5, AF12_FSMC); //PG5,AF12
SYS_GPIOx_SetAF(GPIOG, 8, AF12_FSMC); //PG8,AF12
SYS_GPIOx_SetAF(GPIOG, 15, AF12_FSMC); //PG15,AF12
SYS_GPIOx_SetAF(GPIOH, 3, AF12_FSMC); //PH3,AF12
SYS_GPIOx_SetAF(GPIOH, 5, AF12_FSMC); //PH5,AF12
temp = 0;
temp |= 0<<0; //8位列地址
temp |= 1<<2; //12位行地址
temp |= 1<<4; //16位数据位宽
temp |= 1<<6; //4个内部存区(4 BANKS)
temp |= 2<<7; //2个CAS延迟
temp |= 0<<9; //允许写访问
temp |= 2<<10; //SDRAM时钟=HCLK/2
temp |= 1<<12; //使能突发访问
temp |= 0<<13; //读通道延迟0个HCLK
FMC_Bank5_6->SDCR[0] = temp; //设置FMC BANK5 SDRAM控制寄存器(BANK5和6用于管理SDRAM).
temp = 0;
temp|=1<<0; //加载模式寄存器到**时间的延迟为2个时钟周期
temp|=5<<4; //退出自刷新延迟为6个时钟周期
temp|=3<<8; //自刷新时间为4个时钟周期
temp|=5<<12; //行循环延迟为6个时钟周期
temp|=1<<16; //恢复延迟为2个时钟周期
temp|=1<<20; //行预充电延迟为2个时钟周期
temp|=1<<24; //行到列延迟为2个时钟周期
FMC_Bank5_6->SDTR[0] = temp; //设置FMC BANK5 SDRAM时序寄存器
SDRAM_SendCmd(SDRAM_CMD_BANK1, 0, 1, SDRAM_CMD_CLOCK_CONFIG); //时钟配置使能
Delay_US(300); //至少延迟200us.
SDRAM_SendCmd(SDRAM_CMD_BANK1,0, 1, SDRAM_CMD_PALL); //对所有存储区预充电
SDRAM_SendCmd(SDRAM_CMD_BANK1,0, 8, SDRAM_CMD_AR); //设置自刷新次数
temp = 0;
temp |= 2<<0; //设置突发长度:4(可以是1/2/4/8) -测试过1/2/4发现都正常,唯独8的时候,屏幕会出现随机噪点
temp |= 0<<3; //设置突发类型:连续(可以是连续/交错)
temp |= 2<<4; //设置CAS值:2
temp |= 0<<7; //设置操作模式:0,标准模式
temp |= 1<<9; //设置突发写模式:1,单点访问
SDRAM_SendCmd(SDRAM_CMD_BANK1,temp, 1, SDRAM_CMD_LOAD_MODE); //设置SDRAM模式
//COUNT=SDRAM刷新周期/行数-20
//SDRAM刷新周期为64ms,SDCLK=AHB/2=100Mhz,行数为4096.
//计算方法为64*1000*AHB/2/4096-20
temp = 64*1000*(SYS_GetAHBClockSpeed()/1000000/2)/4096-20;
FMC_Bank5_6->SDRTR = temp<<1; //设置刷新频率计数器
}
/*************************************************************************************************************************
* 函数 : bool SDRAM_SendCmd(SDRAM_CMD_BANK_SELECT BankSelect, u16 mdr, u8 AutoRefresh, SDRAM_CMD_TYPE mode)
* 功能 : SDRAM 命令模式设置
* 参数 : BankSelect:bank选择;mdr:模式;AutoRefresh:自刷新设置;mode:模式命令
* 返回 : TRUE:成功;FALSE:失败
* 依赖 : 底层宏定义
* 作者 : aaa@qq.com
* 时间 : 2019-09-08
* 最后修改时间 : 2019-09-08
* 说明 :
*************************************************************************************************************************/
bool SDRAM_SendCmd(SDRAM_CMD_BANK_SELECT BankSelect, u16 mdr, u8 AutoRefresh, SDRAM_CMD_TYPE mode)
{
u32 retry=0;
u32 temp = 0;
temp |= mode<<0; //设置指令
temp |= BankSelect<<3; //设置发送指令到bank5还是6
temp |= (AutoRefresh&0xf)<<5; //设置自刷新次数
temp |= mdr<<9; //设置模式寄存器的值
FMC_Bank5_6->SDCMR = temp; //配置寄存器
//temp = FMC_Bank5_6->SDCMR;
//uart_printf("FMC_Bank5_6->SDCMR=%X\r\n", temp);
while((FMC_Bank5_6->SDSR&(1<<5))) //等待指令发送完成
{
retry++;
Delay_US(1);
if(retry > 50000)return FALSE;
}
return TRUE;
}
/*************************************************************************************************************
* 文件名 : stm32f7_sdram.h
* 功能 : STM32F7 外部SDRAM驱动
* 作者 : aaa@qq.com
* 创建时间 : 2019-09-08
* 最后修改时间 : 2019-09-08
* 详细:
*************************************************************************************************************/
#ifndef __STM32F7_SDRAM_H_
#define __STM32F7_SDRAM_H_
#include "system.h"
//========================================================================
// SRAM硬件相关配置
//------------------------------------------------------------------------
#define Bank5_SDRAM_ADDR ((u32)0XC0000000)
void SDRAM_Init(void); //SDRAM初始化
#endif //__STM32F7_SDRAM_H_
上一篇: mysql自增ID起始值修改方法
下一篇: c#注册客户端事件示例