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




