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 BANKSDRAM_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个BANKSDRAM_Handler.Init.CASLatency=FMC_SDRAM_CAS_LATENCY_3;               //CAS为3SDRAM_Handler.Init.WriteProtection=FMC_SDRAM_WRITE_PROTECTION_DISABLE;//失能写保护SDRAM_Handler.Init.SDClockPeriod=FMC_SDRAM_CLOCK_PERIOD_2;           //SDRAM时钟为HCLK/2=180M/2=90M=11.1nsSDRAM_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=683HAL_SDRAM_ProgramRefreshRate(&SDRAM_Handler,683);//设置刷新频率}
//发送SDRAM初始化序列
void SDRAM_Initialization_Sequence(SDRAM_HandleTypeDef *hsdram)
{u32 temp=0;//SDRAM控制器初始化完成以后还需要按照如下顺序初始化SDRAMSDRAM_Send_Cmd(0,FMC_SDRAM_CMD_CLK_ENABLE,1,0); //时钟配置使能delay_us(500);                                  //至少延时200usSDRAM_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 只能用DMA2HAL_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--》ramfor(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--》Sdramfor(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--》Sdramfor(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); 
}


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部