cancel
Showing results for 
Search instead for 
Did you mean: 

F042 ADC DMA malfunction:?? I am using a Nucleo_F042k board but will target a F042F MCU later. I'm using DMA to set up 2 ADC channels + the 3 internal ADC values. Results : 1: 2146: 2: 1668: 3: 0: 4: 0: 5: 0. Only the first is verifiable.

DIngr.1
Associate II

I have probably missed something simple.

I use CubeMx to Configure the A2D channels

  hadc.Instance = ADC1;
  hadc.Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV1;
  hadc.Init.Resolution = ADC_RESOLUTION_12B;
  hadc.Init.DataAlign = ADC_DATAALIGN_RIGHT;
  hadc.Init.ScanConvMode = ADC_SCAN_DIRECTION_FORWARD;
  hadc.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
  hadc.Init.LowPowerAutoWait = DISABLE;
  hadc.Init.LowPowerAutoPowerOff = DISABLE;
  hadc.Init.ContinuousConvMode = ENABLE;
  hadc.Init.DiscontinuousConvMode = DISABLE;
  hadc.Init.ExternalTrigConv = ADC_SOFTWARE_START;
  hadc.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
  hadc.Init.DMAContinuousRequests = DISABLE;
  hadc.Init.Overrun = ADC_OVR_DATA_PRESERVED;
  if (HAL_ADC_Init(&hadc) != HAL_OK)
  {
    Error_Handler();
  }

/** Configure for the selected ADC regular channel to be converted.
  */
  sConfig.Channel = ADC_CHANNEL_8;
  sConfig.Rank = ADC_RANK_CHANNEL_NUMBER;
  sConfig.SamplingTime = ADC_SAMPLETIME_239CYCLES_5;
  if (HAL_ADC_ConfigChannel(&hadc, &sConfig) != HAL_OK)
  {
    Error_Handler();
  }
  /** Configure for the selected ADC regular channel to be converted.
  */
  sConfig.Channel = ADC_CHANNEL_9;
  if (HAL_ADC_ConfigChannel(&hadc, &sConfig) != HAL_OK)
  {
    Error_Handler();
  }
  /** Configure for the selected ADC regular channel to be converted.
  */
  sConfig.Channel = ADC_CHANNEL_TEMPSENSOR;
  if (HAL_ADC_ConfigChannel(&hadc, &sConfig) != HAL_OK)
  {
    Error_Handler();
  }
  /** Configure for the selected ADC regular channel to be converted.
  */
  sConfig.Channel = ADC_CHANNEL_VREFINT;
  if (HAL_ADC_ConfigChannel(&hadc, &sConfig) != HAL_OK)
  {
    Error_Handler();
  }
  /** Configure for the selected ADC regular channel to be converted.
  */
  sConfig.Channel = ADC_CHANNEL_VBAT;
  if (HAL_ADC_ConfigChannel(&hadc, &sConfig) != HAL_OK)
  {
    Error_Handler();

I only need to take data periodically so I use this to kick off the conversion very 3 seconds.

     if(AdcTmr == 3000)

     {

        AdcTmr = 0;

        HAL_ADC_Start_DMA(&hadc, AdcBuf, NUM_A2D_CHANS);

     }

where NUM_A2D_CHANS is the set to 5 for the number of channels to be scanned. The Callback routine is

void  HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef  *hadc)
{
   AdcRdy = FALSE;
   if(hadc->Instance == ADC1)
   {
      for(int i = 0; i < NUM_A2D_CHANS; i++)
      {
         AdcVal[i] = AdcBuf[i];
         AdcBuf[i] = 0;
      }
      AdcRdy = TRUE;
   }
}

The contents of the AdcBuf is transferred to the AdcVal buffer and printed out. as above

ADC Data: : 1: 2144: 2: 1665: 3: 0: 4: 0: 5: 0

The first value is the output of a pot and changes as the pot changes.

Channel 2 is also tied to a second pot but the value doesn't change as the pot is varied . I don't know what it represents. The last three values should be from the internal sensors put are obviously incorrect.

I've missed something.

Should I be registering a callback for the DMA instead of using the ADC_ConvCpltCallback???

Suggestions??

1 REPLY 1
DIngr.1
Associate II

I got the functionality I wanted using Interrupts.

ADC Data: : 1: 2298: 2: 3339: 3: 1670: 4: 1452: 5: 0

The first two values are tied to pots and change as I set the pot. The next two change with sample but by one or two bit. Not unexpected for an A2D. The last value is VBAT but I there may not be a VBAT connection on the Nucleo-F042k board. I'll have to check the datasheet.

I would really like to get the DMA working to save clock cycles.

Any Suggestions??