STM32F429 FSMC总线扩展SDRAM DMA中断调试笔记

keil版本:5.25
STM32F429IIT6+W9825G6KH(32M 字节 SDRAM)
SDRAM地址 0XC0000000 - 0XC2000000

uint32_t dma_sram_buf[200]__attribute__((at(0XC0000100)))={0};//SDRAM
uint32_t dma_ram_buf[200]={0};//内部ram

一、SDRAM配置

SDRAM_HandleTypeDef SDRAM_Handler;   //SDRAM句柄
//SDRAM初始化
void SDRAM_Init(void)
{
    FMC_SDRAM_TimingTypeDef SDRAM_Timing;
                                                     
    SDRAM_Handler.Instance=FMC_SDRAM_DEVICE;                             //SDRAM在BANK5,6  
    SDRAM_Handler.Init.SDBank=FMC_SDRAM_BANK1;                           //第一个SDRAM BANK
    SDRAM_Handler.Init.ColumnBitsNumber=FMC_SDRAM_COLUMN_BITS_NUM_9;     //列数量
    SDRAM_Handler.Init.RowBitsNumber=FMC_SDRAM_ROW_BITS_NUM_13;          //行数量
    SDRAM_Handler.Init.MemoryDataWidth=FMC_SDRAM_MEM_BUS_WIDTH_16;       //数据宽度为16位
    SDRAM_Handler.Init.InternalBankNumber=FMC_SDRAM_INTERN_BANKS_NUM_4;  //一共4个BANK
    SDRAM_Handler.Init.CASLatency=FMC_SDRAM_CAS_LATENCY_3;               //CAS为3
    SDRAM_Handler.Init.WriteProtection=FMC_SDRAM_WRITE_PROTECTION_DISABLE;//失能写保护
    SDRAM_Handler.Init.SDClockPeriod=FMC_SDRAM_CLOCK_PERIOD_2;           //SDRAM时钟为HCLK/2=180M/2=90M=11.1ns
    SDRAM_Handler.Init.ReadBurst=FMC_SDRAM_RBURST_ENABLE;                //使能突发
    SDRAM_Handler.Init.ReadPipeDelay=FMC_SDRAM_RPIPE_DELAY_1;            //读通道延时
    
    SDRAM_Timing.LoadToActiveDelay=2;                                   //加载模式寄存器到激活时间的延迟为2个时钟周期
    SDRAM_Timing.ExitSelfRefreshDelay=8;                                //退出自刷新延迟为8个时钟周期
    SDRAM_Timing.SelfRefreshTime=6;                                     //自刷新时间为6个时钟周期                                 
    SDRAM_Timing.RowCycleDelay=6;                                       //行循环延迟为6个时钟周期
    SDRAM_Timing.WriteRecoveryTime=2;                                   //恢复延迟为2个时钟周期
    SDRAM_Timing.RPDelay=2;                                             //行预充电延迟为2个时钟周期
    SDRAM_Timing.RCDDelay=2;                                            //行到列延迟为2个时钟周期
    
    HAL_SDRAM_Init(&SDRAM_Handler,&SDRAM_Timing);SDRAM底层驱动,引脚配置,时钟使能被HAL_SDRAM_Init()调用
    SDRAM_Initialization_Sequence(&SDRAM_Handler);//发送SDRAM初始化序列
	//刷新频率计数器(以SDCLK频率计数),计算方法:
	//COUNT=SDRAM刷新周期/行数-20=SDRAM刷新周期(us)*SDCLK频率(Mhz)/行数
    //我们使用的SDRAM刷新周期为64ms,SDCLK=180/2=90Mhz,行数为8192(2^13).
	//所以,COUNT=64*1000*90/8192-20=683
	HAL_SDRAM_ProgramRefreshRate(&SDRAM_Handler,683);//设置刷新频率

}
//发送SDRAM初始化序列
void SDRAM_Initialization_Sequence(SDRAM_HandleTypeDef *hsdram)
{
    u32 temp=0;
    //SDRAM控制器初始化完成以后还需要按照如下顺序初始化SDRAM
    SDRAM_Send_Cmd(0,FMC_SDRAM_CMD_CLK_ENABLE,1,0); //时钟配置使能
    delay_us(500);                                  //至少延时200us
    SDRAM_Send_Cmd(0,FMC_SDRAM_CMD_PALL,1,0);       //对所有存储区预充电
    SDRAM_Send_Cmd(0,FMC_SDRAM_CMD_AUTOREFRESH_MODE,8,0);//设置自刷新次数 
    //配置模式寄存器,SDRAM的bit0~bit2为指定突发访问的长度,
	//bit3为指定突发访问的类型,bit4~bit6为CAS值,bit7和bit8为运行模式
	//bit9为指定的写突发模式,bit10和bit11位保留位
	temp=(u32)SDRAM_MODEREG_BURST_LENGTH_1          |	//设置突发长度:1(可以是1/2/4/8)
              SDRAM_MODEREG_BURST_TYPE_SEQUENTIAL   |	//设置突发类型:连续(可以是连续/交错)
              SDRAM_MODEREG_CAS_LATENCY_3           |	//设置CAS值:3(可以是2/3)
              SDRAM_MODEREG_OPERATING_MODE_STANDARD |   //设置操作模式:0,标准模式
              SDRAM_MODEREG_WRITEBURST_MODE_SINGLE;     //设置突发写模式:1,单点访问
    SDRAM_Send_Cmd(0,FMC_SDRAM_CMD_LOAD_MODE,1,temp);   //设置SDRAM的模式寄存器
}

二、DMA配置

DMA_HandleTypeDef  SdramDMA_Handler;      //DMA句柄
//DMAx的各通道配置
void MYDMA_Config(DMA_Stream_TypeDef *DMA_Streamx,u32 chx)
{ 
	if((u32)DMA_Streamx>(u32)DMA2)//得到当前stream是属于DMA2还是DMA1
	{
        __HAL_RCC_DMA2_CLK_ENABLE();//DMA2时钟使能	
	}else 
	{
        __HAL_RCC_DMA1_CLK_ENABLE();//DMA1时钟使能 
	}

    SdramDMA_Handler.Instance=DMA_Streamx;                            //数据流选择
    SdramDMA_Handler.Init .Channel = chx;
    /* 存储器到存储器模式 */
    SdramDMA_Handler.Init.Direction = DMA_MEMORY_TO_MEMORY;
    /* 使能自动递增功能 */
    SdramDMA_Handler.Init.PeriphInc = DMA_PINC_ENABLE;
    /* 使能自动递增功能 */
    SdramDMA_Handler.Init.MemInc = DMA_MINC_ENABLE;
    /* 源数据是字大小(32 位) */
    SdramDMA_Handler.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;
    /* 目标数据也是字大小(32 位) */
    SdramDMA_Handler.Init.MemDataAlignment = DMA_MDATAALIGN_WORD;
    /* 一次传输模式,存储器到存储器模式不能使用循环传输 */
    SdramDMA_Handler.Init.Mode = DMA_NORMAL;
    /* DMA 数据流优先级为高 */
    SdramDMA_Handler.Init.Priority = DMA_PRIORITY_HIGH;
    /* 禁用 FIFO 模式 */
    SdramDMA_Handler.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
    SdramDMA_Handler.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL;
    /* 单次模式 */
    SdramDMA_Handler.Init.MemBurst = DMA_MBURST_SINGLE;
    /* 单次模式 */
    SdramDMA_Handler.Init.PeriphBurst = DMA_PBURST_SINGLE;
    /* 完成 DMA 数据流参数配置 */

    HAL_DMA_Init(&SdramDMA_Handler);
} 

三、中断配置

void DMA2_Stream0_IRQHandler(void)//手动添加这个函数
{
    HAL_DMA_IRQHandler(&SdramDMA_Handler);//处理DMA中断请求
    /*
    通过调用 HAL_DMA_Start 来开始使用 DMA 搬运数据。但使用是需要注意的是,该函数调用一次就会失效。其原因有三个:
    函数内将 hdma->State 的状态改为了 HAL_DMA_STATE_BUSY,但结束传输以后并没有改回为 HAL_DMA_STATE_READY。
    函数内的 __HAL_UNLOCK() 执行是在 hdma->State为 HAL_DMA_STATE_BUSY 的状态下。
    在中断状态寄存器(DMA_L/HISR)中。传输完成后会将 TCIFx 和 HTIFx 位置位。在不使用中断的情况下,也会置位。HAL_DMA_Start 并没有清除这两位。
    所以,要想使用 HAL_DMA_Start 来搬运数据,加上以下代码即可:
    */
    __HAL_UNLOCK(&SdramDMA_Handler);
    SdramDMA_Handler.State = HAL_DMA_STATE_READY;
    __HAL_DMA_CLEAR_FLAG(&SdramDMA_Handler, DMA_FLAG_TCIF0_4);
    __HAL_DMA_CLEAR_FLAG(&SdramDMA_Handler, DMA_FLAG_HTIF0_4);

}

四、中断回调函数

void sdram_DMA_RegisterCallback(DMA_HandleTypeDef *hdma)
{
    //用户代码
}

五、测试
mian.c

int main(void)
{
	 //系统初始化
	  .............
	  SDRAM_Init();
	  ................
      
      MYDMA_Config(DMA2_Stream0,DMA_CHANNEL_0);//DMA_MEMORY_TO_MEMORY 只能用DMA2
      HAL_NVIC_SetPriority(DMA2_Stream0_IRQn,3,3);
      HAL_NVIC_EnableIRQ(DMA2_Stream0_IRQn); 
      HAL_DMA_RegisterCallback(&SdramDMA_Handler,HAL_DMA_XFER_CPLT_CB_ID,sdram_DMA_RegisterCallback);//传输完成回调函数注册

      //Sdram--》ram
      for(int i=0;i<200;i++)
      {
          dma_sram_buf[i]=i+100;
      }
      delay_ms(10);  
      HAL_DMA_Start_IT(&SdramDMA_Handler, (uint32_t)dma_sram_buf, (uint32_t)dma_ram_buf, 200);
      delay_ms(10); 
      
      //ram--》Sdram
       for(int i=0;i<200;i++)
      {
          dma_ram_buf[i]=i+10;
      }
      delay_ms(10);  
      HAL_DMA_Start_IT(&SdramDMA_Handler, (uint32_t)dma_ram_buf, (uint32_t)dma_sram_buf, 200);
      delay_ms(10); 
      
      //ram--》Sdram
      for(int i=0;i<200;i++)
      {
          dma_ram_buf[i]=i+1000;
      }
      delay_ms(10);  
      HAL_DMA_Start_IT(&SdramDMA_Handler, (uint32_t)dma_ram_buf, (uint32_t)dma_sram_buf, 200);
      delay_ms(10); 
}
  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: STM32F407的FSMC(Flexible Static Memory Controller)总线应用是指将FSMC用于连接外部存储器或外设的数据交换。FSMC是一个灵活的高性能静态存储器控制器,可以与各种存储器类型和外设相连接。 STM32F407的FSMC总线应用有以下几个方面: 1. 外部存储器扩展:通过FSMC总线,可以将外部存储器,如SRAM(静态随机存储器)或 NOR Flash(并行闪存),连接到STM32F407微控制器。这样可以扩展STM32F407的存储容量,适用于需要大容量内存的应用,如图像处理、音频处理等。 2. 外设连接:FSMC还可以用于连接外部设备,如LCD液晶显示屏。通过FSMC总线,可以将STM32F407与LCD控制器相连接,实现彩色图像的实时显示。此外,FSMC还可以连接其他外设,如触摸屏控制器、摄像头模块等。 3. 并行接口:FSMC总线是一个高速的并行接口,支持多种总线协议。除了SRAM和NOR Flash之外,FSMC还可以连接其他外部存储器,如PSRAM(伪静态随机存储器)、NAND Flash(并行闪存)等。通过FSMC的并行接口,可以实现高速数据传输和存取。 4. DMA支持:FSMCSTM32F407的DMA(直接存储器访问)控制器相结合,可实现高效的数据传输。DMA可以直接从外部存储器读取数据或向外部存储器写入数据,减轻了CPU的负担,提高了数据传输的效率。 总之,STM32F407的FSMC总线应用广泛,可以连接各种外部存储器和外设,具有灵活性和高性能。它在大容量存储、图像处理、音频处理等应用中发挥着重要作用,同时通过DMA支持提供了高效的数据传输解决方案。 ### 回答2: STM32F407的FSMC(Flexible Static Memory Controller)总线可以用于处理与外部静态存储器的通信。它提供了多种接口和功能,方便与不同类型的存储器进行连接,包括SRAM、NOR Flash和PSRAM等。 在SRAM应用中,FSMC总线可以为外部SRAM提供直接访问功能。通过配置FSMC控制寄存器和时序寄存器,可以实现读取和写入SRAM中的数据。这种方式可以扩展MCU的内存空间,提高数据处理能力。 在NOR Flash应用中,FSMC总线可以实现对外部闪存的读取和写入。通过配置FSMC的控制寄存器和时序寄存器,可以设置访问闪存的时序和模式。这种方式可以用于存储嵌入式应用程序代码和数据,提高系统的运行速度和效率。 在PSRAM应用中,FSMC总线可以连接并访问外部并行存储器。通过配置FSMC的控制寄存器和时序寄存器,可以实现对PSRAM的读取和写入。这种方式可以提供高速存储器的访问能力,适用于对存储速度要求较高的应用场景。 总之,STM32F407的FSMC总线应用广泛,能够满足不同类型的外部存储器的连接和通信需求。它提供了灵活的接口和丰富的功能,可以大幅拓展内存空间,提高系统性能和效率。 ### 回答3: STM32F407的FSMC(Flexible Static Memory Controller)总线是一种用于连接外部存储器设备的接口。它提供了与静态存储器(SRAM和NOR闪存)、NAND闪存、SDRAM等设备进行高速数据传输的功能。FSMC总线的应用范围广泛,包括但不限于以下几个方面: 首先,FSMC总线可以连接静态存储器设备,例如SRAM和NOR闪存。SRAM是一种快速且易于访问的存储器,适用于对读写速度要求较高的应用场景。NOR闪存则在数据存储方面提供了非常大的存储容量,适用于嵌入式系统中的代码存储需求。 其次,FSMC总线还可以连接NAND闪存,这是一种使用较多的闪存存储设备,适用于对存储容量要求较高的应用场景。NAND闪存不仅具备较大的存储容量,还具备良好的擦除和写入性能。 另外,FSMC总线还支持连接SDRAM,这是一种用于动态存储的存储器设备。SDRAM具备较大的存储容量和高速的数据传输速度,适用于对存储容量和数据读写性能要求较高的应用场景,如图像处理、音频处理等。 总之,STM32F407的FSMC总线广泛应用于嵌入式系统中需要连接外部存储器设备的场景。通过高速、稳定的数据传输,实现了对静态存储器(SRAM和NOR闪存)、NAND闪存和SDRAM等存储设备的有效控制和访问,为嵌入式系统的数据存储和处理提供了良好的支持。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值