搜索
查看: 3816|回复: 9

[已解决] 问题:双重 ADC 多通道规则同步下,DMA 传送结果到数组出错

[复制链接]

该用户从未签到

2

主题

4

帖子

0

蝴蝶豆

初级会员

最后登录
2017-9-16
发表于 2017-9-13 00:23:08 | 显示全部楼层 |阅读模式
10ST金币
本帖最后由 sun0727 于 2017-9-13 03:15 编辑

设想的是这样的

ADC1 作为 MasterADC 控制如下 5 路, 结果依次付给 数组 的 0-4 低16位:

ADC1_IN1 -------> ADCConvertedData[0] 低16位
ADC1_IN2 -------> ADCConvertedData[1] 低16位
ADC1_IN3 ------>  ADCConvertedData[2] 低16位
ADC1_IN4 ------> ADCConvertedData[3] 低16位
ADC1_IN12-----> ADCConvertedData[4] 低16位

ADC2 作为 SlaveADC 控制如下 3 路, 结果依次付给 数组 的 0-2 的高16位:

ADC2_IN1-------> ADCConvertedData[0] 高16位
ADC2_IN3-------> ADCConvertedData[1] 高16位
ADC2_IN4-------> ADCConvertedData[2] 高16位

但是经过我自己的编写,发现 ADC1 能扫描,但是 ADC2 结果在数组中的位置并不固定,原因是因为 ADC2 下的通道是 3 个 ,ADC1 的通道是 5 个 数量不对称 请问程序如何修改

以下是我的部分配置



DMA 配置
DMA_HandleTypeDef  ADC1_DMA_Handle;

void ADC1_DMA_Init(ADC_HandleTypeDef* hadc)
{

ADC1_DMA_Handle.Instance = DMA1_Channel1;
ADC1_DMA_Handle.Init.Direction = DMA_PERIPH_TO_MEMORY;
ADC1_DMA_Handle.Init.PeriphInc = DMA_PINC_DISABLE;
ADC1_DMA_Handle.Init.MemInc = DMA_MINC_ENABLE;
ADC1_DMA_Handle.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;
ADC1_DMA_Handle.Init.MemDataAlignment = DMA_MDATAALIGN_WORD;
ADC1_DMA_Handle.Init.Mode = DMA_CIRCULAR;
ADC1_DMA_Handle.Init.Priority = DMA_PRIORITY_HIGH;

//HAL_DMA_DeInit(&ADC1_DMA_Handle);
HAL_DMA_Init(&ADC1_DMA_Handle);

__HAL_LINKDMA(hadc,DMA_Handle,ADC1_DMA_Handle);
     
HAL_NVIC_SetPriority(DMA1_Channel1_IRQn, 1, 0);
HAL_NVIC_EnableIRQ(DMA1_Channel1_IRQn);

}

多通道规则同步的配置



  1. void ADC_Multimode_Config(void)
  2. {
  3.     ADC_Multimode.Mode = ADC_DUALMODE_REGSIMULT;
  4.   ADC_Multimode.DMAAccessMode = ADC_DMAACCESSMODE_12_10_BITS;
  5.   ADC_Multimode.TwoSamplingDelay = ADC_TWOSAMPLINGDELAY_4CYCLES;
  6.      
  7.     HAL_ADCEx_MultiModeConfigChannel(&ADC1_Handle, &ADC_Multimode);
  8. }
复制代码
ADC1 的初始化

  1. void ADC1_Input_Init(void)
  2. {
  3.     ADC1_Handle.Instance          = ADC1;
  4.     ADC1_Handle.Init.ClockPrescaler        = ADC_CLOCK_SYNC_PCLK_DIV2;      /* Synchronous clock mode, input ADC clock divided by 2*/
  5.   ADC1_Handle.Init.Resolution            = ADC_RESOLUTION_12B;            /* 12-bit resolution for converted data */
  6.   ADC1_Handle.Init.DataAlign             = ADC_DATAALIGN_RIGHT;           /* Right-alignment for converted data */
  7.   ADC1_Handle.Init.ScanConvMode          = ADC_SCAN_ENABLE;                       /* Sequencer disabled (ADC conversion on only 1 channel: channel set on rank 1) */
  8.   ADC1_Handle.Init.EOCSelection          = ADC_EOC_SINGLE_CONV;           /* EOC flag picked-up to indicate conversion end */
  9.   ADC1_Handle.Init.LowPowerAutoWait      = DISABLE;
  10.   ADC1_Handle.Init.ContinuousConvMode    = ENABLE;
  11.   ADC1_Handle.Init.NbrOfConversion       = 5;
  12.   ADC1_Handle.Init.DiscontinuousConvMode = DISABLE;
  13.   ADC1_Handle.Init.ExternalTrigConv      = ADC_SOFTWARE_START;            /
  14.   ADC1_Handle.Init.ExternalTrigConvEdge  = ADC_EXTERNALTRIGCONVEDGE_NONE; /
  15.   ADC1_Handle.Init.DMAContinuousRequests = ENABLE;                        /* ADC DMA continuous request to match with DMA circular mode */
  16.   ADC1_Handle.Init.Overrun               = ADC_OVR_DATA_OVERWRITTEN;
  17.     HAL_ADC_Init(&ADC1_Handle);
  18.      
  19. }
复制代码
ADC1 Channel 配置

  1. void ADC1_Channel_Config(void)
  2. {
  3.   //common config for channel
  4.    
  5.   ADC1_sConfig.SamplingTime = ADC_SAMPLETIME_19CYCLES_5;   /* Sampling time (number of clock cycles unit) */
  6.   ADC1_sConfig.SingleDiff   = ADC_SINGLE_ENDED;            /* Single-ended input channel */
  7.   ADC1_sConfig.OffsetNumber = ADC_OFFSET_NONE;             /* No offset subtraction */
  8.   ADC1_sConfig.Offset = 0;

  9.   ADC1_sConfig.Channel      = ADC_CHANNEL_1;                /* Sampled channel number */   
  10.     ADC1_sConfig.Rank         = ADC_REGULAR_RANK_1;          /* Rank of sampled channel number ADCx_CHANNEL */
  11.     HAL_ADC_ConfigChannel(&ADC1_Handle, &ADC1_sConfig);
  12.      
  13.     ADC1_sConfig.Channel      = ADC_CHANNEL_2;  
  14.     ADC1_sConfig.Rank         = ADC_REGULAR_RANK_2;
  15.     HAL_ADC_ConfigChannel(&ADC1_Handle, &ADC1_sConfig);
  16.      
  17.     ADC1_sConfig.Channel      = ADC_CHANNEL_3;  
  18.     ADC1_sConfig.Rank         = ADC_REGULAR_RANK_3;
  19.     HAL_ADC_ConfigChannel(&ADC1_Handle, &ADC1_sConfig);
  20.      
  21.     ADC1_sConfig.Channel      = ADC_CHANNEL_4;  
  22.     ADC1_sConfig.Rank         = ADC_REGULAR_RANK_4;
  23.     HAL_ADC_ConfigChannel(&ADC1_Handle, &ADC1_sConfig);
  24.      
  25.     ADC1_sConfig.Channel      = ADC_CHANNEL_12;
  26.     ADC1_sConfig.Rank         = ADC_REGULAR_RANK_5;
  27.     HAL_ADC_ConfigChannel(&ADC1_Handle, &ADC1_sConfig);
  28. }
复制代码
ADC2 的初始化 和  Channel 配置
  1. void ADC2_Input_Init(void)
  2. {
  3.     ADC2_Handle.Instance          = ADC2;
  4.      
  5.     //HAL_ADC_DeInit(& ADC2_Handle);
  6.     //HAL_ADCEx_Calibration_Start(&ADC2_Handle, ADC_SINGLE_ENDED);
  7.      
  8.     ADC2_Handle.Init.ClockPrescaler        = ADC_CLOCK_SYNC_PCLK_DIV2;      /* Synchronous clock mode, input ADC clock divided by 2*/
  9.   ADC2_Handle.Init.Resolution            = ADC_RESOLUTION_12B;            /* 12-bit resolution for converted data */
  10.   ADC2_Handle.Init.DataAlign             = ADC_DATAALIGN_RIGHT;           /* Right-alignment for converted data */
  11.   ADC2_Handle.Init.ScanConvMode          = ADC_SCAN_ENABLE;                      /* Sequencer disabled (ADC conversion on only 1 channel: channel set on rank 1) */
  12.   ADC2_Handle.Init.EOCSelection          = ADC_EOC_SINGLE_CONV;           /* EOC flag picked-up to indicate conversion end */
  13.   ADC2_Handle.Init.LowPowerAutoWait      = DISABLE;                       /* Auto-delayed conversion feature disabled */
  14.   ADC2_Handle.Init.ContinuousConvMode    = ENABLE;                        /* Continuous mode enabled (automatic conversion restart after each conversion) */
  15.   ADC2_Handle.Init.NbrOfConversion       = 3;                             /* Parameter discarded because sequencer is disabled */
  16.   ADC2_Handle.Init.DiscontinuousConvMode = DISABLE;                       /* Parameter discarded because sequencer is disabled */
  17.   ADC2_Handle.Init.NbrOfDiscConversion   = 1;                             /* Parameter discarded because sequencer is disabled */
  18.   //ADC2_Handle.Init.ExternalTrigConv      = ADC_SOFTWARE_START;            /* Software start to trig the 1st conversion manually, without external event */
  19.   //ADC2_Handle.Init.ExternalTrigConvEdge  = ADC_EXTERNALTRIGCONVEDGE_NONE; /* Parameter discarded because software trigger chosen */
  20.   ADC2_Handle.Init.DMAContinuousRequests = ENABLE;                        /* ADC DMA continuous request to match with DMA circular mode */
  21.   ADC2_Handle.Init.Overrun               = ADC_OVR_DATA_OVERWRITTEN;      /* DR register is overwritten with the last conversion result in case of overrun */
  22.    
  23.     HAL_ADC_Init(&ADC2_Handle);
  24.      
  25. }

  26. //--------------------Configure the ADC2 Channel-----------------------------------
  27. void ADC2_Channel_Config(void)
  28. {
  29.   //common config for channel
  30.   ADC2_sConfig.SamplingTime = ADC_SAMPLETIME_19CYCLES_5;   /* Sampling time (number of clock cycles unit) */
  31.   ADC2_sConfig.SingleDiff   = ADC_SINGLE_ENDED;            /* Single-ended input channel */
  32.   ADC2_sConfig.OffsetNumber = ADC_OFFSET_NONE;             /* No offset subtraction */
  33.   ADC2_sConfig.Offset = 0;

  34.   ADC2_sConfig.Channel      = ADC_CHANNEL_1;                /* Sampled channel number */   
  35.     ADC2_sConfig.Rank         = ADC_REGULAR_RANK_1;          /* Rank of sampled channel number ADCx_CHANNEL */
  36.     HAL_ADC_ConfigChannel(&ADC2_Handle, &ADC2_sConfig);
  37.      
  38.     ADC2_sConfig.Channel      = ADC_CHANNEL_3;  
  39.     ADC2_sConfig.Rank         = ADC_REGULAR_RANK_2;
  40.     HAL_ADC_ConfigChannel(&ADC2_Handle, &ADC2_sConfig);
  41.      
  42.     ADC2_sConfig.Channel      = ADC_CHANNEL_4;  
  43.     ADC2_sConfig.Rank         = ADC_REGULAR_RANK_3;
  44.     ADC2_sConfig.SamplingTime = ADC_SAMPLETIME_1CYCLE_5;
  45.     HAL_ADC_ConfigChannel(&ADC2_Handle, &ADC2_sConfig);
  46.      
  47. }
复制代码


复制代码
函数的调用

#define ADC_CONVERTED_DATA_BUFFER_SIZE   ((uint32_t)  5)   /* Size of array aADCxConvertedData[] */
uint32_t   aADCxConvertedData[ADC_CONVERTED_DATA_BUFFER_SIZE];


//------------------------------Start ADC in Dualmode and DMA --------------------------------------
void ADC_DMA_Dualmode_Start(void)
{   
ADC1_Input_Init();
ADC_Multimode_Config();
ADC1_Channel_Config();
     
ADC2_Input_Init();
ADC2_Channel_Config();
//  
//  
HAL_ADC_Start(&ADC2_Handle);
HAL_ADCEx_MultiModeStart_DMA(&ADC1_Handle,(uint32_t *)aADCxConvertedData,ADC_CONVERTED_DATA_BUFFER_SIZE);
     
}



最佳答案

查看完整内容

你数据是分:高16位、低16位, 而接收到的数据只有12位, 是不是应该把高16位的数据,右移4位, 并把右移出来的部分,填充到低16位的高4位中呢? 写的有点拗口,希望能明白我在说什么。
回复

使用道具 举报

该用户从未签到

0

主题

2189

帖子

397

蝴蝶豆

论坛元老

最后登录
2021-12-8
发表于 2017-9-13 00:23:09 | 显示全部楼层
你数据是分:高16位、低16位,
而接收到的数据只有12位,
是不是应该把高16位的数据,右移4位,
并把右移出来的部分,填充到低16位的高4位中呢?

写的有点拗口,希望能明白我在说什么。

评分

参与人数 1蝴蝶豆 +4 收起 理由
zero99 + 4

查看全部评分

回复

使用道具 举报

该用户从未签到

2

主题

4

帖子

0

蝴蝶豆

初级会员

最后登录
2017-9-16
 楼主| 发表于 2017-9-13 01:01:59 | 显示全部楼层
本帖最后由 sun0727 于 2017-9-13 03:16 编辑

求大神指点这种 数量非对称的 双重 ADC
回复

使用道具 举报

该用户从未签到

74

主题

3420

帖子

82

蝴蝶豆

社区小助手

最后登录
2023-11-12
发表于 2018-1-18 10:09:37 | 显示全部楼层
STM32的ADC转换分辨率只有12位,楼主为何要把它拆成2个16位来读取?

评分

参与人数 1蝴蝶豆 +2 收起 理由
zero99 + 2

查看全部评分

回复

使用道具 举报

该用户从未签到

36

主题

145

帖子

11

蝴蝶豆

金牌会员

最后登录
2020-11-10
发表于 2018-1-18 11:14:49 | 显示全部楼层
前一段时间使用双重同时采样,我的设置中,ADC1和ADC2的转换通道是一样多,我想楼主如果ADC通道有多余,也可以考虑在ADC2中增加几个多余通道。另外,DMA的字长一定要设置成32位。附件是我工程。

handle.zip

3.39 KB, 下载次数: 10, 下载积分: ST金币 -1

评分

参与人数 1蝴蝶豆 +4 收起 理由
zero99 + 4

查看全部评分

回复

使用道具 举报

  • TA的每日心情
    开心
    2017-12-6 11:47
  • 签到天数: 1 天

    [LV.1]初来乍到

    49

    主题

    3724

    帖子

    429

    蝴蝶豆

    论坛元老

    最后登录
    2021-8-7
    发表于 2018-1-18 15:49:48 | 显示全部楼层
    弄成同样通道数吧,两路ADC扫描频率相同,采样率相同,只是内存得多开一点。

    评分

    参与人数 1蝴蝶豆 +2 收起 理由
    zero99 + 2

    查看全部评分

    回复

    使用道具 举报

    该用户从未签到

    82

    主题

    718

    帖子

    121

    蝴蝶豆

    版主

    最后登录
    2021-1-2
    发表于 2018-1-18 16:20:43 | 显示全部楼层
    看代码好像是采用中断调用DMA,既然如此各个通道带参数独立调用DMA,存储到自己定义的数组中,回调数据时,按照规定读取或输出,这样就没有需要多用存储的要求了。想想是吗?

    评分

    参与人数 1蝴蝶豆 +3 收起 理由
    zero99 + 3

    查看全部评分

    回复

    使用道具 举报

    该用户从未签到

    28

    主题

    528

    帖子

    40

    蝴蝶豆

    论坛元老

    最后登录
    2021-3-28
    发表于 2018-1-19 16:11:25 | 显示全部楼层
    搞FOC的吧
    回复

    使用道具 举报

    该用户从未签到

    0

    主题

    11

    帖子

    0

    蝴蝶豆

    初级会员

    最后登录
    2020-5-13
    发表于 2020-3-5 15:00:26 | 显示全部楼层
    楼主你这个问题解决了吗?能不能帮我看一下我的工程,跟你的设置的一样,只不过我的是对称adc转换的,但是在转换时发现各通道的数据都是不对,这该怎么办?是我配置错误了吗?
    回复

    使用道具 举报

    该用户从未签到

    0

    主题

    11

    帖子

    0

    蝴蝶豆

    初级会员

    最后登录
    2020-5-13
    发表于 2020-3-5 15:05:38 | 显示全部楼层
    文件有点大,不好意思

    test_adc1.part02.rar

    5 MB, 下载次数: 0, 下载积分: ST金币 -1

    test_adc1.part03.rar

    5 MB, 下载次数: 0, 下载积分: ST金币 -1

    test_adc1.part04.rar

    5 MB, 下载次数: 0, 下载积分: ST金币 -1

    test_adc1.part05.rar

    4.22 MB, 下载次数: 0, 下载积分: ST金币 -1

    test_adc1.part01.rar

    5 MB, 下载次数: 0, 下载积分: ST金币 -1

    回复

    使用道具 举报

    您需要登录后才可以回帖 注册/登录

    本版积分规则

    关闭

    站长推荐上一条 /3 下一条

    Archiver|手机版|小黑屋|论坛-意法半导体STM32/STM8技术社区

    GMT+8, 2024-4-30 00:33 , Processed in 1.197800 second(s), 46 queries .

    Powered by Discuz! X3.4

    Copyright © 2001-2024, Tencent Cloud.

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