为什么ADC1在DMA模式下多通道 音频采集采集有干扰

他的最新文章
他的热门文章
您举报文章:
举报原因:
原文地址:
原因补充:
(最多只允许输入30个字)查看: 3949|回复: 14
库函数版ADC多通道采集的DMA问题(为何多次采集只显示第一次的结果)
主题帖子精华
新手入门, 积分 29, 距离下一级还需 -9 积分
在线时间0 小时
[C] 纯文本查看 复制代码void
ADC1_DMA_Config(void)
ADC_InitTypeDef ADC_InitS //定义ADC结构体
DMA_InitTypeDef DMA_InitS//定义DMA结构体
GPIO_InitTypeDef GPIO_InitS
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); //使能DMA1时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA |RCC_APB2Periph_ADC1, ENABLE );
//使能ADC1及GPIOA通道时钟
RCC_ADCCLKConfig(RCC_PCLK2_Div6);
//设置ADC分频因子6 72M/6=12,ADC最大时间不能超过14M
//PA2——PA6 作为5路模拟通道输入引脚
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
//模拟输入
GPIO_Init(GPIOA, &GPIO_InitStructure);
//DMA1的通道1配置
DMA_DeInit(DMA1_Channel1);
//将DMA的通道1寄存器重设为缺省值
DMA_InitStructure.DMA_PeripheralBaseAddr = ADC1_DR_A
//传输数据的源头地址
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)&ADCConvertedV
//数据存储的目标地址
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
//ADC的DMA操作(外设到内存)
DMA_InitStructure.DMA_BufferSize =5;
//DMA通道的DMA缓存的大小
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_D
//外设地址寄存器不变
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_E
//内存地址寄存器递增
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfW
//外设数据宽度为16位
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfW //内存数据宽度为16位
DMA_InitStructure.DMA_Mode =DMA_Mode_C
//工作在循环缓存模式
DMA_InitStructure.DMA_Priority = DMA_Priority_H //DMA通道1拥有高优先级
DMA_InitStructure.DMA_M2M = DMA_M2M_D
//DMA通道1没有设置为内存到内存传输
DMA_Init(DMA1_Channel1, &DMA_InitStructure);
DMA_ITConfig(DMA1_Channel1,DMA_IT_TC,ENABLE);//配置DMA1通道1传输完成中断
DMA_Cmd(DMA1_Channel1,ENABLE);//使能DMA1
ADC_DeInit(ADC1);
//复位ADC1,将外设 ADC1 的全部寄存器重设为缺省值
//ADC1的配置
ADC_InitStructure.ADC_Mode = ADC_Mode_I //ADC工作模式:ADC1和ADC2工作在独立模式
ADC_InitStructure.ADC_ScanConvMode = ENABLE; //模数转换工作在扫描模式
ADC_InitStructure.ADC_ContinuousConvMode = ENABLE; //模数转换工作在连续模式
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_N //转换由软件而不是外部触发启动
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_R //ADC数据右对齐
ADC_InitStructure.ADC_NbrOfChannel = 5; //顺序进行规则转换的ADC通道的数目
ADC_Init(ADC1, &ADC_InitStructure); //根据ADC_InitStruct中指定的参数初始化外设ADCx的寄存器
//设置每个通道的转化顺序和采样时间
ADC_RegularChannelConfig(ADC1,ADC_Channel_2, 1, ADC_SampleTime_239Cycles5 ); //ADC1通道2转换顺序为1,采样时间为239.5周期
ADC_RegularChannelConfig(ADC1,ADC_Channel_3, 2, ADC_SampleTime_239Cycles5 ); //ADC1通道3转换顺序为2,采样时间为239.5周期
ADC_RegularChannelConfig(ADC1,ADC_Channel_4, 3, ADC_SampleTime_239Cycles5 ); //ADC1通道4转换顺序为3,采样时间为239.5周期
ADC_RegularChannelConfig(ADC1,ADC_Channel_5, 4, ADC_SampleTime_239Cycles5 ); //ADC1通道5转换顺序为4,采样时间为239.5周期
ADC_RegularChannelConfig(ADC1,ADC_Channel_6, 5, ADC_SampleTime_239Cycles5 ); //ADC1通道6转换顺序为5,采样时间为239.5周期
ADC_DMACmd(ADC1,ENABLE);//使能ADC1的DMA传输方式
ADC_Cmd(ADC1, ENABLE); //使能指定的ADC1
ADC_ResetCalibration(ADC1); //重置ADC1的校准寄存器
while(ADC_GetResetCalibrationStatus(ADC1)); //获取ADC1重置校准寄存器的状态
ADC_StartCalibration(ADC1);
//开始校准ADC1
while(ADC_GetCalibrationStatus(ADC1));
//等待校准结束
ADC_SoftwareStartConvCmd(ADC1, ENABLE); //使能指定的ADC1的软件转换启动功能
[C] 纯文本查看 复制代码
[C] 纯文本查看 复制代码void ReadADCAverageValue(void)
uint8_t i,
uint32_t sum = 0;
for(i=0; i&Channel_N i++)
for(count=0; count&Sample_N count++)
sum += ADCConvertedValue[count][i];
AD_After_Filter[i]=sum/Sample_N
[C] 纯文本查看 复制代码
[C] 纯文本查看 复制代码void Display_ADC1Voltage(void)
for(i=0; i&5; i++)
adcx=AD_After_Filter[i];
LCD_ShowxNum(156,90,adcx,4,16,0);//显示ADC的值
temp=(float)adcx*(3.3/4096);
[C] 纯文本查看 复制代码}
[C] 纯文本查看 复制代码5个通道,每个通道采集10次求平均值,可是结果只有第一行有数据,相当于每个通道只采集了1次????求指点
找到问题啦~~DMA的缓存设置太小
活到老学到老~
主题帖子精华
新手入门, 积分 29, 距离下一级还需 -9 积分
在线时间0 小时
找到问题啦~~DMA的缓存设置太小
活到老学到老~
主题帖子精华
在线时间32 小时
不是第一行有数据吗?
看到您都是在固定位置显示。。。每次都刷新前面一次,那肯定只有一行的吧?
我是开源电子网?网站管理员,对网站有任何问题,请与我联系!
主题帖子精华
新手入门, 积分 29, 距离下一级还需 -9 积分
在线时间0 小时
回复【2楼】Admin:
---------------------------------
有定义数组的
#define&Channel_Num&&5
#define&Sample_Num&&10
vu16&ADCConvertedValue[Sample_Num][Channel_Num];//分别放5个AD1通道转换的数据值,每个通道采集10次求平均值
u16&AD_After_Filter[Channel_Num];
活到老学到老~
主题帖子精华
新手入门, 积分 29, 距离下一级还需 -9 积分
在线时间0 小时
回复【2楼】Admin:
---------------------------------
我的意思是这个数组&ADCConvertedValue[Sample_Num][Channel_Num]仿真的结果,只有第一行有数据,其余9行都为0
活到老学到老~
主题帖子精华
在线时间32 小时
JLINIK在线调试即可发现问题
我是开源电子网?网站管理员,对网站有任何问题,请与我联系!
主题帖子精华
在线时间206 小时
回复【6楼】蔡虹天堂:
---------------------------------
应该是50吧?
主题帖子精华
新手入门, 积分 21, 距离下一级还需 -1 积分
在线时间0 小时
回复【3楼】蔡虹天堂:
---------------------------------
楼主程序写的好啊,用二维数组来求平均,我想了好久都没想到(我才学)。
主题帖子精华
中级会员, 积分 206, 距离下一级还需 294 积分
在线时间15 小时
楼主的程序注释很清晰
主题帖子精华
新手入门, 积分 22, 距离下一级还需 -2 积分
在线时间0 小时
楼主在调用“sum&+=&ADCConvertedValue[count];”时,不需要使能并等待DMA完成么?
```
&&&&DMA_Cmd(DMA1_Channel1,&ENABLE);
&&&&while(DMA_GetFlagStatus(DMA1_FLAG_HT1)&==&RESET);&&&&
```
主题帖子精华
新手入门, 积分 39, 距离下一级还需 -19 积分
在线时间2 小时
楼主你好,我借鉴你的程序写了一个ADC+DMA的程序,结果采样的值全是零,能贴一下你主函数部分是怎么实现的吗?
IT菜鸟逆袭记~~~~
主题帖子精华
新手入门, 积分 35, 距离下一级还需 -15 积分
在线时间0 小时
回复【6楼】蔡虹天堂:
---------------------------------
棒.
主题帖子精华
新手入门, 积分 35, 距离下一级还需 -15 积分
在线时间0 小时
回复【6楼】蔡虹天堂:
---------------------------------
这个缓存大小设置,与采集的数的多少有什么关系?
主题帖子精华
新手入门, 积分 23, 距离下一级还需 -3 积分
在线时间0 小时
能否将这个整个程序&分享一下????
主题帖子精华
新手入门, 积分 18, 距离下一级还需 2 积分
在线时间1 小时
HI,你有发现相邻的ADC互相影响的问题吗?
Powered bystm32 adc多通道采集 使用dma 为什么只显示一个通道的值_百度知道
stm32 adc多通道采集 使用dma 为什么只显示一个通道的值
我有更好的答案
那么就能采集到循环数据按照顺序配置;5:
ADC_ChannelConfig(ADC1;
for(; ucnt & ADC_NUM_CNT;
uint8_t ucnt = 0;
} 这样配置就没有问题;ADC1 in continous mode4;/
}/&#47,有5处地方要注意:1、
DMA_InitStruct,adc 6通道dma采样,一开始也遇到这个问题;
ADC_ChannelConfig(ADC1, adc1_channel_gather[ucnt] , ADC_SampleTime_55_5Cycles);
/* ADC DMA request in circular mode *&#47,先配置端口→配置DMA→配置ADC→配置通道ADC_ChannelConfig()→ADC校准→允许DMA→配置循环模式 ADC_DMARequestModeConfig()→允许ADC DMA→允许ADC→启动转换ADC_StartOfConversion(ADC1) 。大体步骤就是这样;/&#47.5 Cycles as sampling time *&#47,不能够分开配置采样通道顺序和时间/&#47,设置它们的转化顺序和采样时间
/&#47, ADC_SampleTime_55_5Cycles);* Convert the ADC1
/&#47.DMA_Mode
= DMA_Mode_C循环模式2、DMA_InitS ucnt++)//发现一个STM32F051的//3;设置指定ADC的规则组通道,贴出来给遇到类似问题的朋友参考;这5个地方如果配置正确、 ADC_DMARequestModeConfig(ADC1, ADC_DMAMode_Circular)、ADC_ChannelConfig(ADC1,ADC_Channel_0|ADC_Channel_5|ADC_Channel_6|ADC_Channel_7|ADC_Channel_16|ADC_Channel_17 、ADC_InitStruct.ADC_ContinuousConvMode = ENABLE;
/&#47.DMA_MemoryInc
= DMA_MemoryInc_Enable我用的STM32F051
为您推荐:
其他类似问题
换一换
回答问题,赢新手礼包
个人、企业类
违法有害信息,请在下方选择后提交
色情、暴力
我们会通过消息、邮箱等方式尽快将举报结果通知您。STM32 ADC与DMA多通道处理
> STM32 ADC与DMA多通道处理
STM32 ADC与DMA多通道处理
#define ADC1_DR_Address ((uint32_t)0x4001244C)//ADC1 DR寄存器基地址DMA_InitTypeDef DMA_InitS //DMAADC_InitTypeDef ADC_InitS //ADC#define ADC_CH 2 //通道数#define ADC_num 10 //采集点数vu16 After_filter[ADC_CH]; //用来存放求平均值之后的结果vu16 ADCConvertedValue[ADC_num][ADC_CH];//AD数据缓存/******************************************************************************** 函数名称: DMA_Configuration(void)* 函数功能: DMA控制器 设置* 参数变量: NONE* 全局变量: NONE* 调用函数:* 修改时间:* 版 本: V1.0* 状 态: ADC1 使用DMA1通道 CH1*******************************************************************************/void DMA_Configuration(void){ RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); //使能DMA时钟 //DMA1 channel1 configuration ---------------------------------------------- DMA_DeInit(DMA1_Channel1); DMA_InitStructure.DMA_PeripheralBaseAddr = ADC1_DR_A DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)&ADCConvertedV//存放ADC数值 DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;//数据目的地址 RAM DMA_InitStructure.DMA_BufferSize =ADC_CH*ADC_//分配内部RAM DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_D//外设地址不改变 DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_E//内存地址递增 DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfW//数据宽度为16bit DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfW//数据宽度为16bit DMA_InitStructure.DMA_Mode = DMA_Mode_C//工作循环存数模式 DMA_InitStructure.DMA_Priority = DMA_Priority_H//高优先级别 DMA_InitStructure.DMA_M2M = DMA_M2M_D//数据内存到内存传送 DMA_Init(DMA1_Channel1, &DMA_InitStructure);// // Enable DMA1 channel1 DMA_Cmd(DMA1_Channel1, ENABLE);}/******************************************************************************** 函数名称: ADC_Configuration* 函数功能: ADC功能设置 使用DMA总线 通道1* 参数变量: NONE* 全局变量: NONE* 调用函数:* 修改时间:* 版 本: V1.0* 状 态:调试完成*******************************************************************************/void ADC_Configuration(void){ RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1,ENABLE); //使能ADC1 时钟 // ADC1 configuration ------------------------------------------------------ ADC_InitStructure.ADC_Mode = ADC_Mode_I//ADC1和ADC2 独立工作 ADC_InitStructure.ADC_ScanConvMode = ENABLE;//工作于多通道 ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;//工作于连续模式 ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_N//选择由软件触发 ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_R//数据右对齐 ADC_InitStructure.ADC_NbrOfChannel = ADC_CH;//N个通道 ADC_Init(ADC1, &ADC_InitStructure);// ADC1 初始化 ADC_RegularChannelConfig(ADC1, ADC_Channel_4, 1, ADC_SampleTime_239Cycles5);//GPIO.4 UA ADC_RegularChannelConfig(ADC1, ADC_Channel_5, 2, ADC_SampleTime_239Cycles5);//GPIOA.5 UB ADC_DMACmd(ADC1, ENABLE); //使能DMA ADC1 ADC_Cmd(ADC1, ENABLE);//使能 ADC1 ADC_ResetCalibration(ADC1);// 重置指定的ADC的校准寄存器 while(ADC_GetResetCalibrationStatus(ADC1)); // 等待重置指定的ADC的校准寄存器 ADC_StartCalibration(ADC1);//开始指定ADC的校准程序 while(ADC_GetCalibrationStatus(ADC1)); // Check the end of ADC1 calibration
ADC_SoftwareStartConvCmd(ADC1, ENABLE); // 使能或者失能指定的ADC的软件转换启动功能}/******************************************************************************* 函数名称: GetVolt(u16 advalue)* 函数功能: 获取ADC的值,将二进制换算为十进制* 参数变量: NONE* 全局变量: NONE* 调用函数:* 修改时间:* 修改内容:* 版 本:V1.0* 状 态:******************************************************************************/u16 GetVolt(u16 advalue){return (u16)(advalue * 330 / 4096); //求的结果扩大了100倍,方便下面求出小数}/******************************************************************************* 函数名称: void Filter(void)* 函数功能: 求平均值函数* 参数变量: NONE* 全局变量: NONE* 调用函数:* 修改时间:* 修改内容:* 版 本:V1.0* 状 态:******************************************************************************/void Filter(void){int sum = 0;u8 count,temp_i; for(temp_i=0;temp_i { for ( count=0;count { sum += ADCConvertedValue[count][temp_i]&0xFFFC; } After_filter[temp_i]=sum/ADC_ sum=0; }}/******************************************************************************* 函数名称: Data_conversion()* 函数功能: 数据量转换* 参数变量: NONE* 全局变量: NONE* 调用函数:* 修改时间:* 修改内容:* 版 本:V1.0* 状 态:******************************************************************************/void Data_conversion(){ Filter(); //取运算数据 // RT.UB= GetVolt(After_filter[0]); // RT.UA= GetVolt(After_filter[1]);}
分享给小伙伴们:
我来说两句……
最新技术贴
微信公众号二
微信公众号一STM8L致命问题!DMA读取ADC多通道,通道之间互相影响!==www.ic37.com
热门型号:
&&&当前位置:
STM8L致命问题!DMA读取ADC多通道,通道之间互相影响!
用户名:fyh123
注册时间: 0:45:00
STM8L致命问题!DMA读取ADC多通道,通道之间互相影响!
测试过程:AD同时连接了2个通道(ADC_Channel_0+ADC_Channel_Vrefint),分别测量CH0输入和内部Vref。开启DMA,使AD工作模式为ADC_ConversionMode_Continuous,则ADC_SoftwareStartConv后,自动循环依次读取这2个通道。 现象:输入CH0的值变化时,ADC_Channel_Vrefint的值也随之同方向变化---变化很大。 猜想:AD工作在Continuous模式下,内部模拟开关自动循环切换测量不同通道,通道切换后没有延时等待稳定就开始转换?导致读取各通道之间互相影响。---DMA读取AD,通道切换是自动完成,无法切换通道后的延时!不知道这个猜想是否正确,如果这样那有什么解决方案?
用户名:fyh123
注册时间: 0:45:00
////////////////////////////////////////////////////////////////
///////DMA//////////////////////////////////////////////
&&/* Enable DMA1 clock */
&&CLK_PeripheralClockConfig(CLK_Peripheral_DMA1, ENABLE);
&&/* Connect ADC to DMA channel 0 */
&&SYSCFG_REMAPDMAChannelConfig(REMAP_DMA1Channel_ADC1ToChannel0);
&&DMA_Init(DMA1_Channel0, BUFFER_ADDRESS,
& && && &&&ADC1_DR_ADDRESS,
& && && &&&BUFFER_SIZE,
& && && &&&DMA_DIR_PeripheralToMemory,
& && && &&&DMA_Mode_Circular,
& && && &&&DMA_MemoryIncMode_Inc,
& && && &&&DMA_Priority_High,
& && && &&&DMA_MemoryDataSize_HalfWord);
&&/* DMA Channel0 enable */
&&DMA_Cmd(DMA1_Channel0, ENABLE);
&&/* Enable DMA1 channel0 Transfer complete interrupt */
&&DMA_ITConfig(DMA1_Channel0, DMA_ITx_TC, ENABLE);
&&/* DMA enable */
&&DMA_GlobalCmd(ENABLE);
////////////////////////////////////////////////////////////////
///////ADC//////////////////////////////////////////////&&
&&/* Enable ADC1 clock */
&&CLK_PeripheralClockConfig(CLK_Peripheral_ADC1, ENABLE);
&&/* Initialize and configure ADC1 */
&&//工作在In continuous conversion mode, the ADC starts another conversion as soon as it finishes one
&&ADC_Init(ADC1, ADC_ConversionMode_Continuous, ADC_Resolution_12Bit, ADC_Prescaler_2);
&&ADC_SamplingTimeConfig(ADC1, ADC_Group_SlowChannels, ADC_SamplingTime_384Cycles);
&&ADC_SamplingTimeConfig(ADC1, ADC_Group_FastChannels, ADC_SamplingTime_384Cycles);
&&/* Enable ADC1 */
&&ADC_Cmd(ADC1, ENABLE);
&&/* Enable ADC1 Channels 4 */
&&ADC_ChannelCmd(ADC1, ADC_Channel_4, ENABLE); /* connected to Potentiometer RV */& &
&&ADC_ChannelCmd(ADC1, ADC_Channel_Vrefint, ENABLE);//测基准电压
&&/* Enable ADC1 DMA requests*/
&&ADC_DMACmd(ADC1, ENABLE);
&&/* Start ADC1 Conversion using TIM1 TRGO*/
&&ADC_SoftwareStartConv(ADC1);
用户名:fyh123
注册时间: 12:42:00
别沉了啊,高人们给指点下啊
用户名:fyh123
注册时间: 8:44:00
香主,能看看这个问题吗
用户名:fyh123
注册时间: 9:29:00
解决了...真想说个艹
用户名:zhangchn
注册时间: 6:55:00
怎么解决的?能分享一下吗
用户名:IJK
注册时间: 9:46:00
我猜问题多半在于LZ的代码
用户名:shexujia
注册时间: 19:49:00
答案是什么呢&&在用32的时候&&俺也有这问题
热门型号:}

我要回帖

更多关于 多通道数据采集系统 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信