STM32 CubeMX “Timer + ADC + DMA”

15 Jan

This is a simple write-up so I don’t have to figure it out again next time. The goal is to setup a periodic timer which starts an ADC measurement on the background using DMA. I’m using a NUCLEO-F303RE development board.

Timer configuration

The STM32F303RE is configured to put 72MHz at TIM4. To generate events at 10Hz, a prescaler of 7200-1 is used with a counter period of 1000-1. After the prescaler, the frequency is 10kHz. The counter reaches 1000 after 0.1 second, after which the value is reloaded. An important setting here is the “Trigger Event Selection TRGO: Update Event”. This will be used to trigger the ADC.

ADC configuration

I have selected 5 channels (IN3 – IN7) on ADC2 which should all be measured in one go.

In the ADC configuration, I use 12-bit resolution. DMA Continuous Requests is enabled, because otherwise it will only measure on the first trigger from the timer. The number of conversions is set to 5, because I am measuring 5 channels. Each channels is configured individually in the ‘Rank’-dropdown.

The External Trigger Conversion Source is set to “Timer 4 Trigger Out Event”, which corresponds to the previously mentioned timer configuration. This way, the ADC will be started every 0.1 seconds.

To do this using DMA, the DMA is configured as follows. Data Width is chosen Half Word (16-bits), since the ADC is configured at 12-bit. Mode Circular is enabled because otherwise only one measurement will be done. Values of the previous measurement are overwritten.

Code

After generating the code with CubeMX, the following lines are important. First of all, a buffer for DMA:

/* USER CODE BEGIN 0 */
volatile uint16_t adc_buffer[5] = {0};

Just before the main loop, start the timer and DMA:

/* USER CODE BEGIN 2 */
HAL_ADC_Start_DMA(&hadc2, (uint32_t*)&adc_buffer, 5);
HAL_TIM_Base_Start_IT(&htim4);

Somewhere down in main.c, add the interrupt function for a completed ADC conversion:

/* USER CODE BEGIN 4 */
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc){
  /* This is called after the conversion is completed */
}

The complete code is available on GitHub.

One Reply to “STM32 CubeMX “Timer + ADC + DMA””

  1. Hi Bart,

    Some comments:

    1. If you are not handling the ADC triggering timer interrupt, starting it with HAL_TIM_Base_Start will be more proper.

    2. As a sharing from my personal mistake, and maybe good to share with future reader, that the init seq of TIM and DMA must be in the right order, that DMA first and TIM follows, else the callback sequence of the DMA written buffer will be wrong.

    Cheers

Leave a Reply

Your email address will not be published. Required fields are marked *

Time limit is exhausted. Please reload CAPTCHA.

This site uses Akismet to reduce spam. Learn how your comment data is processed.