Using DMA ADC in combination with normal ADC?

Post here first, or if you can't find a relevant section!
Post Reply
Eldi4
Posts: 22
Joined: Fri Dec 20, 2019 8:10 am
Answers: 1
Location: Kediri, Indonesia

Using DMA ADC in combination with normal ADC?

Post by Eldi4 »

Hello there,
I'm looking a way to use DMA ADC and normal ADC combined, the DMA ADC is used to measuring current and voltage of power supply (continous), while the normal ADC used to measure temperature of transistor (probably like once per second), when i read the ADC value of temperature, the DMA goes messed up. Is there a way to do that?
I have separated the DMA ADC channel with the ADC that is used for temperature reading, the DMA is ADC1 whilst the temperature is ADC2.
If i call readTherm(int channel) function somewhere on the program, the DMA buffer goes mad (random big number like 12412812951) and also i did'nt get my temperature reading either (also some random big number).

Here is my whole DMA, ADC and some HAL GPIO settings :

Code: Select all

extern "C" void DMA1_Channel1_IRQHandler(void)
{
  HAL_DMA_IRQHandler(&hdma_adc1);
}

extern "C" void HAL_ADC_MspInit(ADC_HandleTypeDef* hadcx)
{

  GPIO_InitTypeDef GPIO_InitStruct = {0};
  
  if(hadcx->Instance==ADC2){
    __HAL_RCC_ADC2_CLK_ENABLE();
  }
  
  if(hadcx->Instance==ADC1)
  {
    __HAL_RCC_ADC1_CLK_ENABLE();
  
    hdma_adc1.Instance = DMA1_Channel1;
    hdma_adc1.Init.Direction = DMA_PERIPH_TO_MEMORY;
    hdma_adc1.Init.PeriphInc = DMA_PINC_DISABLE;
    hdma_adc1.Init.MemInc = DMA_MINC_ENABLE;
    hdma_adc1.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;
    hdma_adc1.Init.MemDataAlignment = DMA_MDATAALIGN_WORD;
    hdma_adc1.Init.Mode = DMA_CIRCULAR;
    hdma_adc1.Init.Priority = DMA_PRIORITY_LOW;
    if (HAL_DMA_Init(&hdma_adc1) != HAL_OK)
    {
      Error_Handler();
    }

    __HAL_LINKDMA(hadcx,DMA_Handle,hdma_adc1);
  }

}


extern "C" void HAL_ADC_MspDeInit(ADC_HandleTypeDef* hadcx)
{

  if(hadcx->Instance==ADC1)
  {
    __HAL_RCC_ADC1_CLK_DISABLE();
    HAL_DMA_DeInit(hadcx->DMA_Handle);
  }
  
  if(hadcx->Instance==ADC2)
  {
    __HAL_RCC_ADC2_CLK_DISABLE();
    HAL_DMA_DeInit(hadcx->DMA_Handle);
  }

}


static void MX_GPIO_Init(void)
{
  GPIO_InitTypeDef GPIO_InitStruct = {0};

  /* GPIO Ports Clock Enable */
  __HAL_RCC_GPIOA_CLK_ENABLE();
  __HAL_RCC_GPIOB_CLK_ENABLE();
  __HAL_RCC_GPIOC_CLK_ENABLE();

  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(GPIOA, GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3|GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7|GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11|GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15, GPIO_PIN_RESET);
  HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3|GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7|GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11|GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15, GPIO_PIN_RESET);
  HAL_GPIO_WritePin(GPIOC, GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3|GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7|GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11|GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15, GPIO_PIN_RESET);

  /*Configure GPIO pin : PB10 */
  GPIO_InitStruct.Pin = GPIO_PIN_5|GPIO_PIN_11|GPIO_PIN_10|GPIO_PIN_6|GPIO_PIN_8|GPIO_PIN_7|GPIO_PIN_9;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
  HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

  GPIO_InitStruct.Pin = GPIO_PIN_11|GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_8|GPIO_PIN_12;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
  HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
  
  GPIO_InitStruct.Pin = GPIO_PIN_1|GPIO_PIN_0;
  GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

  GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3|GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7;
  GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
}

static void MX_DMA_Init(void) 
{
  /* DMA controller clock enable */
  __HAL_RCC_DMA1_CLK_ENABLE();

  /* DMA interrupt init */
  /* DMA1_Channel1_IRQn interrupt configuration */
  HAL_NVIC_SetPriority(DMA1_Channel1_IRQn, 0, 0);
  HAL_NVIC_EnableIRQ(DMA1_Channel1_IRQn);
}


static void MX_ADC1_Init(void)
{

  /* USER CODE BEGIN ADC1_Init 0 */

  /* USER CODE END ADC1_Init 0 */

  ADC_ChannelConfTypeDef sConfig = {0};
  ADC_ChannelConfTypeDef sConfig2 = {0};
  /* USER CODE BEGIN ADC1_Init 1 */

  /* USER CODE END ADC1_Init 1 */
  /** Common config 
  */
  hadc1.Instance = ADC1;
  hadc1.Init.ScanConvMode = ADC_SCAN_ENABLE;
  hadc1.Init.ContinuousConvMode = ENABLE;
  hadc1.Init.DiscontinuousConvMode = DISABLE;
  hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START;
  hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
  hadc1.Init.NbrOfConversion = 4;
  if (HAL_ADC_Init(&hadc1) != HAL_OK)
  {
    Error_Handler();
  }
  
  hadc2.Instance = ADC2;
  hadc2.Init.ScanConvMode = ADC_SCAN_DISABLE;
  hadc2.Init.ContinuousConvMode = DISABLE;
  hadc2.Init.DiscontinuousConvMode = DISABLE;
  hadc2.Init.ExternalTrigConv = ADC_SOFTWARE_START;
  hadc2.Init.DataAlign = ADC_DATAALIGN_RIGHT;
  hadc2.Init.NbrOfConversion = 1;
  if (HAL_ADC_Init(&hadc2) != HAL_OK)
  {
    Error_Handler();
  }
  sConfig2.Channel = ADC_CHANNEL_6;
  sConfig2.Rank = ADC_REGULAR_RANK_1;
  sConfig2.SamplingTime = ADC_SAMPLETIME_55CYCLES_5;
  if (HAL_ADC_ConfigChannel(&hadc2, &sConfig2) != HAL_OK){
    Error_Handler();
  }
  sConfig2.Channel = ADC_CHANNEL_7;
  sConfig2.Rank = ADC_REGULAR_RANK_2;
  sConfig2.SamplingTime = ADC_SAMPLETIME_55CYCLES_5;
  if (HAL_ADC_ConfigChannel(&hadc2, &sConfig2) != HAL_OK){
    Error_Handler();
  }
  /*
  sConfig2.Channel = ADC_CHANNEL_8;
  sConfig2.Rank = ADC_REGULAR_RANK_3;
  sConfig2.SamplingTime = ADC_SAMPLETIME_55CYCLES_5;
  if (HAL_ADC_ConfigChannel(&hadc2, &sConfig2) != HAL_OK){
    Error_Handler();
  }
  */
  //////////////////////////////////////////////////////////////////
  sConfig.Channel = ADC_CHANNEL_2;
  sConfig.Rank = ADC_REGULAR_RANK_1;
  sConfig.SamplingTime = ADC_SAMPLETIME_7CYCLES_5;
  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK){
    Error_Handler();
  }
  sConfig.Channel = ADC_CHANNEL_3;
  sConfig.Rank = ADC_REGULAR_RANK_2;
  sConfig.SamplingTime = ADC_SAMPLETIME_7CYCLES_5;
  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK){
    Error_Handler();
  }

  sConfig.Channel = ADC_CHANNEL_4;
  sConfig.Rank = ADC_REGULAR_RANK_3;
  sConfig.SamplingTime = ADC_SAMPLETIME_7CYCLES_5;
  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK){
    Error_Handler();
  }

  sConfig.Channel = ADC_CHANNEL_9;
  sConfig.Rank = ADC_REGULAR_RANK_4;
  sConfig.SamplingTime = ADC_SAMPLETIME_7CYCLES_5;
  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK){
    Error_Handler();
  }


  if (HAL_ADCEx_Calibration_Start(&hadc1) != HAL_OK){
    Error_Handler();
  }
  
  //if (HAL_ADCEx_Calibration_Start(&hadc2) != HAL_OK){
  //  Error_Handler();
  //}
}

int readTherm(int channel){
  ADC_ChannelConfTypeDef adcChannel = {0};
  switch(channel){
    case 0:
      //adcChannel.Channel = ADC_CHANNEL_8;
      break;
    case 1:
      adcChannel.Channel = ADC_CHANNEL_6;
      break;
    case 2:
      adcChannel.Channel = ADC_CHANNEL_7;
      break;
  }
  adcChannel.Rank = 1;
  adcChannel.SamplingTime = ADC_SAMPLETIME_55CYCLES_5; //or any other value available.
  if(HAL_ADC_ConfigChannel(&hadc2, &adcChannel) != HAL_OK){
    Error_Handler();
  }
  HAL_ADC_Start(&hadc2);
  if (HAL_ADC_PollForConversion(&hadc2, 10) == HAL_OK){
    return HAL_ADC_GetValue(&hadc2);
  }
}

int raw_ch1Voltage;
int raw_ch2Voltage;
int raw_ch1Current;
int raw_ch2Current;
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* AdcHandle)
{
  
  if(AdcHandle->Instance==ADC1){

    raw_ch1Voltage = (dmaAdcBuffer[0]+dmaAdcBuffer[4]+dmaAdcBuffer[8])/3;
    raw_ch2Voltage = (dmaAdcBuffer[2]+dmaAdcBuffer[6]+dmaAdcBuffer[10])/3;
    raw_ch1Current = (dmaAdcBuffer[3]+dmaAdcBuffer[7]+dmaAdcBuffer[11])/3;
    raw_ch2Current = (dmaAdcBuffer[1]+dmaAdcBuffer[5]+dmaAdcBuffer[9])/3;
    // Add value from DMA buffer to running average (for smooth performance).
    ch1Voltage.reading(raw_ch1Voltage);
    ch2Current.reading(raw_ch2Current);
    ch2Voltage.reading(raw_ch2Voltage);
    ch1Current.reading(raw_ch1Current);
    
  }
}

void initializeHAL(){
  HAL_Init();
  MX_GPIO_Init();
  MX_DMA_Init();
  MX_ADC1_Init();
  HAL_ADC_Start(&hadc1);
  HAL_ADC_Start(&hadc2);
  HAL_ADC_Start_DMA(&hadc1, dmaAdcBuffer, 12);
}

I have tried to change the PinMap setting on "variants//Generic_F103Cx", like this :

Code: Select all

#ifdef HAL_ADC_MODULE_ENABLED
WEAK const PinMap PinMap_ADC[] = {
  {PA_0,  ADC1,  STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 0, 0)}, // ADC1_IN0
  // {PA_0,  ADC2,  STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 0, 0)}, // ADC2_IN0
  {PA_1,  ADC1,  STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 1, 0)}, // ADC1_IN1
  // {PA_1,  ADC2,  STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 1, 0)}, // ADC2_IN1
  {PA_2,  ADC1,  STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 2, 0)}, // ADC1_IN2
  // {PA_2,  ADC2,  STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 2, 0)}, // ADC2_IN2
  {PA_3,  ADC1,  STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 3, 0)}, // ADC1_IN3
  // {PA_3,  ADC2,  STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 3, 0)}, // ADC2_IN3
  {PA_4,  ADC1,  STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 4, 0)}, // ADC1_IN4
  // {PA_4,  ADC2,  STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 4, 0)}, // ADC2_IN4
  {PA_5,  ADC1,  STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 5, 0)}, // ADC1_IN5
  // {PA_5,  ADC2,  STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 5, 0)}, // ADC2_IN5
  //{PA_6,  ADC1,  STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 6, 0)}, // ADC1_IN6
  {PA_6,  ADC2,  STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 6, 0)}, // ADC2_IN6
  //{PA_7,  ADC1,  STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 7, 0)}, // ADC1_IN7
  {PA_7,  ADC2,  STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 7, 0)}, // ADC2_IN7
  {PB_0,  ADC1,  STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 8, 0)}, // ADC1_IN8
  // {PB_0,  ADC2,  STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 8, 0)}, // ADC2_IN8
  //{PB_1,  ADC1,  STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 9, 0)}, // ADC1_IN9
  {PB_1,  ADC2,  STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 9, 0)}, // ADC2_IN9
  {NC,    NP,    0}
};
#endif
but no luck

My board is BluePill and i use STM32Core

{UPDATE} : the DMA actually crashes on HAL_ADC_Start(&hadc2); as well.
HAL_ADCEx_Calibration_Start(&hadc2) too.
by Eldi4 » Fri Jul 24, 2020 12:16 pm
[UPDATE] : After reading some reference manual (i should have read it before programming these actually lol), i think i should use injected ADC, while the ADC is busy reading voltage and current, trigger an injected ADC request, when injected channel is triggered the ADC abort all of its current conversion and prioritize the injected channel. The injected channel has it's own register so the converted value is not interfering with the ADC with DMA and corrupts the DMA buffer.
I will come back after trying to implement this...,

[UPDATE] : Got it to work, by implementing injection mode adc on the temperature reading.
Go to full post
Eldi4
Posts: 22
Joined: Fri Dec 20, 2019 8:10 am
Answers: 1
Location: Kediri, Indonesia

Re: Using DMA ADC in combination with normal ADC?

Post by Eldi4 »

[UPDATE] : After reading some reference manual (i should have read it before programming these actually lol), i think i should use injected ADC, while the ADC is busy reading voltage and current, trigger an injected ADC request, when injected channel is triggered the ADC abort all of its current conversion and prioritize the injected channel. The injected channel has it's own register so the converted value is not interfering with the ADC with DMA and corrupts the DMA buffer.
I will come back after trying to implement this...,

[UPDATE] : Got it to work, by implementing injection mode adc on the temperature reading.
Post Reply

Return to “General discussion”