You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

STM32F303K8 HAL库ADC+DMA首次读取后陷入死循环问题

问题分析与修复方案

看起来你遇到的HardFault(陷入Default_Handler死循环)是两个关键问题导致的,咱们逐个解决:

1. DMA传输长度和数组容量不匹配,触发内存越界

先看这段代码:

uint32_t adcValue1[60];
// ...
if(HAL_ADC_Start_DMA(&hadc1, (uint32_t*)adcValue1, 120) != HAL_OK)
    return 0;

你只给数组分配了60个uint32_t的存储空间,却让DMA传输120个同类型元素——DMA不会管数组边界,会直接往内存的后续区域写入数据,破坏栈内容、全局变量甚至寄存器上下文,最终触发HardFault异常跳转到默认中断处理函数。

修复方法:把DMA传输长度和数组大小对齐。比如你要存储60个采样值,就把传输参数改成60:

if(HAL_ADC_Start_DMA(&hadc1, (uint32_t*)adcValue1, 60) != HAL_OK)
    return 0;

要是确实需要120个元素,就把数组声明改成uint32_t adcValue1[120];

2. DMA中断已开启但未实现对应处理函数

你的MX_DMA_Init里开启了DMA1_Channel1的中断:

HAL_NVIC_SetPriority(DMA1_Channel1_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(DMA1_Channel1_IRQn);

但整个代码里找不到DMA1_Channel1_IRQHandler函数。当DMA触发半传输、传输完成或者错误中断时,MCU找不到对应的处理入口,就会跳转到Default_Handler死循环。

两种解决方式

  • 如果你需要用DMA中断(比如处理传输完成回调),添加这个中断处理函数,把它交给HAL库处理:
void DMA1_Channel1_IRQHandler(void)
{
  HAL_DMA_IRQHandler(&hdma_adc1);
}
  • 要是你只是用DMA循环传输,不需要中断回调,直接把中断开启的代码注释掉即可:
// HAL_NVIC_SetPriority(DMA1_Channel1_IRQn, 0, 0);
// HAL_NVIC_EnableIRQ(DMA1_Channel1_IRQn);

额外小提醒

你代码里用了sprintf((char*)buffer, ...),但没看到buffer的声明,记得提前定义一个足够大的字符数组,比如char buffer[128];,不然也可能出现内存越界问题。

按照上面的步骤修改后,应该就能正常进入while(1)循环,DMA也会持续更新ADC的采样值了。

内容的提问来源于stack exchange,提问作者Mikebebe

火山引擎 最新活动