OpenEdv-开源电子网

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

STM32 ADC 两个通道 DMA传输问题

[复制链接]

2

主题

4

帖子

0

精华

新手入门

积分
32
金钱
32
注册时间
2011-6-12
在线时间
0 小时
发表于 2011-8-29 02:43:54 | 显示全部楼层 |阅读模式
 现在单个通道可以工作 并且数据正确

两个通道就有一个问题 
unsigned int volatile ADC_Value[2];这是设置转换结果
DMA_InitStructure.DMA_BufferSize =1; 开放DMA  1个缓冲区
仿真下 ADC两个通道的数据怎么都存放在ADC_Value[0]中 
而且还是不规则的存放顺序

DMA_BufferSize需要设置多大才能读取到ADC两个通道的数据 分别存放到ADC_Value[0] ADC_Value[1] 中 

现在发现ADC_Value[1]中没有数据为0  
而ADC_Value[0]有数据 每次读取都会有数据 而且 数据不是规则变化的 
比方说第一次读取 4095-3.3V的值 
     第二次读取 1703-35C的温度值 
     第三次读取可能是 4095 可能是 1703 
两个通道的数据不是同时分布到ADC_Value[0] ADC_Value[1] 中 吗??

DMA_InitStructure.DMA_BufferSize 这个参数需要设置多少才能正确的读取两个通道数据 在ADC_Value[0] ADC_Value[1]中 

ADC初始化是设置好了两个通道 仿真数据也是正确的 怎么都存放到ADC_Value[0] 中去了

我的理解:DMA_BufferSize应该开放2个空间 一个是channel 1通道 采集电压 一个是channel 16内部温度的 
            主函数读取一次数据的时候 DMA把  channel 1 channel 16 的数据分别存储放到ADC_Value[0] ADC_Value[1] 中
         而现在仿真 好像是 每次读取一次数据 只有一个通道的数据存储到ADC_Value[0]中,第一次读取可能是电压的 第二次可能是 温度的 第三次可能是电压可能是温度的 
        DMA_BufferSize 需要设置多大才能把两个通道的数据一次存储到ADC_Value[0] ADC_Value[1] 中去
 求大侠回答下 郁闷了一天了,
期待懂的人回答下好吗!!!!!!!!原子哥 求救啊。。。。。。。。
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165540
金钱
165540
注册时间
2010-12-1
在线时间
2117 小时
发表于 2011-8-29 08:40:52 | 显示全部楼层
回复【楼主位】zhanmcu:
---------------------------------
很明显需要size=2.
而且你的adc必须是同一个adc的两个通道.
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

2

主题

4

帖子

0

精华

新手入门

积分
32
金钱
32
注册时间
2011-6-12
在线时间
0 小时
 楼主| 发表于 2011-8-29 21:08:08 | 显示全部楼层
回复【2楼】正点原子:
----------------------------
是的  我的数据已经出来了, 但是每次读取数据 两个通道的结果放到ADC_Value[0]中,并不是分布到两个缓冲里面,
而且读取数据都是正确的! 

是不是跟ADC工作模式 独立模式啊 扫描啊,连续采样有关系!!!
回复 支持 反对

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165540
金钱
165540
注册时间
2010-12-1
在线时间
2117 小时
发表于 2011-8-30 00:39:55 | 显示全部楼层
回复【3楼】zhanmcu:
---------------------------------
应该是扫描模式的.
另外你的unsigned int,改为unsigned short.试试.
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

7

主题

49

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
441
金钱
441
注册时间
2013-1-3
在线时间
89 小时
发表于 2013-12-31 14:01:44 | 显示全部楼层
回复【2楼】正点原子:
---------------------------------
原子哥,我现在也在搞ADC采集两路模拟电压通过DMA传输,一直不明白DMA是怎么把ADC每通道的数据进行传输的。
ADC->DR只有一个也就是说DMA的基地址是一个,DMA是怎么把这两个通道的数据进行一一传输,我想要的效果是DMA把第一个通道的数据放在AD_Value[0],第二个通道数据放在AD_Value[1]中。 DMA_BufferSize的具体意思是什么,在内存中是什么样子的。谢了!
回复 支持 反对

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165540
金钱
165540
注册时间
2010-12-1
在线时间
2117 小时
发表于 2013-12-31 23:23:47 | 显示全部楼层
回复【5楼】zhuwenfly:
---------------------------------
这你得好好看看《STM32参考手册》DMA章节了。有详细讲解。
简单讲,DMA就是个搬运工,会在触发信号的控制下,不停的从某个地方搬运数据到另外一个地方。
DMA_BufferSize,就是指DMA此次要传输的数据量。比如我要传输10个数据,那么DMA_BufferSize就设置为10.
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

5

主题

22

帖子

0

精华

初级会员

Rank: 2

积分
67
金钱
67
注册时间
2014-3-1
在线时间
1 小时
发表于 2014-3-1 17:27:46 | 显示全部楼层
回复【4楼】正点原子:
---------------------------------
原子哥:问下STM32AD采集不用DMA用多通道单次采集怎么发现数据很乱,求解。
代码如下:void  Adc_Init(void)

ADC_InitTypeDef ADC_InitStructure; 
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA |RCC_APB2Periph_ADC1 , ENABLE );   //使能ADC1通道时钟
 
RCC_ADCCLKConfig(RCC_PCLK2_Div6);   //72M/6=12,ADC最大时间不能超过14M
//PA0/1/2/3 作为模拟通道输入引脚                         
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; //模拟输入引脚
GPIO_Init(GPIOA, &GPIO_InitStructure);

ADC_DeInit(ADC1);  //将外设 ADC1 的全部寄存器重设为缺省值

ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; //ADC工作模式:ADC1和ADC2工作在独立模式
ADC_InitStructure.ADC_ScanConvMode = ENABLE; //模数转换工作在单通道模式
ADC_InitStructure.ADC_ContinuousConvMode = ENABLE; //模数转换工作在单次转换模式
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; //转换由软件而不是外部触发启动
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; //ADC数据右对齐
ADC_InitStructure.ADC_NbrOfChannel = 4; //顺序进行规则转换的ADC通道的数目
ADC_Init(ADC1, &ADC_InitStructure); //根据ADC_InitStruct中指定的参数初始化外设ADCx的寄存器   
 
ADC_RegularChannelConfig(ADC1, ADC_Channel_0, 1, ADC_SampleTime_239Cycles5 ); //ADC1,ADC通道3,规则采样顺序值为1,采样时间为239.5周期        
    ADC_RegularChannelConfig(ADC1, ADC_Channel_1, 2, ADC_SampleTime_239Cycles5 );
    ADC_RegularChannelConfig(ADC1, ADC_Channel_2, 3, ADC_SampleTime_239Cycles5 );
ADC_RegularChannelConfig(ADC1, ADC_Channel_3, 4, ADC_SampleTime_239Cycles5 );

ADC_Cmd(ADC1, ENABLE); //使能指定的ADC1

ADC_ResetCalibration(ADC1); //重置指定的ADC1的校准寄存器
 
while(ADC_GetResetCalibrationStatus(ADC1)); //获取ADC1重置校准寄存器的状态,设置状态则等待

ADC_StartCalibration(ADC1); //开始指定ADC1的校准状态
 
while(ADC_GetCalibrationStatus(ADC1)); //获取指定ADC1的校准程序,设置状态则等待
 
//ADC_SoftwareStartConvCmd(ADC1, ENABLE); //使能指定的ADC1的软件转换启动功能

}

u16 ADC_CONVER(void)
{
   
    ADC_SoftwareStartConvCmd(ADC1, ENABLE); //使能指定的ADC1的软件转换启动功能
 
while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC ));//等待转换结束

return ADC_GetConversionValue(ADC1); //返回最近一次ADC1规则组的转换结果
}




然后再main函数调用:
int main(void)
 {
u16 adcx;
float temp;
SystemInit();
delay_init(72);      //延时初始化
NVIC_Configuration();
  uart_init(9600);
  LED_Init();
  KEY_Init();
LCD_Init();
Adc_Init();
POINT_COLOR=RED;//设置字体为红色 
LCD_ShowString(60,50,"Mini STM32");
LCD_ShowString(60,70,"ADC TEST");
LCD_ShowString(60,90,"ATOM@ALIENTEK");
LCD_ShowString(60,110,"2010/12/30");
//显示提示信息
POINT_COLOR=BLUE;//设置字体为蓝色
LCD_ShowString(60,130,"ADC_CH0_VAL:");       
LCD_ShowString(60,150,"ADC_CH0_VOL:0.000V");       
while(1)
{
    adcx=ADC_CONVER();
LCD_ShowNum(156,130,adcx,4,16);//显示ADC的值
temp=(float)adcx*(3.3/4096);
adcx=temp;
LCD_ShowNum(156,150,adcx,1,16);//显示电压值
temp-=adcx;
temp*=1000;
LCD_ShowNum(172,150,temp,3,16);
LED0=!LED0;
delay_ms(1000);

}

 }

发现数据不是先PA0,PA1,PA2,PA3的AD值,第一个是PA3的,其它的有点紊乱。
怎么回事,谢谢大哥与各位朋友。
回复 支持 反对

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165540
金钱
165540
注册时间
2010-12-1
在线时间
2117 小时
发表于 2014-3-1 22:01:36 | 显示全部楼层
回复【7楼】小小飞行器:
---------------------------------
没这么用过,你还不如用我们例程提供的方式,去做。要哪个通道,给哪个通道。
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

5

主题

22

帖子

0

精华

初级会员

Rank: 2

积分
67
金钱
67
注册时间
2014-3-1
在线时间
1 小时
发表于 2014-3-1 22:12:33 | 显示全部楼层
回复【8楼】正点原子:
---------------------------------
OK
回复 支持 反对

使用道具 举报

7

主题

31

帖子

0

精华

初级会员

Rank: 2

积分
79
金钱
79
注册时间
2014-7-12
在线时间
0 小时
发表于 2014-8-1 17:11:30 | 显示全部楼层
回复【8楼】正点原子:
---------------------------------
原子哥,请问所给的ADC例程里那个Get_Adc()函数是可以任意读取ADC1的通道0~3的AD值吗?
回复 支持 反对

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165540
金钱
165540
注册时间
2010-12-1
在线时间
2117 小时
发表于 2014-8-2 00:37:04 | 显示全部楼层
回复【10楼】beiker:
---------------------------------
我们例程只初始化了0~3,就只能读0~3,如果你还要读其他的,相应的你得对这些通道进行初始化。
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

7

主题

31

帖子

0

精华

初级会员

Rank: 2

积分
79
金钱
79
注册时间
2014-7-12
在线时间
0 小时
发表于 2014-8-5 18:12:37 | 显示全部楼层
回复【11楼】正点原子:
---------------------------------
就是说我可以即读通道0同时又可以读通道1?是这个意思不?
回复 支持 反对

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165540
金钱
165540
注册时间
2010-12-1
在线时间
2117 小时
发表于 2014-8-5 23:04:31 | 显示全部楼层
回复【12楼】beiker:
---------------------------------
有2个ADC,就可以。
如果一个adc的2个通道,就只能分时读。
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

7

主题

31

帖子

0

精华

初级会员

Rank: 2

积分
79
金钱
79
注册时间
2014-7-12
在线时间
0 小时
发表于 2014-8-10 21:57:31 | 显示全部楼层
回复【13楼】正点原子:
---------------------------------
了解了,谢谢原子哥!
回复 支持 反对

使用道具 举报

1

主题

7

帖子

0

精华

初级会员

Rank: 2

积分
63
金钱
63
注册时间
2014-6-18
在线时间
8 小时
发表于 2015-3-25 14:17:11 | 显示全部楼层
如果模块1正在使用DMA,而模块2请求DMA,那么这时候DMA会停止模块1的工作而响应模块2的请求吗?
回复 支持 反对

使用道具 举报

2

主题

10

帖子

0

精华

新手上路

积分
38
金钱
38
注册时间
2014-10-10
在线时间
0 小时
发表于 2015-4-13 09:47:21 | 显示全部楼层
我现在也有同样的问题,但是我的DMA设置的是2个空间,但是数据全部跑到AD_Value[0]了 
回复 支持 反对

使用道具 举报

1

主题

6

帖子

0

精华

新手上路

积分
36
金钱
36
注册时间
2015-4-24
在线时间
3 小时
发表于 2015-4-27 23:41:45 | 显示全部楼层
回复【3楼】zhanmcu:
--------------------------------- 当时这问题怎么解决的,遇到
同样的问题,adc工作在连续转换模式,求解脱
回复 支持 反对

使用道具 举报

1

主题

4

帖子

0

精华

新手入门

积分
28
金钱
28
注册时间
2015-5-11
在线时间
0 小时
发表于 2015-5-11 10:56:30 | 显示全部楼层
回复【5楼】zhuwenfly:
---------------------------------
求助   大一的 科创也做这个   不会   求帮忙
回复 支持 反对

使用道具 举报

39

主题

156

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
417
金钱
417
注册时间
2012-12-23
在线时间
19 小时
发表于 2015-5-12 11:41:18 | 显示全部楼层
如果使用ADC的多通道传输,使用DMA是最方便的
因为对于ADC的规则组转换方式,它只有ADC->DR这一个数据寄存器(注入组有ADC->DR1/DR2/DR3/DR4)
所以使用规则组转换的话,每转换一次ADC->DR这个值是会被重新刷新的
而DMA,像原子哥说的那样,它就是一个搬运工,只要一来数据DMA就把这个数据搬到RAM区
这个时候你只需要设定一下搬运的次数就可以了,也就是你读取ADC的次数了
天道酬勤
回复 支持 反对

使用道具 举报

5

主题

27

帖子

0

精华

初级会员

Rank: 2

积分
73
金钱
73
注册时间
2014-2-28
在线时间
2 小时
发表于 2015-7-13 20:33:31 | 显示全部楼层
回复【13楼】正点原子:
---------------------------------
原子哥 你好!现在使用DMA的话 我使用ADC1的 0-1通道   0通道 采集220V的波形  是间隔0.5ms 读取一次   我怎么定时 读取这个波形  还要1通道 采集其余的数据   1通道的及时性要求不高 可以暂停
没有解决不了的问题 只有不努力的笨蛋
回复 支持 反对

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165540
金钱
165540
注册时间
2010-12-1
在线时间
2117 小时
发表于 2015-7-13 22:36:45 | 显示全部楼层
回复【20楼】d350998385:
---------------------------------
那就用单通道dma得了。dma触发可以用定时器触发。0.5ms触发一次。
另外一个通道,做注入通道处理,或者单独转换。
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

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

本版积分规则



关闭

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

正点原子公众号

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

GMT+8, 2025-6-20 05:55

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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