In this tutorial, we’ll discuss the STM32 ADC Channel Select and how to switch between different ADC channels using HAL functions. You’ll learn how to implement STM32 ADC Multi-Channel
The practical example we’ll implement in this tutorial is an STM32 LED dimmer using multiple potentiometers on multiple analog input pins and multiple PWM outputs to control the brightness of some LEDs. We’ll read the multiple analog input channels (regular group) in single-conversion mode using the ADC Channel select (switch) method. Without further ado, let’s get right into it!
Table of Contents
- STM32 ADC Channel Select
- STM32 ADC Multi-Channel Without DMA
- STM32 ADC Multi-Channel Select (No Scan) Example
- STM32 STM32 ADC Multi-Channel Without DMA
- Wrap Up
STM32 ADC Channel Select
While working with the STM32 ADC with multiple channels being used, you can use the STM32 ADC Scan Mode which will automatically select and convert every single channel in the scan’s regular group of channels. Alternatively, you can disable the scan mode and manually (with software) switch between the ADC channels and convert each one as needed per your application requirements.
Here is how to manually select and switch between 4x different ADC channels and store the conversion result of the 4 channels into an array.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
uint16_t i = 0, AD_RES[4]; ADC_ChannelConfTypeDef ADC_CH_Cfg = {0}; uint32_t ADC_Channels[4] = {ADC_CHANNEL_6, ADC_CHANNEL_7, ADC_CHANNEL_8, ADC_CHANNEL_9}; int main(void) { HAL_Init(); SystemClock_Config(); MX_GPIO_Init(); MX_ADC1_Init(); ADC_CH_Cfg.Rank = ADC_REGULAR_RANK_1; ADC_CH_Cfg.SamplingTime = ADC_SAMPLETIME_1CYCLE_5; while (1) { for(i=0; i<4; i++) { ADC_CH_Cfg.Channel = ADC_Channels[i]; // Select The ADC Channel [i] HAL_ADC_ConfigChannel(&hadc1, &ADC_CH_Cfg); // Configure The Selected ADC Channel HAL_ADC_Start(&hadc1); // Start ADC Conversion @ Selected Channel HAL_ADC_PollForConversion(&hadc1, 1); // Poll The ADC Channel With TimeOut = 1mSec AD_RES[i] = HAL_ADC_GetValue(&hadc1); // Read The ADC Conversion Result } } } |
Using the built-in ADC scan mode is more efficient in terms of CPU time and ADC’s throughput overall. However, using the manual channel selection and conversion method (the code example above) that we’ll explain in this tutorial is very flexible and allows achieving any custom applications’ requirements. The STM32 ADC Scan Mode is illustrated in detail in the tutorial linked below (with examples using polling, interrupt, and DMA).
This tutorial will give you more in-depth information about the STM32 ADC Scan Mode and how to read multi-channels of the ADC regular group using (polling, interrupt, and DMA) in single-conversion mode with code examples for each configuration.
STM32 ADC Multi-Channel Without DMA
In this tutorial, we’ll explore the STM32 ADC Multi-Channel Without DMA operation in single-conversion (one-shot) mode. In this mode, the ADC will select a desired channel of the regular group and start the conversion process. Upon conversion completion, the application can poll for the ADC result or get an interrupt or DMA notification instead. Then, the ADC can switch to (select) another channel of the regular group and repeat the conversion process.
This manual channel selection & conversion enables us to sample different ADC channels with different periodicities (sampling rates). Here is an illustrative diagram of how this process works.
For the multi-channel operation of the STM32 ADC, we can use the auto “scan” mode instead of manually switching between the regular group of channels as show in this tutorial. To learn more about the STM32 ADC Multi-Channel scan mode you can check the following tutorials:
STM32 ADC Multi-Channel Select (No Scan) Example
In this example project, we’ll create an STM32 LED Dimmer using ADC & PWM to read multiple analog inputs from 4x potentiometers to control the brightness of 4x PWM outputs going to 4x LEDs. This demo will run the STM32 ADC in multi-channel single-conversion mode without DMA (no scan).
- Set up a new project as usual with system clock @ 72MHz
- Set up 4x Analog Input Pins (Channel 6, 7, 8, and 9) – The 4x Pot. Pins
- Set up Timer2 in PWM mode with output on channels 1:4 (The 4x LED Pins)
STM32 STM32 ADC Multi-Channel Without DMA
In this LAB, our goal is to build a system that initializes multiple ADC analog input pins (4x channels: 6-9). Also, configure a timer module to operate in PWM mode with 4x outputs on channels 1-4 (4x LED pins).
Then, we can select the ADC regular group channels one by one to start the conversion of each channel sequentially, get the ADC results, map them to the PWM duty cycle registers, and repeat the whole process over and over again.
And now, let’s build this system step-by-step
Step #1
Open STM32CubeMX, create a new project, and select the target microcontroller.
Step #2
Configure The ADC1 Peripheral, Enable the regular Channels: 6-9, and set the number of regular conversions to 1. You’ll find that the analog channel has these default configurations which happens to be ok for us in this example project.
Step #3
Configure Timer2 To Operate In PWM Mode With Output On CH1-4.
Step #4
Go to the RCC clock configuration page and enable the HSE external crystal oscillator input.
Step #5
Go to the clock configurations page, and select the HSE as a clock source, PLL output, and type in 72MHz for the desired output system frequency. Hit the “ Enter” key, and let the application solve for the required PLL dividers/multipliers to achieve the desired clock rate.
Step #6
Name & Generate The Project Initialization Code For CubeIDE or The IDE You’re Using.
STM32 ADC Multi-Channel Without DMA Example Code
Here is The Application Code For This LAB (main.c)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 |
/* * LAB Name: STM32 ADC Multi-Channel Without DMA * Author: Khaled Magdy * For More Info Visit: www.DeepBlueMbedded.com */ #include "main.h" ADC_HandleTypeDef hadc1; TIM_HandleTypeDef htim2; uint16_t i = 0, AD_RES[4]; ADC_ChannelConfTypeDef ADC_CH_Cfg = {0}; uint32_t ADC_Channels[4] = {ADC_CHANNEL_6, ADC_CHANNEL_7, ADC_CHANNEL_8, ADC_CHANNEL_9}; void SystemClock_Config(void); static void MX_GPIO_Init(void); static void MX_ADC1_Init(void); static void MX_TIM2_Init(void); int main(void) { HAL_Init(); SystemClock_Config(); MX_GPIO_Init(); MX_ADC1_Init(); MX_TIM2_Init(); HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_1); HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_2); HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_3); HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_4); ADC_CH_Cfg.Rank = ADC_REGULAR_RANK_1; ADC_CH_Cfg.SamplingTime = ADC_SAMPLETIME_1CYCLE_5; while (1) { for(i=0; i<4; i++) { ADC_CH_Cfg.Channel = ADC_Channels[i]; // Select The ADC Channel [i] HAL_ADC_ConfigChannel(&hadc1, &ADC_CH_Cfg); // Configure The Selected ADC Channel HAL_ADC_Start(&hadc1); // Start ADC Conversion @ Selected Channel HAL_ADC_PollForConversion(&hadc1, 1); // Poll The ADC Channel With TimeOut = 1mSec AD_RES[i] = HAL_ADC_GetValue(&hadc1); // Read The ADC Conversion Result } TIM2->CCR1 = (AD_RES[0]<<4); // Map The ADC_RES1 To PWM1 DutyCycle TIM2->CCR2 = (AD_RES[1]<<4); // Map The ADC_RES2 To PWM2 DutyCycle TIM2->CCR3 = (AD_RES[2]<<4); // Map The ADC_RES3 To PWM3 DutyCycle TIM2->CCR4 = (AD_RES[3]<<4); // Map The ADC_RES4 To PWM4 DutyCycle HAL_Delay(1); } } |
Wiring
I know that it may look messy, but there isn’t too much about it. These are only 4x LEDs and 4x potentiometers connected to the corresponding GPIO pins on the STM32 blue pill board.
STM32 ADC Multi-Channel Without DMA Example Testing
Required Parts For STM32 Examples
All the example Code/LABs/Projects in this STM32 Series of Tutorials are done using the Dev boards & Electronic Parts Below:
QTY. | Component Name | Amazon.com | AliExpress | eBay |
1 | STM32-F103 BluePill Board (ARM Cortex-M3 @ 72MHz) | Amazon | AliExpress | eBay |
1 | Nucleo-L432KC (ARM Cortex-M4 @ 80MHz) | Amazon | AliExpress | eBay |
1 | ST-Link V2 Debugger | Amazon | AliExpress | eBay |
2 | BreadBoard | Amazon | AliExpress | eBay |
1 | LEDs Kit | Amazon & Amazon | AliExpress | eBay |
1 | Resistors Kit | Amazon & Amazon | AliExpress | eBay |
1 | Capacitors Kit | Amazon & Amazon | AliExpress & AliExpress | eBay & eBay |
1 | Jumper Wires Pack | Amazon & Amazon | AliExpress & AliExpress | eBay & eBay |
1 | Push Buttons | Amazon & Amazon | AliExpress | eBay |
1 | Potentiometers | Amazon | AliExpress | eBay |
1 | Micro USB Cable | Amazon | AliExpress | eBay |
★ Check The Links Below For The Full Course Kit List & LAB Test Equipment Required For Debugging ★
Download Attachments
You can download all attachment files for this Article/Tutorial (project files, schematics, code, etc..) using the link below. Please consider supporting our work through the various support options listed in the link down below. Every small donation helps to keep this website up and running and ultimately supports the whole community.
Wrap Up
In conclusion, we’ve explored how to manually select and convert the STM32 ADC Channels (regular group) without using the auto “scan mode” or the DMA for reading this multi-channel configuration.
You can build on top of the examples provided in this tutorial and/or explore the other parts of the STM32 ADC tutorials series below for more information about the other STM32 ADC operating modes and conversion schemes.