STM32L4 ADC Conversion Triggers

by Matthew Watson


Posted on August 6, 2018 at 9:00 PM


This guide will illustrate using the difference ADC conversion triggers on the NUCLEO-L476RG. CubeMX is used to generate the project files. It aims to fill the gap between the manuals on the HAL drivers, the STM32L4 referece manual and the CubeMX configuration boxes.

Summary

The document will follow the steps for configuring the NUCLEO-L476RG and setting up the project to read IN1 on ADC1 using the following triggers:

I have found working out the relationship between the Registers and the CubeMX check boxes to be a little confusing at times so this document is wrttien as a guide mainly for myself in the hope that later it will jog my memory but hopfully others might find it useful too.

Regular Conversion launched by Software

CubeMX Pinout

Choose which channels which will be sampled, for the example I use only single channel IN1. This is the only Pin Configuratin needed for Softare Converison. Dont be fooled by Conversion Trigger this is for Pinout configuration that is if you want to trigger on a pin input.

Select the ADC channels.

CubeMX Configuration

In ADC configuration need to select External conversion trigger source and also ensure Continious Conversion Mode is DISABLED, if it is enabled the trigger will not matter and the ADC will sample continiously.

ADC configuration

I want to generate an interupt at the end of conversion (EOC) so I will enable the interupt in NVIC tab. If instread you want to POLL for the end of conversion this is not needed.

ADC NVIC

Generate the code and make the software chages

  • Start the ADC
  • Add code to handle the ADC conversion complete interupt

The software

With Software trigger the ADC can start with

  • HAL_ADC_Start(&hadc1) then check the EOC or
  • HAL_ADC_Start_IT(&hadc1) then on EOC will trigger an interrupt if set

int main(void)
{
...
/* USER CODE BEGIN 2 */ 
  HAL_ADC_Start(&hadc1);
  if (HAL_ADC_PollForConversion(&hadc1, 10) != HAL_OK)
  {
    /* End Of Conversion flag not set on time */
    Error_Handler();
  }
  /* Check if the continous conversion of regular channel is finished */
  if ((HAL_ADC_GetState(&hadc1) & HAL_ADC_STATE_REG_EOC) == HAL_ADC_STATE_REG_EOC)
  {
    /* Get the converted value of regular channel*/
    uint32_t value = HAL_ADC_GetValue(&hadc1);
  }

OR start the ADC using IT and then configure the interupt handler

int main(void)
{
...
/* USER CODE BEGIN 2 */ 
  HAL_ADC_Start_IT(&hadc1); 

Setup the ADC conversion complete callback, good practise to check that the interupt handler has been generated in stm32l4xx_it.c.

void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc){
uint32_t value = HAL_ADC_GetValue(&hadc1);
}

That is it, you have a conversion triggered by software, although not doing anything with the value.

Conversion by Timer Out event (TRGO)

CubeMX Pinout

As per above for the ADC, but here I add a timer. Timer1, not that I am not setting an output.

Timer Pinout configuration

CubeMX Configuration

ADC

In ADC configuration need to select External conversion trigger source and also ensure Continious Conversion Mode is DISABLED, if it is enabled the trigger will not matter and the ADC will sample continiously.

ADC configuration

I want to generate an interupt at the end of conversion (EOC) so I will enable the interupt in NVIC tab. If instread you want to POLL for the end of conversion this is not needed.

ADC NVIC

TIM1

In the timer configuration need to select when at pulse will be sent to TRGO. Here I have selected Update Event, counter overflow. The frequecny of the pulse configured by PSC and ARR.

Timer1 Configuration

The software

Generate the code and make the software chages

  • Start the ADC
  • Start the Timer
  • Add code to handle the ADC conversion complete interupt

int main(void)
{
...
    /* USER CODE BEGIN 2 */
    HAL_TIM_Base_Start(&htim1);
  
    if (HAL_ADCEx_Calibration_Start(&hadc1, ADC_SINGLE_ENDED) !=  HAL_OK)
    {
        /* ADC Calibration Error */
        Error_Handler();
    }
    HAL_ADC_Start_IT(&hadc1);

Setup the ADC conversion complete callback, good practise to check that the interupt handler has been generated in stm32l4xx_it.c.

void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc){
    uint32_t value = HAL_ADC_GetValue(&hadc1);
}

That is it, you have a conversion triggered by the Update Event of Timer1 through TRGO, although not doing anything with the value. Using TRGO2 is exactl the same process, just selection TRGO2:

Timer1 Configuration
Timer1 Configuration

Conversion launched by Timer Capture Compare 1 Event

CubeMX Pinout

As per above for the ADC, but changes to Timer are need. Again note that no output is being generated but I am using a Channel for a Compare Capture event generation. The channel setup needs to match that set it the ADC configuratio we are using Capture Compare 1 so need to set up Channel1.

Select the Timer Compare

CubeMX Configuration

In ADC configuration need to select External conversion trigger source and also ensure Continious Conversion Mode is DISABLED, if it is enabled the trigger will not matter and the ADC will sample continiously.

ADC configuration

I want to generate an interupt at the end of conversion (EOC) so I will enable the interupt in NVIC tab. If instread you want to POLL for the end of conversion this is not needed.

ADC NVIC

TIM1

Here we setup the Comapre Match settings. Remeber to set pulse to be less that the AutoReload setting, else it will ever be reached and will not set a trigger.

Timer1 Configuration

The software

Generate the code and make the software chages

  • Start the ADC
  • Start the Timer in OC mode
  • Add code to handle the ADC conversion complete interupt

int main(void)
{
...
    /* USER CODE BEGIN 2 */
    HAL_TIM_OC_Start(&htim1);
  
    if (HAL_ADCEx_Calibration_Start(&hadc1, ADC_SINGLE_ENDED) !=  HAL_OK)
    {
        /* ADC Calibration Error */
        Error_Handler();
    }
    HAL_ADC_Start_IT(&hadc1);

NOTE: I don't start the TIM with _IT as I am not using the interupt handler.

Setup the ADC conversion complete callback, good practise to check that the interupt handler has been generated in stm32l4xx_it.c.

void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc){
    uint32_t value = HAL_ADC_GetValue(&hadc1);
}

That is it, you have a conversion triggered the output compare event on Timer 1. Set a break point on the ADC callback, or toggle the led inside the callback oand or change the timer to provide an output to a change to see the covnersion timing.

Conclusion

The guide has stepped throguh process of setting the various triggers for ADC conversion. These features of the low cost Nucleo baords have proven to be are very powerful and convenient for a number of my projects and hope this guide will help you to realse the same.

Any questions or suggestions feel free use the contact me.

Reference

The following are the documents referenced in this guide and the key documents for any project using this STM32L476 microprocessor.