Skip to main content
Andy Pevy
Associate
June 9, 2017
Solved

ADC with DMA with SW Trigger on L486 MCU

  • June 9, 2017
  • 4 replies
  • 2203 views
Posted on June 09, 2017 at 12:06

I wish to use ADC1 to measure 6 channels and to have the results DMAd into memory.

I am using CubeMX V4.21 and I think that I have set the parameters up correctly

(See attached screen snip ADC_DMA_1 to 3.PNG)

This sequence is to be triggered by S/W to run once, terminate and then run again sometime later.

(This is in a loop for testing at the moment).

The DMA happens as I am seeing the ADC readings appear in the adc1_data array and I get the DMA half complete interrupt handler being called but not the end of sequence interrupt.

What am I doing wrong please.....

My code is :-

uint16_t adc1_data[6];

#define ADC1_BUFFER_SIZE_IN_BYTES 12

#define   ADC1_TEMP1_OFFSET                   0

#define

ADC1_TEMP2_OFFSET                    1

#define

ADC1_VBOOST_OFFSET                 2

#define

ADC1_VHLC_OFFSET                       3

#define

ADC1_INTERNAL_TEMP_OFFSET  4

#define

ADC1_VREF_OFFSET                       5

volatile bool adc1_active_flag;

void start_adc1(void)

{

   HAL_StatusTypeDef status;

   set_VDDA_PWR_EN(ANALOG_POWER_ON);

   set_nVMON_ENABLE(VMON_ENABLE_ON);

   set_nTEMP_SENSOR_PWR_EN(TEMP_SENSOR_POWER_ON);

   adc1_active_flag = TRUE;

   osDelay(2);

   status = HAL_ADCEx_Calibration_Start(&hadc1, ADC_SINGLE_ENDED);

   if(HAL_OK != status)

   {

      // Blah

   }

   status = HAL_ADC_Start_DMA(&hadc1, (uint32_t *)adc1_data, ADC1_BUFFER_SIZE_IN_BYTES);

   if(HAL_OK != status)

   {

      // Blah

   }

}

void HAL_ADC_ConvHalfCpltCallback(ADC_HandleTypeDef* hadc)

{

   static bool apapap;

   if(ADC1 == hadc->Instance)

   {

      // Voltage subsystem...

      apapap = TRUE; // <<< Gets here....

   }

   if(ADC2 == hadc->Instance)

   {

      // Blah

   }   

   if(ADC3 == hadc->Instance)

   {

      // Blah

   }

}

void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)

{

   if(ADC1 == hadc->Instance)

   {

      if(__HAL_ADC_GET_FLAG(hadc, ADC_FLAG_EOS)) // << Never gets here...

:(

      {

         // Voltage subsystem...

         adc1_active_flag = FALSE;

         set_nTEMP_SENSOR_PWR_EN(TEMP_SENSOR_POWER_OFF);

         set_nVMON_ENABLE(VMON_ENABLE_OFF);

      }

      if(__HAL_ADC_GET_FLAG(hadc, ADC_FLAG_EOC))

      {

         // Voltage subsystem...

         adc1_active_flag = FALSE;

         set_nTEMP_SENSOR_PWR_EN(TEMP_SENSOR_POWER_OFF);

         set_nVMON_ENABLE(VMON_ENABLE_OFF);

      }

   }

   if(ADC2 == hadc->Instance)

   {

      // Blah

   }

   if(ADC3 == hadc->Instance)

   {

      // Blah

   }

}

// freeRTOS task...

//

/* Infinite loop */

for(;;)

{

   if(MODE_BLAH == my_mode)

   {

   osDelay(1000);

   // We have been woken so do something...

   start_adc1();

   // Block until the scan has completed...

   // Better way would be to use a mutex block here... [AP]

   while(TRUE == read_adc1_active_flag())

   {

      ;

   }

   len = sprintf(adc1_test, 'T1:%d\tT2%dVB:%d\tVHLC:%d\tMCU_Temp:%d\tVref:%d\n',

   adc1_data[ADC1_TEMP1_OFFSET],

   adc1_data[ADC1_TEMP2_OFFSET],

   adc1_data[ADC1_VBOOST_OFFSET],

   adc1_data[ADC1_VHLC_OFFSET],

   adc1_data[ADC1_INTERNAL_TEMP_OFFSET],

   adc1_data[ADC1_VREF_OFFSET]);

   // Trace the output...

   str_trace('ADC Vals:%s', adc1_test);

   }

}
    This topic has been closed for replies.
    Best answer by Zt Liu
    Posted on June 09, 2017 at 12:20

    Hi, 

    as in your second png, dma packet size is half wold, 16bit, 

    You can't use 

    ADC1_BUFFER_SIZE_IN_BYTES;

    Probably, it's

    #define ADC_CHANNEL_CNT   6

    status = HAL_ADC_Start_DMA(&hadc1, (uint32_t *)adc1_data, ADC_CHANNEL_CNT)

    by the way, if you check you adc buffer, you'll probably see those 6 adc data already lying there.

    Good Luck!

    4 replies

    Zt Liu
    Zt LiuBest answer
    Senior III
    June 9, 2017
    Posted on June 09, 2017 at 12:20

    Hi, 

    as in your second png, dma packet size is half wold, 16bit, 

    You can't use 

    ADC1_BUFFER_SIZE_IN_BYTES;

    Probably, it's

    #define ADC_CHANNEL_CNT   6

    status = HAL_ADC_Start_DMA(&hadc1, (uint32_t *)adc1_data, ADC_CHANNEL_CNT)

    by the way, if you check you adc buffer, you'll probably see those 6 adc data already lying there.

    Good Luck!

    Andy Pevy
    Andy PevyAuthor
    Associate
    June 9, 2017
    Posted on June 09, 2017 at 12:29

    Brilliant, that did the trick..

    Thanks for the answer.

    But...

    I draw your attention to the Doxygen header for the relevant function :-

    /**

    * @brief Enable ADC, start conversion of regular group and transfer result through DMA.

    * @note Interruptions enabled in this function:

    * overrun (if applicable), DMA half transfer, DMA transfer complete.

    * Each of these interruptions has its dedicated callback function.

    * @note Case of multimode enabled (when multimode feature is available): HAL_ADC_Start_DMA()

    * is designed for single-ADC mode only. For multimode, the dedicated

    * HAL_ADCEx_MultiModeStart_DMA() function must be used.

    * @param hadc: ADC handle

    * @param pData: Destination Buffer address.

    * @param Length: Length of data to be transferred from ADC peripheral to memory (in bytes) 

    * @retval HAL status.

    */

    HAL_StatusTypeDef HAL_ADC_Start_DMA(ADC_HandleTypeDef* hadc, uint32_t* pData, uint32_t Length)

    The Length argument does specifically  say 'in BYTES' not 'Number of transfers required'..

    Can this be updated sometime soon so others don't fall into the same trap.

    Andy

    Zt Liu
    Senior III
    June 9, 2017
    Posted on June 09, 2017 at 12:33

    * @param Length: Length of data to be transferred from ADC peripheral to memory (

    in bytes

    )

    This description is definitely incorrect. 

    :((

    ST Technical Moderator
    June 14, 2017
    Posted on June 14, 2017 at 12:16

    Hi

    Pevy.Andy

    and

    Liu.Zhitai

    ,

    I highlighted internally your feedback about the incorrect description.

    Regards

    Imen

    In order to give better visibility on the answered topics, please click on 'Best answer' on the reply which solved your issue or answered your question. Thanks
    Evgeny Erlihman
    Associate III
    November 2, 2017
    Posted on November 02, 2017 at 14:48

    Hi

    DAHMEN.IMEN

    ,

    I am using the NUCLEO-H743ZI with a project generated by Cube 4.0. TheHAL_ADC_Start_DMA documentation states:

    @param Length: Length of data to be transferred from ADC peripheral to memory (in bytes)

    Is it still a documentation bug or is it intentional this time?

    Thanks,

    Evgeny