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的寄存器值变化,才找到这个顺序的问题。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值