nipenghao 发表于 2016-2-24 10:35:10

STM32cube库配置双ADC的同步规则采样

哪位大神能给个使用STM32的HAL库配置双ADC同步规则采样并通过DMA传输的例程,自己利用标准库的试验可以,但是hal库还是不熟,只好来求助了。

Paderboy 发表于 2016-2-24 11:12:03

HAL库里有例程的你可要看看。。。

nipenghao 发表于 2016-2-24 11:33:31

Paderboy 发表于 2016-2-24 11:12
HAL库里有例程的你可要看看。。。

HAL库里有嘛,我找了下没找到,我的库版本是STM32Cube_FW_F4_V1.10.0,里面是有一些ADC的HAL使用例程,只是我想要的是配置两个ADC同时采样的,类似标准库F1系列的RegSimul_DualMode。

发表于 2016-2-24 16:39:07

楼主看一下这个例程,

nipenghao 发表于 2016-2-24 17:10:51

安 发表于 2016-2-24 16:39
楼主看一下这个例程,

嗯,这个看过了,是双ADC的交替模式,只是我想用的是双ADC的同步规则模式,就是在配置时 MultiModeInit.Mode = ADC_DUALMODE_REGSIMULT; 这个例程原来的F1标准库有,而且我用F4时用标准库也行,但是用HAL库配置F4老出错。

Paderboy 发表于 2016-2-24 19:32:13

本帖最后由 Paderboy 于 2016-2-24 19:34 编辑

nipenghao 发表于 2016-2-24 17:10
嗯,这个看过了,是双ADC的交替模式,只是我想用的是双ADC的同步规则模式,就是在配置时 MultiModeInit.M ...
把你cube配置的发上来看看。。

回到未来~ 发表于 2016-2-25 07:02:10

帮顶……

nipenghao 发表于 2016-2-25 10:11:10

Paderboy 发表于 2016-2-24 19:32
把你cube配置的发上来看看。。

下面是配置双ADC的代码,void Dual_ADC_Config(void)
{
    ADC_ChannelConfTypeDef sConfig_master;
    ADC_ChannelConfTypeDef sConfig_slave;
    ADC_MultiModeTypeDef   MultiModeInit;

   
    //config for adc2
    AdcHandle_slave.Instance = ADCy;
    AdcHandle_slave.Init.ClockPrescaler = ADC_CLOCKPRESCALER_PCLK_DIV4;
    AdcHandle_slave.Init.Resolution = ADC_RESOLUTION_12B;
    AdcHandle_slave.Init.DataAlign = ADC_DATAALIGN_RIGHT;
    AdcHandle_slave.Init.ScanConvMode = DISABLE;
    AdcHandle_slave.Init.EOCSelection = DISABLE;//ADC_EOC_SEQ_CONV;   //ADC_EOC_SINGLE_CONV; 转换序列结束
   
    AdcHandle_slave.Init.ContinuousConvMode = ENABLE;
    AdcHandle_slave.Init.NbrOfConversion = 1;                  //sequencer disable
    AdcHandle_slave.Init.DiscontinuousConvMode = DISABLE;      //sequencer disable
    AdcHandle_slave.Init.NbrOfDiscConversion = 0;                  //sequencer disable
   
    //AdcHandle_slave.Init.ExternalTrigConv = ADC_EXTERNALTRIGCONV_T1_CC1;
    AdcHandle_slave.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
    //AdcHandle_slave.Init.DMAContinuousRequests = ENABLE;
   
   // AdcHandle_slave.Init = AdcHandle_master.Init;
//配置ADC2由ADC1触发
    if(HAL_ADC_Init(&AdcHandle_slave) != HAL_OK)
    {
      Error_Handler();
    }
   
    sConfig_slave.Channel   = ADCy_CHANNEL;   //adc2 channel1
    sConfig_slave.Rank      = 1;
    sConfig_slave.SamplingTime= ADC_SAMPLETIME_15CYCLES;
//L4中有    sConfig.SingleDiff= ADC_SINGLE_ENDED;
//L4中有   sConfig.OffsetNumber= 0;
    sConfig_slave.Offset      =0;
    if(HAL_ADC_ConfigChannel(&AdcHandle_slave,&sConfig_slave) !=HAL_OK)
    {
      Error_Handler();
    }
   
    //config for ADC1
    AdcHandle_master.Instance = ADCx;
   
    AdcHandle_master.Init.ClockPrescaler = ADC_CLOCKPRESCALER_PCLK_DIV4;      //L4的时钟跟F4不同
    AdcHandle_master.Init.Resolution = ADC_RESOLUTION_12B;
    AdcHandle_master.Init.DataAlign = ADC_DATAALIGN_RIGHT;
    AdcHandle_master.Init.ScanConvMode = DISABLE;
    AdcHandle_master.Init.EOCSelection = DISABLE;//ADC_EOC_SEQ_CONV;   //ADC_EOC_SINGLE_CONV; 转换序列结束

    AdcHandle_master.Init.ContinuousConvMode = ENABLE;
    AdcHandle_master.Init.NbrOfConversion = 1;                  //sequencer disable
    AdcHandle_master.Init.DiscontinuousConvMode = DISABLE;      //sequencer disable
    AdcHandle_master.Init.NbrOfDiscConversion = 0;                  //sequencer disable               
    //#if defined ADC_TRIGGER_WITH_TIMER
    AdcHandle_master.Init.ExternalTrigConv = ADC_EXTERNALTRIGCONV_T1_CC1;
    AdcHandle_master.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
    AdcHandle_master.Init.DMAContinuousRequests = ENABLE;

    if(HAL_ADC_Init(&AdcHandle_master) != HAL_OK)
    {
      Error_Handler();
    }
    sConfig_master.Channel    = ADCx_CHANNEL;
    sConfig_master.Rank       = 1;
    sConfig_master.SamplingTime = ADC_SAMPLETIME_15CYCLES;
    sConfig_master.Offset   = 0;
    if(HAL_ADC_ConfigChannel(&AdcHandle_master,&sConfig_master) != HAL_OK)
    {
      Error_Handler();
    }
   

//configuration of multimode
    MultiModeInit.Mode = ADC_DUALMODE_REGSIMULT;
    MultiModeInit.TwoSamplingDelay = ADC_TWOSAMPLINGDELAY_5CYCLES;
    MultiModeInit.DMAAccessMode = ADC_DMAACCESSMODE_1;
   
    if(HAL_ADCEx_MultiModeConfigChannel(&AdcHandle_master,&MultiModeInit) != HAL_OK)    //配置ADC的MultiMode
    {
      Error_Handler();
    }
//    if(HAL_ADCEx_MultiModeConfigChannel(&AdcHandle_slave,&MultiModeInit) != HAL_OK)
//    {
//      Error_Handler();
//    }

}

这下面的是配置底层和DMA的代码
void HAL_ADC_MspInit(ADC_HandleTypeDef* hadc)
{
GPIO_InitTypeDef          GPIO_InitStruct;
static DMA_HandleTypeDefhdma_adc;

/*##-1- Enable peripherals and GPIO Clocks #################################*/
/* Enable GPIO clock */
ADCxy_CHANNEL_GPIO_CLK_ENABLE();
/* ADC Periph clock enable */
ADCx_CLK_ENABLE();
ADCy_CLK_ENABLE();

/* Enable DMA2 clock */
DMAxy_CLK_ENABLE();

/*##-2- Configure peripheral GPIO ##########################################*/
/* ADC1 Channel8 GPIO pin configuration */
GPIO_InitStruct.Pin = ADCx_CHANNEL_PIN;                     //ADC1_6
GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(ADCx_CHANNEL_GPIO_PORT, &GPIO_InitStruct);

GPIO_InitStruct.Pin = ADCy_CHANNEL_PIN;                     //ADC2_1
GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(ADCy_CHANNEL_GPIO_PORT, &GPIO_InitStruct);


/*##-3- Configure the DMA streams ##########################################*/
/* Set the parameters to be configured */
hdma_adc.Instance = ADCxy_DMA_STREAM;

hdma_adc.Init.Channel= ADCxy_DMA_CHANNEL;
hdma_adc.Init.Direction = DMA_PERIPH_TO_MEMORY;
hdma_adc.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_adc.Init.MemInc = DMA_MINC_ENABLE;
hdma_adc.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
hdma_adc.Init.MemDataAlignment = DMA_PDATAALIGN_HALFWORD;
hdma_adc.Init.Mode = DMA_CIRCULAR;    //original was DMA_CIRCULAR
hdma_adc.Init.Priority = DMA_PRIORITY_HIGH;
hdma_adc.Init.FIFOMode = DMA_FIFOMODE_DISABLE;         
hdma_adc.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_HALFFULL;
hdma_adc.Init.MemBurst = DMA_MBURST_SINGLE;
hdma_adc.Init.PeriphBurst = DMA_PBURST_SINGLE;

HAL_DMA_Init(&hdma_adc);
   
/* Associate the initialized DMA handle to the the ADC handle */
__HAL_LINKDMA(hadc, DMA_Handle, hdma_adc);

/*##-4- Configure the NVIC for DMA #########################################*/
/* NVIC configuration for DMA transfer complete interrupt */
HAL_NVIC_SetPriority(ADCxy_DMA_IRQn, 0, 0);   
HAL_NVIC_EnableIRQ(ADCxy_DMA_IRQn);
}
然后参照原来函数中的HAL_StatusTypeDef HAL_ADCEx_MultiModeStart_DMA(ADC_HandleTypeDef* hadc, uint32_t* pData, uint32_t Length)函数,重写了个函数,主要是增加了使能DMA mode 和 开启定时器2.

Paderboy 发表于 2016-2-25 15:21:27

我这个测试好了。直接用CubeMx 4.13 配置好直接生成后,
HAL_ADC_Start(&hadc2); 初始化好后先启动ADC2 工作。

HAL_ADCEx_MultiModeStart_DMA(&hadc1, ADCvaule, 1);然后启动ADC 多通道 DMA读取CDR里的数据。。


好了,上整个流程图吧。。




































nipenghao 发表于 2016-2-25 21:37:56

Paderboy 发表于 2016-2-25 15:21
我这个测试好了。直接用CubeMx 4.13 配置好直接生成后,
HAL_ADC_Start(&hadc2); 初始化好后先启动ADC2 工 ...

非常感谢,看了下你用cubemx生成的代码和我的作了下对比,感觉cubemx挺方便的,但是我还不太会用,以后得好好学学。顺便问下如果配置成用定时器触发两个定时器同步规则采样的话生成的代码是怎样的,是否两个定时器的触发模式都要配置。
页: [1] 2 3
查看完整版本: STM32cube库配置双ADC的同步规则采样