ADC-dma死循环问题

方法一

在这里插入图片描述
在这里插入图片描述
初始化dma时候,里面会先使能dma,然后打开相应的中断,然后结果会导致main函数中卡死
在这里插入图片描述
卡在箭头处,也就是打不开adc和dma

解决方案

全部注释,只留第一个配置dma的函数
在这里插入图片描述
11.16:
补充:同样的现象:程序卡死在HAL_ADC_Start_DMA这个函数里面,下面程序无法运行,但是数组里面一直会接收到数据。

出去上文提到的解决方法外,

还有解决方法2:

在这里插入图片描述
dma初始化一定要在adc初始化之前,否则死循环

解决方法3:

注意缓存的大小
在这里插入图片描述
在这里插入图片描述
内存的缓存区必须是16位的(具体原因不详,实测就是这样,如果改成32位的就是会死循环,原因不详)

cubmax配置图:

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

总结:

adc和dma一起用的时候,经常会遇到程序卡死的问题(笔者身边的人也经常遇到这类问题),以上三种解决方案一般能处理死循环的问题,如果有新的情况后续会再补充。

个人的想法:

综合上文三种解决方法可以得知,这类问题大多和dma有关,所以我猜测大概率是dma中断和adc中断冲突导致的,第一种解决方法是直接把dma中断注释了,第三种则是吧dma中断优先级调到最高。

前几天参加电赛的过程中用到adc和dma时候遇到这个问题,配置代码配置了很久,一直死循环,这几天翻博客时候发现以前遇到过这种问题,并且还整理了文章,而且我居然一点映像都没有,电赛那几天找到了后面两种解决方法,并且对这篇文章作出补充。

### 28377D ADC DMA 配置与编程 对于28377D微控制器中的ADC模块,当其与DMA配合工作时,能够高效地处理大量数据采集任务。通过设置合适的寄存器参数并编写相应的驱动程序代码,可确保AD转换过程顺利执行,并自动将结果存储到指定内存区域。 #### 初始化配置 为了使能ADC-DMA功能,在初始化阶段需完成如下操作: - **开启外设时钟**:确保为ADCDMA提供必要的电源管理支持。 - **配置GPIO引脚作为模拟输入端口**:根据实际需求选择对应的物理管脚连接传感器或其他信号源。 - **设定ADC分辨率及时序参数**:调整采样时间和量化精度以满足应用要求。 - **启动DMA请求映射至特定通道**:指明哪个DMA流负责搬运来自ADC的数据包。 ```c // 假定已定义好结构体变量用于保存配置项 ADC_InitTypeDef adc_init; DMA_InitTypeDef dma_init; RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE); RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); GPIO_InitTypeDef gpio_init; gpio_init.GPIO_Pin = GPIO_Pin_0; // AIN0 gpio_init.GPIO_Mode = GPIO_Mode_AIN; GPIO_Init(GPIOA, &gpio_init); adc_init.ADC_Mode = ADC_Mode_Independent; adc_init.ADC_ScanConvMode = DISABLE; adc_init.ADC_ContinuousConvMode = ENABLE; adc_init.ADC_DataAlign = ADC_DataAlign_Right; adc_init.ADC_NbrOfChannel = 1; ADC_Init(ADC1, &adc_init); dma_init.DMA_PeripheralBaseAddr = (uint32_t)&(ADC1->DR); dma_init.DMA_MemoryBaseAddr = (uint32_t)buffer_address; dma_init.DMA_DIR = DMA_DIR_PeripheralSRC; dma_init.DMA_BufferSize = BUFFER_SIZE; dma_init.DMA_PeripheralInc = DMA_PeripheralInc_Disable; dma_init.DMA_MemoryInc = DMA_MemoryInc_Enable; dma_init.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; dma_init.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord; dma_init.DMA_Mode = DMA_Mode_Circular; dma_init.DMA_Priority = DMA_Priority_VeryHigh; DMA_Init(DMA1_Channel1, &dma_init); ``` #### 开始转换与传输 一旦上述准备工作就绪,则可通过简单的API调用来触发整个流程: ```c ADC_DMACmd(ADC1, ENABLE); /* 启用ADCDMA模式 */ DMA_Cmd(DMA1_Channel1, ENABLE); /* 激活选定的DMA通道 */ ADC_SoftwareStartConvCmd(ADC1, ENABLE);/* 手动发起一次完整的扫描序列 */ ``` 以上步骤完成后,每当ADC完成一轮测量后就会自动生成中断事件通知DMA引擎去获取最新数值并将其写入预分配好的缓冲区内[^1]。 #### 故障排查指南 如果遇到任何异常情况或性能瓶颈,建议按照以下几点来进行诊断分析: - 确认所有硬件连线无误,特别是涉及外部设备接口部分; - 使用调试工具(如逻辑分析仪)监测总线活动状况以及各组件的工作状态; - 审查固件设计是否存在潜在缺陷,例如未正确清除标志位导致死循环问题- 尝试降低系统负载来观察是否有改善迹象;
评论 13
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值