您的DMA程序有几个关键问题
1. DMA通道配置缺失
// 必须指定DMA通道
hdma.Init.Channel = DMA_CHANNEL_0; // 取消注释并指定正确的通道
2. FMC与DMA连接问题
FMC读取需要特定的DMA通道映射,不是任意Stream都可以。
3. DMA传输完成检测缺失
没有检查传输状态或使用中断。
修正后的代码
DMA_HandleTypeDef hdma_sram;
void DMA_Config(void)
{
// 使能DMA时钟
__HAL_RCC_DMA1_CLK_ENABLE();
// 配置DMA - 使用正确的Stream和Channel
hdma_sram.Instance = DMA1_Stream0; // 检查数据手册确认这个Stream是否支持FMC
hdma_sram.Init.Channel = DMA_CHANNEL_0; // 必须指定通道
hdma_sram.Init.Direction = DMA_PERIPH_TO_MEMORY; // 从外设(FMC)到内存
hdma_sram.Init.PeriphInc = DMA_PINC_DISABLE; // 外设地址不递增(FMC固定地址)
hdma_sram.Init.MemInc = DMA_MINC_ENABLE; // 内存地址递增
hdma_sram.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD; // 16位对齐
hdma_sram.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD; // 16位对齐
hdma_sram.Init.Mode = DMA_NORMAL; // 普通模式
hdma_sram.Init.Priority = DMA_PRIORITY_HIGH; // 高优先级
hdma_sram.Init.FIFOMode = DMA_FIFOMODE_DISABLE; // 禁用FIFO
hdma_sram.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL;
hdma_sram.Init.MemBurst = DMA_MBURST_SINGLE; // 单次传输
hdma_sram.Init.PeriphBurst = DMA_PBURST_SINGLE; // 单次传输
if (HAL_DMA_Init(&hdma_sram) != HAL_OK) {
Error_Handler();
}
}
// 更可靠的DMA传输函数
HAL_StatusTypeDef DMA_Transfer(uint32_t srcAddr, uint32_t destAddr, uint16_t dataSize)
{
HAL_StatusTypeDef status;
// 停止之前的传输(如果有)
HAL_DMA_Abort(&hdma_sram);
// 启动DMA传输
status = HAL_DMA_Start(&hdma_sram, srcAddr, destAddr, dataSize);
if (status != HAL_OK) {
return status;
}
// 等待传输完成,设置超时时间
status = HAL_DMA_PollForTransfer(&hdma_sram, HAL_DMA_FULL_TRANSFER, 1000);
return status;
}
// 在FMC初始化后关联DMA
void FMC_LinkDMA(void)
{
// 将DMA与SRAM句柄关联
__HAL_LINKDMA(&hsram1, hdma, hdma_sram);
}
|