OpenEdv-开源电子网

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

STM32F1 双ADC+DMA循环模式,每个ADC开2个通道,ADC工作在扫描连续转换模式,每个ADC显示结果混乱

[复制链接]

1

主题

6

帖子

0

精华

新手上路

积分
36
金钱
36
注册时间
2015-4-24
在线时间
3 小时
发表于 2015-4-26 18:42:55 | 显示全部楼层 |阅读模式
5金钱
参考的是ST标准库里Example的双ADC同步规则+DMA采集例程
/* Includes ------------------------------------------------------------------*/
#include "stm32f10x.h"

/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
#define ADC1_DR_Address    ((uint32_t)0x4001244C)

/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
ADC_InitTypeDef ADC_InitStructure;
DMA_InitTypeDef DMA_InitStructure;
__IO uint32_t ADC_DualConvertedValueTab[24];//每个通道采集12次
    
/* Private function prototypes -----------------------------------------------*/
void RCC_Configuration(void);
void GPIO_Configuration(void);
  
/* Private functions ---------------------------------------------------------*/
int main(void)
{     
  /* System clocks configuration ---------------------------------------------*/
  RCC_Configuration();

  /* GPIO configuration ------------------------------------------------------*/
  GPIO_Configuration();

  /* DMA1 channel1 configuration ----------------------------------------------*/
  DMA_DeInit(DMA1_Channel1);
  DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)ADC1_DR_Address;
  DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)ADC_DualConvertedValueTab;
  DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
  DMA_InitStructure.DMA_BufferSize = 24;
  DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
  DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
  DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Word;
  DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Word;
  DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;//和例子唯一不同的地方
  DMA_InitStructure.DMA_Priority = DMA_Priority_High;
  DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
  DMA_Init(DMA1_Channel1, &DMA_InitStructure);
  /* Enable DMA1 Channel1 */
  DMA_Cmd(DMA1_Channel1, ENABLE);

  /* ADC1 configuration ------------------------------------------------------*/
  ADC_InitStructure.ADC_Mode = ADC_Mode_RegSimult;
  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_InitStructure.ADC_NbrOfChannel = 2;
  ADC_Init(ADC1, &ADC_InitStructure);
  /* ADC1 regular channels configuration */ 
  ADC_RegularChannelConfig(ADC1, ADC_Channel_10, 1, ADC_SampleTime_239Cycles5);    
  ADC_RegularChannelConfig(ADC1, ADC_Channel_11, 2, ADC_SampleTime_239Cycles5);
  /* Enable ADC1 DMA */
  ADC_DMACmd(ADC1, ENABLE);

  /* ADC2 configuration ------------------------------------------------------*/
  ADC_InitStructure.ADC_Mode = ADC_Mode_RegSimult;
  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_InitStructure.ADC_NbrOfChannel = 2;
  ADC_Init(ADC2, &ADC_InitStructure);
  /* ADC2 regular channels configuration */ 
  ADC_RegularChannelConfig(ADC2, ADC_Channel_12, 1, ADC_SampleTime_239Cycles5);
  ADC_RegularChannelConfig(ADC2, ADC_Channel_13, 2, ADC_SampleTime_239Cycles5);
  /* Enable ADC2 external trigger conversion */
  ADC_ExternalTrigConvCmd(ADC2, ENABLE);

  /* Enable ADC1 */
  ADC_Cmd(ADC1, ENABLE);
  /* Enable Vrefint channel17 */
  ADC_TempSensorVrefintCmd(ENABLE);

  /* Enable ADC1 reset calibration register */   
  ADC_ResetCalibration(ADC1);
  /* Check the end of ADC1 reset calibration register */
  while(ADC_GetResetCalibrationStatus(ADC1));

  /* Start ADC1 calibration */
  ADC_StartCalibration(ADC1);
  /* Check the end of ADC1 calibration */
  while(ADC_GetCalibrationStatus(ADC1));

  /* Enable ADC2 */
  ADC_Cmd(ADC2, ENABLE);

  /* Enable ADC2 reset calibration register */   
  ADC_ResetCalibration(ADC2);
  /* Check the end of ADC2 reset calibration register */
  while(ADC_GetResetCalibrationStatus(ADC2));

  /* Start ADC2 calibration */
  ADC_StartCalibration(ADC2);
  /* Check the end of ADC2 calibration */
  while(ADC_GetCalibrationStatus(ADC2));

  /* Start ADC1 Software Conversion */ 
  ADC_SoftwareStartConvCmd(ADC1, ENABLE);

  /* Test on DMA1 channel1 transfer complete flag */
  while(!DMA_GetFlagStatus(DMA1_FLAG_TC1));
  /* Clear DMA1 channel1 transfer complete flag */
  DMA_ClearFlag(DMA1_FLAG_TC1);

  while (1)
  {
         ADC1通道1=ADC_DualConvertedValueTab【偶数】的值低16位
        ADC1通道2=ADC_DualConvertedValueTab【偶数】的值高16位
         ADC2通道1=ADC_DualConvertedValueTab【奇数】的值低16位
        ADC2通道2=ADC_DualConvertedValueTab【奇数】的值高16位

  }
}

结果很奇怪,ADC1通道1的值闪烁,一次是ADC1通道1采集值,一次是ADC1通道2的值,交替闪烁。ADC2的值也同理,求高人指点。有没做成功的,借参考,谢谢

正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165536
金钱
165536
注册时间
2010-12-1
在线时间
2117 小时
发表于 2015-4-26 22:23:12 | 显示全部楼层
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复

使用道具 举报

1

主题

6

帖子

0

精华

新手上路

积分
36
金钱
36
注册时间
2015-4-24
在线时间
3 小时
 楼主| 发表于 2015-4-27 00:54:42 | 显示全部楼层
回复【2楼】正点原子:
---------------------------------谢谢原子哥
回复

使用道具 举报

1

主题

6

帖子

0

精华

新手上路

积分
36
金钱
36
注册时间
2015-4-24
在线时间
3 小时
 楼主| 发表于 2015-4-27 00:56:26 | 显示全部楼层
自己顶起来
回复

使用道具 举报

1

主题

6

帖子

0

精华

新手上路

积分
36
金钱
36
注册时间
2015-4-24
在线时间
3 小时
 楼主| 发表于 2015-4-27 23:27:22 | 显示全部楼层
怎么没有指点下呀
回复

使用道具 举报

0

主题

1

帖子

0

精华

新手入门

积分
7
金钱
7
注册时间
2016-7-31
在线时间
0 小时
发表于 2016-7-31 22:35:28 | 显示全部楼层
求解啊,我也遇到这个问题了,楼主已经解决了吗
回复

使用道具 举报

20

主题

468

帖子

3

精华

金牌会员

Rank: 6Rank: 6

积分
1684
金钱
1684
注册时间
2014-2-25
在线时间
230 小时
发表于 2016-8-1 08:49:39 | 显示全部楼层
/****************ADC12采样缓冲区**********************/
//低16位:FreeBackB1-FreeBackB4
//高16位:FreeBackA1-FreeBackA4
/*****************************************************/
__IO uint32_t ADC12_Buff[4];

void ADC12_Init(void)
{
        ADC_InitTypeDef ADC_InitStructure;
        DMA_InitTypeDef    DMA_InitStructure;
        GPIO_InitTypeDef GPIO_InitStructure;
       
        //开启时钟
        RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);                              //使能DMA传输
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1|RCC_APB2Periph_ADC2,ENABLE);   //使能ADC传输       
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOC,ENABLE); //使能GPIO传输

       
        //GPIOC作为模拟通道输入引脚
        GPIO_InitStructure.GPIO_Pin=GPIO_Pin_4|GPIO_Pin_5;
        GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AIN;//模拟输入
        GPIO_Init(GPIOC,&GPIO_InitStructure);      //初始化GPIOC       
       
  //GPIOB作为模拟通道输入引脚
        GPIO_InitStructure.GPIO_Pin=GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7;
        GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AIN;//模拟输入
        GPIO_Init(GPIOA,&GPIO_InitStructure);      //初始化GPIOB       
       
        ADC_DeInit(ADC1);                 //复位ADC1
        RCC_ADCCLKConfig(RCC_PCLK2_Div6); //设置ADC时钟,72/6=12MHz

  //-----------ADC1参数设置----------------------------------
        ADC_InitStructure.ADC_Mode=ADC_Mode_RegSimult;      //ADC同步规则模式
        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通道数目4
        ADC_Init(ADC1,&ADC_InitStructure);                  //初始化ADC1

        ADC_RegularChannelConfig(ADC1,ADC_Channel_14,1,ADC_SampleTime_71Cycles5);  //ADC_Test1采样       
        ADC_RegularChannelConfig(ADC1,ADC_Channel_6, 2,ADC_SampleTime_71Cycles5);  //ADC_Test2采样       
        ADC_RegularChannelConfig(ADC1,ADC_Channel_4, 3,ADC_SampleTime_71Cycles5);  //ADC_Test3采样       
        ADC_RegularChannelConfig(ADC1,ADC_Channel_2, 4,ADC_SampleTime_71Cycles5);  //ADC_Test4采样       
       
  //-----------ADC2参数设置----------------------------------
        ADC_InitStructure.ADC_Mode=ADC_Mode_RegSimult;      //ADC同步规则模式
        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通道数目4
        ADC_Init(ADC2,&ADC_InitStructure);                  //初始化ADC1

        ADC_RegularChannelConfig(ADC2,ADC_Channel_15 ,1,ADC_SampleTime_71Cycles5);  //FreeBack1采样       
        ADC_RegularChannelConfig(ADC2,ADC_Channel_7 , 2,ADC_SampleTime_71Cycles5);  //FreeBack2采样       
        ADC_RegularChannelConfig(ADC2,ADC_Channel_5,  3,ADC_SampleTime_71Cycles5);  //FreeBack3采样       
        ADC_RegularChannelConfig(ADC2,ADC_Channel_3,  4,ADC_SampleTime_71Cycles5);  //FreeBack4采样       
       
        ADC_ExternalTrigConvCmd(ADC2, ENABLE);                                     //使能ADC2外部触发转换
       
  //------------DMA参数设置----------------------------------
        DMA_DeInit(DMA1_Channel1);                                 //将DMA的通道x寄存器重设为缺省值
        DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)&ADC1->DR; //DMA外设基地址
        DMA_InitStructure.DMA_MemoryBaseAddr = (u32)ADC12_Buff;    //DMA内存基地址
        DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;         //数据传输方向,从内存读取
        DMA_InitStructure.DMA_BufferSize = 4;                      //DMA通道的DMA缓存的大小
        DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;             //外设地址寄存器不变
        DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;                      //内存地址寄存器递增
        DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Word;      //数据宽度为32位
        DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Word;              //数据宽度为32位
        DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;          //工作在循环缓存模式
        DMA_InitStructure.DMA_Priority = DMA_Priority_High;     //DMA通道 x拥有中等优先级
        DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;            //DMA通道x没有设置为内存到内存传输
        DMA_Init(DMA1_Channel1, &DMA_InitStructure);            //根据DMA_InitStruct中指定的参数初始化DMA的通道USART1_Tx_DMA_Channel所标识的寄存器
       
        DMA_Cmd(DMA1_Channel1,ENABLE);                          //打开DMA传输
       
        ADC_Cmd(ADC1,ENABLE);                 //使能ADC1
        ADC_Cmd(ADC2,ENABLE);                 //使能ADC2
       
        ADC_ResetCalibration(ADC1);                 //开启复位校准
        while(ADC_GetResetCalibrationStatus(ADC1)); //等待复位校准结束
        ADC_StartCalibration(ADC1);                 //开启AD校准
        while(ADC_GetCalibrationStatus(ADC1));      //等待校准结束
       
        ADC_ResetCalibration(ADC2);                 //开启复位校准
        while(ADC_GetResetCalibrationStatus(ADC2)); //等待复位校准结束
        ADC_StartCalibration(ADC2);                 //开启AD校准
        while(ADC_GetCalibrationStatus(ADC2));      //等待校准结束
       
       
        ADC_DMACmd(ADC1, ENABLE);                      //ADC1 DMA传送数据打开
        ADC_SoftwareStartConvCmd(ADC1,ENABLE);         //使能指定的ADC1的软件转换功能
}

回复

使用道具 举报

20

主题

468

帖子

3

精华

金牌会员

Rank: 6Rank: 6

积分
1684
金钱
1684
注册时间
2014-2-25
在线时间
230 小时
发表于 2016-8-1 08:51:28 | 显示全部楼层
这是我以前写的,可以使用,高位装ADC2的值,低16位装ADC1的值,都是4个通道.可正常使用的.
你的程序我没细看,你对比看看吧
回复

使用道具 举报

20

主题

96

帖子

0

精华

初级会员

Rank: 2

积分
192
金钱
192
注册时间
2016-1-12
在线时间
62 小时
发表于 2016-8-25 22:59:44 | 显示全部楼层
1201yuge 发表于 2016-8-1 08:49
/****************ADC12采样缓冲区**********************/
//低16位:FreeBackB1-FreeBackB4
//高16位: ...

您好,对这段这段程序有一个问题。
为什么双ADC模式下,DMA外设基地址还是 (u32)&ADC1->DR(ADC1的基地址);而不是用双重模式的ADC通用规则寄存器(参开手册285页),ADC1和ADC2共用的数据寄存器。
回复

使用道具 举报

42

主题

297

帖子

0

精华

高级会员

Rank: 4

积分
994
金钱
994
注册时间
2016-7-22
在线时间
318 小时
发表于 2016-12-7 16:21:41 | 显示全部楼层
飞羽1918 发表于 2016-8-25 22:59
您好,对这段这段程序有一个问题。
为什么双ADC模式下,DMA外设基地址还是 (u32)&ADC1->DR(ADC1的基地 ...

同步规则模式
此模式在规则通道组上执行。外部触发源来自ADC1的规则组多路器(由ADC1_CR2寄存器的
EXTSEL[2:0]选择)。 给ADC2提供同步触发。
注意: 不要在2个ADC上转换相同的通道(如果转换两个ADC的相同通道,不可能提供重叠的采样时
间)。
在ADC1或ADC2的转换结束时:
● 产生一个32位DMA传输请求(如果设置了DMA位),传输到SRAM的32位ADC1_DR寄存器
上半个字包含ADC2的转换数据,低半个字包含ADC1的转换数据。
回复

使用道具 举报

2

主题

12

帖子

0

精华

初级会员

Rank: 2

积分
66
金钱
66
注册时间
2015-11-2
在线时间
10 小时
发表于 2017-9-1 11:01:50 | 显示全部楼层
你好,我也遇到这个问题了,貌似是采样顺序颠倒了,请问你解决了吗,怎么解决的?
回复

使用道具 举报

0

主题

2

帖子

0

精华

新手入门

积分
13
金钱
13
注册时间
2017-11-8
在线时间
0 小时
发表于 2017-11-8 10:19:57 | 显示全部楼层
问一下,循环模式使能后,是使用中断方式还是查询方式接收dma数据?
回复

使用道具 举报

37

主题

142

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
278
金钱
278
注册时间
2016-9-13
在线时间
73 小时
发表于 2017-12-29 10:26:45 | 显示全部楼层
1201yuge 发表于 2016-8-1 08:51
这是我以前写的,可以使用,高位装ADC2的值,低16位装ADC1的值,都是4个通道.可正常使用的.
你的程序我没细看, ...

请问高位装adc2的值,但是adc2有4个通道,这四个通道之间怎么互相排序呢?
回复

使用道具 举报

0

主题

7

帖子

0

精华

初级会员

Rank: 2

积分
108
金钱
108
注册时间
2020-4-29
在线时间
26 小时
发表于 2021-11-9 17:47:54 | 显示全部楼层
1201yuge 发表于 2016-8-1 08:51
这是我以前写的,可以使用,高位装ADC2的值,低16位装ADC1的值,都是4个通道.可正常使用的.
你的程序我没细看, ...

兄弟能分享详细一下详细一点的代码吗?谢谢你
回复

使用道具 举报

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

本版积分规则



关闭

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

正点原子公众号

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

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

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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