OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 10355|回复: 18

STM32F446 ADC DMA模式下 经常OVR(数据溢出),导致ADC不工作

[复制链接]

15

主题

51

帖子

0

精华

初级会员

Rank: 2

积分
52
金钱
52
注册时间
2017-9-9
在线时间
36 小时
发表于 2017-11-8 21:57:47 | 显示全部楼层 |阅读模式
5金钱
如题:STM32F446  ADC DMA模式下  经常OVR(数据溢出),导致ADC不工作。芯片STM32F446  ,系统时钟配置成168M,ADC为21M, 用PB0口进行ADC采样,软件触发方式,用DMA将采样数据存储在一个数组中。

程序跑着跑着ADC就停止工作,发现ADC_SR寄存器的OVR置为1,经过检查,也没查出有啥问题,请大神帮忙看看:
1、ADC配置如下
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);
ADC_DeInit();
ADC_CommonInitStructure.ADC_Mode = ADC_Mode_Independent;
ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_5Cycles;
ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled;
ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div4;//
ADC_CommonInit(&ADC_CommonInitStructure);

ADC_InitStructure.ADC_Resolution = ADC_Resolution_8b;
ADC_InitStructure.ADC_ScanConvMode = DISABLE;   
ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;
ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;  
ADC_InitStructure.ADC_NbrOfConversion = 1;

ADC_Init(ADC1, &ADC_InitStructure);
ADC_RegularChannelConfig(ADC1,ADC_Channel_8, 1, ADC_SampleTime_3Cycles);//ADC12_IN_8

    /* Enable DMA request after last transfer (Single-ADC mode) */
ADC_DMARequestAfterLastTransferCmd(ADC1, ENABLE);
    /* Enable ADC1 DMA */
ADC_DMACmd(ADC1, ENABLE);
ADC_Cmd(ADC1, ENABLE);

2、DMA配置如下
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE);
  DMA_InitStructure.DMA_Channel = DMA_Channel_0;  
  DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)&(ADC1->DR);
  DMA_InitStructure.DMA_Memory0BaseAddr = (u32)addr;
  DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;
  DMA_InitStructure.DMA_BufferSize = len;
  DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
  DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
  DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
  DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
  DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
  DMA_InitStructure.DMA_Priority = DMA_Priority_High;
  DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;         
  DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;
  DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
  DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
  DMA_Init(DMA2_Stream0, &DMA_InitStructure);
  DMA_Cmd(DMA2_Stream0, ENABLE);
  DMA_ITConfig(DMA2_Stream0, DMA_IT_TC, DISABLE);




最佳答案

查看完整内容[请看2#楼]

我用定时器定时读取DMA传出来的ADC的值,发现ADC采样的模拟数值是对的,但是通道不对,比如PA0输入1.5V,而读出的确是PA1为1.5V,即DMA传输出错了。修改方法,此时先DMA_DeInit(DMAy_Streamx); 重新初始化ADC; 之后再读数据就正常了。 补充内容 (2018-7-6 18:39): 在读取DMA数据时,先检测是否DMA传输完成没,if(SET == DMA_GetFlagStatus(DMA2_Stream0,DMA_FLAG_TCIF0)),等待传输完成后再读取,就不会出现,通道不对应的问题。
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

2

主题

6

帖子

0

精华

初级会员

Rank: 2

积分
75
金钱
75
注册时间
2017-11-23
在线时间
10 小时
发表于 2017-11-8 21:57:48 | 显示全部楼层
我用定时器定时读取DMA传出来的ADC的值,发现ADC采样的模拟数值是对的,但是通道不对,比如PA0输入1.5V,而读出的确是PA1为1.5V,即DMA传输出错了。修改方法,此时先DMA_DeInit(DMAy_Streamx); 重新初始化ADC; 之后再读数据就正常了。

补充内容 (2018-7-6 18:39):
在读取DMA数据时,先检测是否DMA传输完成没,if(SET == DMA_GetFlagStatus(DMA2_Stream0,DMA_FLAG_TCIF0)),等待传输完成后再读取,就不会出现,通道不对应的问题。
回复

使用道具 举报

15

主题

51

帖子

0

精华

初级会员

Rank: 2

积分
52
金钱
52
注册时间
2017-9-9
在线时间
36 小时
 楼主| 发表于 2017-11-8 23:27:45 | 显示全部楼层
回复

使用道具 举报

15

主题

51

帖子

0

精华

初级会员

Rank: 2

积分
52
金钱
52
注册时间
2017-9-9
在线时间
36 小时
 楼主| 发表于 2017-11-9 10:52:15 | 显示全部楼层
顶一下
回复

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165508
金钱
165508
注册时间
2010-12-1
在线时间
2115 小时
发表于 2017-11-10 01:18:00 | 显示全部楼层
帮顶
回复

使用道具 举报

19

主题

110

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
257
金钱
257
注册时间
2017-8-2
在线时间
46 小时
发表于 2017-11-14 16:34:59 | 显示全部楼层
我也遇到这个问题,我看资料里说溢出了就清溢出标志,然后重新初始化ADC和DMA.我这样做了,然后可以运行了。但是后面我加上定时器,本来ADC还在初始化,总是又跳进定时器了。我的定时器就是用来定时读取DMA传出来的ADC的值。
回复

使用道具 举报

19

主题

110

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
257
金钱
257
注册时间
2017-8-2
在线时间
46 小时
发表于 2017-11-14 16:50:18 | 显示全部楼层
尽管如此,如果数据丢失(溢出),则会将 ADC_SR 寄存器中的 OVR 位置 1 并生成一个中      
断(如果 OVRIE 使能位已置 1)。随后会禁止 DMA 传输并且不再接受 DMA 请求。在这种      
情况下,如果生成 DMA 请求,则会中止正在进行的规则转换并忽略之后的规则触发。随后  
需要将所使用的 DMA 流中的 OVR 标志和 DMAEN 位清零,并重新初始化 DMA 和 ADC,         
以将需要的转换通道数据传输到正确的存储器单元。只有这样,才能恢复转换并再次使能数
据传输。注入通道转换不会受到溢出错误的影响。
回复

使用道具 举报

19

主题

110

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
257
金钱
257
注册时间
2017-8-2
在线时间
46 小时
发表于 2017-11-14 16:53:15 | 显示全部楼层
要在使用 DMA 时将 ADC 从 OVR 状态中恢复,请按以下步骤操作:
1. 重新初始化 DMA(调整目标地址和 NDTR 计数器)
2.  将 ADC_SR 寄存器中的 ADC OVR 位清零
3.  触发 ADC 以开始转换。
回复

使用道具 举报

19

主题

110

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
257
金钱
257
注册时间
2017-8-2
在线时间
46 小时
发表于 2017-11-15 14:24:35 | 显示全部楼层
本帖最后由 Bunny17 于 2017-11-15 14:25 编辑

另外还要设置  ADC1->CR2|=1<<9;   才正确
位 9   DDS:DMA 禁止选择(对于单一 ADC 模式) (DMA disable selection (for single ADC mode))
此位由软件置 1 和清零。
0:最后一次传输后不发出新的 DMA 请求(在 DMA 控制器中进行配置)
1:只要发生数据转换且 DMA = 1,便会发出 DAM 请求

回复

使用道具 举报

19

主题

110

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
257
金钱
257
注册时间
2017-8-2
在线时间
46 小时
发表于 2017-11-16 09:54:53 | 显示全部楼层
我后来发现是我的DMA没有开启循环模式,导致ADC溢出,不知道你的是不是
回复

使用道具 举报

15

主题

51

帖子

0

精华

初级会员

Rank: 2

积分
52
金钱
52
注册时间
2017-9-9
在线时间
36 小时
 楼主| 发表于 2017-11-16 22:50:34 | 显示全部楼层
Bunny17 发表于 2017-11-16 09:54
我后来发现是我的DMA没有开启循环模式,导致ADC溢出,不知道你的是不是

你好,最近没上线,我的DMA开启循环模式了啊,感觉配置的也没什么错,为啥这么容易溢出了呢,溢出后数据就断了,对于我的程序处理来说相当麻烦,数据得从头再开始采样。
回复

使用道具 举报

6

主题

36

帖子

0

精华

初级会员

Rank: 2

积分
84
金钱
84
注册时间
2017-8-23
在线时间
34 小时
发表于 2017-11-17 11:33:53 | 显示全部楼层
miraclexue 发表于 2017-11-16 22:50
你好,最近没上线,我的DMA开启循环模式了啊,感觉配置的也没什么错,为啥这么容易溢出了呢,溢出后数据 ...

DMA开启双缓冲模式呢?
回复

使用道具 举报

19

主题

110

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
257
金钱
257
注册时间
2017-8-2
在线时间
46 小时
发表于 2017-11-25 11:16:06 | 显示全部楼层
miraclexue 发表于 2017-11-16 22:50
你好,最近没上线,我的DMA开启循环模式了啊,感觉配置的也没什么错,为啥这么容易溢出了呢,溢出后数据 ...

解决了吗
回复

使用道具 举报

15

主题

51

帖子

0

精华

初级会员

Rank: 2

积分
52
金钱
52
注册时间
2017-9-9
在线时间
36 小时
 楼主| 发表于 2017-12-5 12:14:46 | 显示全部楼层

每次初始化都要加DMA_DeInit(DMAy_Streamx);
回复

使用道具 举报

19

主题

110

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
257
金钱
257
注册时间
2017-8-2
在线时间
46 小时
发表于 2017-12-7 13:27:04 | 显示全部楼层
miraclexue 发表于 2017-12-5 12:14
每次初始化都要加DMA_DeInit(DMAy_Streamx);

我的是开启的DMA中断解决的。ADC循环采集,DMA传输完成就中断处理一次数据
回复

使用道具 举报

1

主题

8

帖子

0

精华

初级会员

Rank: 2

积分
117
金钱
117
注册时间
2016-1-15
在线时间
23 小时
发表于 2018-9-6 09:42:15 | 显示全部楼层
这个帖子好久了,我还是想问下。 我目前采用 ADC 三重模式,在初始化完 ADC和 DMA后使用 HAL_ADCEx_MultiModeStart_DMA()使能DMA传输和启动ADC后,OVR立即会==1,不知道为什么?按理来说这时候ADC应该还是没有开始工作呀 ?

/* Enable the DMA Stream */
    HAL_DMA_Start_IT(hadc->DMA_Handle, (uint32_t)&ADC->CDR, (uint32_t)pData, Length);
   
    /* if no external trigger present enable software conversion of regular channels */
    if((hadc->Instance->CR2 & ADC_CR2_EXTEN) == RESET)
    {
      /* Enable the selected ADC software conversion for regular group */
      hadc->Instance->CR2 |= (uint32_t)ADC_CR2_SWSTART;
    }

这是 HAL_ADCEx_MultiModeStart_DMA()会执行的一段 。
回复

使用道具 举报

0

主题

4

帖子

0

精华

新手入门

积分
15
金钱
15
注册时间
2019-6-17
在线时间
5 小时
发表于 2019-8-12 18:03:29 | 显示全部楼层
stm32f4 系统时钟配置成168M, 三重ADC交替采样同一通道,ADC为21M, 用PC0口进行ADC采样,软件触发方式,MDA双缓存模式传输数据,经常OVR(数据溢出),溢出后按照手册恢复ADC和dma,同时记录溢出次数,发现平均40s溢出一次。
是ADC本来就容易溢出还是配置错了,搞不清楚,大家大概多久溢出一次?
回复

使用道具 举报

0

主题

4

帖子

0

精华

新手入门

积分
15
金钱
15
注册时间
2019-6-17
在线时间
5 小时
发表于 2019-8-15 12:01:02 | 显示全部楼层
力拔山兮 发表于 2019-8-12 18:03
stm32f4 系统时钟配置成168M, 三重ADC交替采样同一通道,ADC为21M, 用PC0口进行ADC采样,软件触发方式,M ...

不断溢出的问题已经解决,是ADC_CR2寄存器的DMA位置1了。这一位是给单一模式用的,我是用的三重模式,按道理说这一位应该无效才对,但是经过反复试验,确实是此位导致不断溢出。
//****************************************************************************************
但是还有新问题,三重ADC采样3.3v的电源是正确的,但是DAC输出的3.3v采样有问题,表现形式为DAC带负载能力不强。DAC通道输出缓冲器(BOFF)使能后,ADC采样结果有改善。由于没有电压表,不知道是ADC设置有问题,还是DAC有问题。
回复

使用道具 举报

0

主题

4

帖子

0

精华

新手入门

积分
15
金钱
15
注册时间
2019-6-17
在线时间
5 小时
发表于 2019-8-27 17:48:59 | 显示全部楼层
力拔山兮 发表于 2019-8-15 12:01
不断溢出的问题已经解决,是ADC_CR2寄存器的DMA位置1了。这一位是给单一模式用的,我是用的三重模式,按 ...

问题已经解决,是因为开发板上的AD引脚有别的负载,把电压拉低了。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-5-16 06:45

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表