Pages

mercredi 3 septembre 2014

Using ADC with DMA on STM32 micrcontroller


The most received cry of help that I get form many people is about how using DMA with ADC for a continuous conversion of analog sensors inputs. So I made the decision to share the needed steps to configure it ( and also to avoid the duplication of my answer each time).

I will take advantage of STM32Cube project to make it easy and I admit that you have already STM32CubeMX software tool and the installed STM32CubeF4 Firmware. If it is ok, let's start then and for other people they can follow links to setup the tool and the firmware.







 Open STM32CubeMX tool and click on 'new project' I chose STM32F439BITx microcontroller from the list. You can chose your own if you are using a specific board. I guess that all ADCs in STM32 microcontrollers have this feature.













After that, form the Pinout view of the tool expand ADC peripheral and select the three internal channels (Temperature / Vref and Vbat ). You can select your own but I used these three channels as a demonstration in this tutorial.

In the second case, all what you have is to connect your analog inputs to the channels pins. Selected channel are colored in green in the microcontroller or you can operate conversely by selecting first your pin as ADC input by a right click on it. (exp PA0)















Now it's time to configure the ADC to operate as we want, (yes yes and the DMA too ;) ). So Click on ADC and add three regular channel configuration to be converted. Also don't forget to enable Scan Mode and continuous mode to have a continuous conversion of the three configured channels.











 Switch now to the 'DMA Settings' tab, add a DMA request by selecting the stream and the priority. Also enable the increment of the memory because we will store all converted values in a array. The used mode is the circular mode because we will have a continues transfer of a word (data width).





Click Ok, generate a project and open it (I use IAR wokbench you have the possibility to chose Keil or TrueSTUDIO too). We will add some extra code to complete our demo: In the main.c file we will declare a 32 bit array and we will start the ADC and the DMA by calling HAL_ADC_Start() and HAL_ADC_Start_DMA(). After each conversion the value is transferred form the data register of the ADC to the array and the DMA will increment the index automatically.
1:  /* USER CODE BEGIN PFP */  
2:  uint32_t ADC1ConvertedValues[1024];  
3:  /* USER CODE END PFP */  
4:  int main(void)  
5:  {  
6:   /* MCU Configuration----------------------------------------------------------*/  
7:   /* Reset of all peripherals, Initializes the Flash interface and the Systick. */  
8:   HAL_Init();  
9:   /* Configure the system clock */  
10:   SystemClock_Config();  
11:   /* Initialize all configured peripherals */  
12:   MX_GPIO_Init();  
13:   MX_DMA_Init();  
14:   MX_ADC1_Init();  
15:   /* USER CODE BEGIN 2 */  
16:   // -- Enables ADC and starts conversion of the regular channels.  
17:   if( HAL_ADC_Start(&hadc1) != HAL_OK)  
18:    return 0;  
19:   // -- Enables ADC DMA request  
20:   if (HAL_ADC_Start_DMA(&hadc1, (uint32_t*)ADC1ConvertedValues, 2048) != HAL_OK)  
21:    return 0;  
22:   /* USER CODE END 2 */  
23:   /* Infinite loop */  
24:   while (1){}  
25:  }  

All converted values are transferred and stored in ADC1ConvertedValues which is an array of 1ko of size. Values are stored in the order of conversion ( Temp sensor then Vref then Vbat ).

This is a Live watch of ADC1ConvertedValues array while demo execution.