Posted on August 28, 2018 at 9:00 PM
This guide will illustrate using the NUCLEO-L476RG ADC with DMA and conversion trigged on Timer. 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 cnfiguration boxes.
The document will follow the steps for configuring the NUCLEO-L476RG and setting up the project to:
I have found working out the relationship between the Registers and the CubeMX check boxes to be a little confusing at times -- constant swithing between the HAL manaul, the refence manaual, cubeMX and the generated code when starting a project -- 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.
The STM32L476je datasheet tells us the STM32L4 ADC is
For the Nucleo there many I/O available for the ADC so reference the STM32L476 reference manual the STM32L4 datasheet and Nucleo User Manual are write youself a table with the connector pin (nucleo), port and pin (stm32l4 gpio) and the ADC channel (ADC). The main conenctions I use are the following:
In this section we choose which channels which will be sampled. Once selected ensure the pin in green and lists only ONE ADC, ie. ADC1_IN1. If you are NOT starting from a new proejct this is important as some configureation may remian on the pin and will need to be reset.
A timer will be used to trigger the ADC concersion so we need to set that up. There are a number of Timers (but not all) that can be used for conversion start, refer to reference manual or easier look at the ADC configuration in next section for the list.
For this project I have used Output Comapare CH2 and not Output Compare No Output only so I can attach a scope to pin to see the start of the ADC conversions. This is helpful for debugging and checking the timer frequency.
There are three conversion modes, single, scan and discontinious that are best depicted in the following image.
The selection of the mode is achieved by the combination of the following settings:
Enabled means DMA not need to be restarted after each transfer and therefore will be ready to run again on next trigger
The generated code hadc1.Init.DMAContinuousRequests = ENABLE sets BIT1 DMACFG in the ADC configuration register (ADC_CFGR) to circualr mode selected (insted of one shot mode).
Specify which EOC (End Of Conversion) flag is used for conversion by polling and interruption: end of unitary conversion or end of sequence conversions
Set to end of sequence, for this case, I toggle the onbaord LED to show that conversion is complete.
Select the behavior in case of overrun: data overwritten or preserved
Select overwrite, if select preserved you will need to manage reset by reading the ADC regualr Data Register (ADC_DR) after each EOC. If not cleared the OVR error is raised and DMA transfers stop. Refer to RM0351 p543.
Needed to setup the coversions
The L4 ADC supports hardware oversampling, 2,4,8,16,32,128 and 256 times without CPU support. The converted data is accumulated in a register and the outut can be processed by the data shifter and the truncater. (source: STM) The two important settings for this exampler are:
The selection of the Reference Soruce can provide some confusion. Here we use a comapre event, as setup in the Pinout section. The selection in the ADC configuration needs to match the Pinout TImer configuration and later in how the timer is started with the generated code. Other than which timer there are
Refer to timer configurations to understand the events, getting this wrong will mean the conversion will not start as expected.
DMA setting will copy data from ADC regiser to SRAM location with use of CPU.
Options are Circular or Normal. Here I set up circular so that data a overwritten on each scan. The size of the buffer is set in code. The DMA controller will auto increment the buffer pointer for each channel read.
The DMA controller can effiienclty pack ADC readings, for example only reading 8bit can save as byte. When startign teh DMA ADC in code need to make sure the buffer size matches.
I use the the ADC global interupt mainly for the EOC interupt.
As the ADC start is triggered from Timer 2 Output Comapre on the rising edge (set up above) we need to configure the timer to be output compare, toggle on match, and set the desired frequency. Here I have set 100ms, which will trigger the ADC at 200ms because ADC is set to trigger on rising edge only. This can be seen on the scope image below.
Setting the Prescaler and Reload counter for precise frequncy is simplified by using a free tool from MikroElektronika : Just enter you clock rate and desired frequency and it will prove the PSC and reload.
For testing having the timer output can help with debugging. Here is a plot of the timer, and also I have set the User LED to toggle on ADC conversion complete interupt so confirm the ADC operation.
To get it working
/* USER CODE BEGIN PV */
/* Private variables ---------------------------------------------------------*/
uint16_t adc1Data[3];
int main(void)
{
...
/* USER CODE BEGIN 2 */
HAL_TIM_OC_Start(&htim2, TIM_CHANNEL_2);
HAL_ADC_Start_DMA(&hadc1, (uint32_t*)&adc1Data, 3);
Note :
To lessen the content I have ommitted any real processing of the data. The results of the conversion can be view on the ST LINK debugger. For this example I just toggle the User LED to inducte the the intercupt is working and therefore a ADC conversion is also working.
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc){
HAL_GPIO_TogglePin(LD2_GPIO_Port, LD2_Pin);
}
The result is an ADC conversion of three channel on the Timer Trigger. The following scope image (also above) shows when the timer triggers the conversion and then when the conversion is compelted. With that it is up to me/you to do something real with the ADC data.
The guide has stepped throguh process of creating a project to read three ADC channels using DMA and timers. 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.
The following are the documents referenced in this guide and the key documents for any project using this STM32L476 microprocessor.