19_CubeMX初始化顺序错误导致DMA读取ADC失败

CubeMX 配置使用DMA读取regular ADC数据

选择ADC通道
在这里插入图片描述
添加DMA请求。配置Priority为High,配置Mode为Circular循环执行DMA,Memory地址自增,相应的数据宽度(ADC 最多12bit,Half Word 16bit够用)

在这里插入图片描述
使能Scan Conversion Mode,扫描每个regular ADC通道

使能DMA Continuous Requests,在每个regular ADC通道转换完成后,都发起DMA请求
在这里插入图片描述
配置ADC regular ADC。包含2个转换,分别对应Channel1和Channel2,我这里使用HRTimer Trigger Out 1 event外部regular触发ADC转换
在这里插入图片描述

CubeMX 生成初始化代码可能错误

在MX_ADC1_Init()中包含DMA初始化

MX_DMA_Init()中包含DMA时钟使能和DMA中断配置

CubeMX可能生成初始化代码顺序如下:

/*ADC和DMA初始化*/
MX_ADC1_Init();
/*DMA时钟使能和DMA中断配置*/
MX_DMA_Init();

DMA初始化过程在DMA时钟使能前,导致DMA初始化失败!!!

具体失败现象为:

  • ADC数据读取错误,并且产生overrun标志位
  • DMA中断只能在一开始时进入,后续不再触发DMA中断
  • MX_ADC1_Init()函数中,不能写入DMA CCR寄存器(hdma->Instance->CCR = tmp)
 /*以下均在MX_ADC1_Init()内*/
/* Get the CR register value */
  tmp = hdma->Instance->CCR;
  
  /* Clear PL, MSIZE, PSIZE, MINC, PINC, CIRC, DIR bits */
  tmp &= ((uint32_t)~(DMA_CCR_PL    | DMA_CCR_MSIZE  | DMA_CCR_PSIZE  | \
                      DMA_CCR_MINC  | DMA_CCR_PINC   | DMA_CCR_CIRC   | \
                      DMA_CCR_DIR));
  
  /* Prepare the DMA Channel configuration */
  tmp |=  hdma->Init.Direction        |
          hdma->Init.PeriphInc           | hdma->Init.MemInc           |
          hdma->Init.PeriphDataAlignment | hdma->Init.MemDataAlignment |
          hdma->Init.Mode                | hdma->Init.Priority;

  /* Write to DMA Channel CR register */
  hdma->Instance->CCR = tmp;  /*由于DMA时钟尚未使能,所以执行完该语句并不能在CCR内写入值*/

解决

检查问题所在功能的时钟使能和初始化顺序

尤其功能间具有依赖关系时,很可能其一功能的使能和初始化没在同一个函数内,可能CubeMX把初始化错误的放在使能前面

结语

当时用CubeMX生成了两个工程,明明配置都一样,其中一个工程运行时很正常,另一个一直读不出ADC数据。
费解,连Beyond Compare都用上了,痛苦面具😭。
最后Debug模式下查看DMA、ADC的寄存器值变化,才找到这个顺序的问题。

  • 3
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
在使用STM32F103芯片进行DMA中断读取ADC的程序中,首先需要初始化ADCDMA初始化ADC时,需要设置ADC的通道、采样周期和转换模式。通道用于选择ADC输入的通道,采样周期用于设置ADC的转换速率,转换模式用于选择ADC的工作模式。 初始化DMA时,需要设置DMA的通道、传输方向、数据宽度和传输数量。通道用于选择DMA传输使用的通道,传输方向用于设置数据的传输方向(从ADC读取还是向其他外设写入),数据宽度用于设置每次传输的数据宽度(比如8位或12位),传输数量用于设置传输的次数。 接下来,需要配置DMA中断,通过DMA中断来触发数据的读取和处理。配置DMA中断需要设置中断触发源和优先级。中断触发源可以选择DMA传输完成或者半传输完成来触发中断,优先级可以用于设置中断的执行顺序。 在程序中,可以通过编写中断服务函数来处理DMA中断。中断服务函数中可以读取ADC数据并进行相应的处理,比如存储数据、计算平均值或者发送到其他外设。 最后,需要在主函数中使能ADCDMA和中断,并且进入主循环以保持程序运行。在主循环中可以执行其他任务,并定期检查ADCDMA状态以确保数据传输正常。 总结起来,实现STM32F103芯片的DMA中断读取ADC程序需要进行ADCDMA初始化配置,编写中断服务函数来处理数据读取和处理,并在主函数中使能相关模块并进入主循环。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值