cancel
Showing results for 
Search instead for 
Did you mean: 

ADC with DMA with SW Trigger on L486 MCU

Andy Pevy
Associate
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);

   }

}
1 ACCEPTED SOLUTION

Accepted Solutions
Zt Liu
Senior III
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!

View solution in original post

5 REPLIES 5
Zt Liu
Senior III
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
Associate
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
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. 

:((

Imen.D
ST Employee
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

When your question is answered, please close this topic by clicking "Accept as Solution".
Thanks
Imen
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