External Trigger Source Selection in STM32 ADC
In this tutorial, we’ll explore how to use external triggers to start ADC conversions on STM32 microcontrollers. Instead of relying on software to initiate each conversion, a hardware trigger, usually from a timer, can control exactly when the ADC samples the input. You’ll learn how to configure timers, select the right trigger source, and synchronize multiple channels for precise, consistent data acquisition.
Recommended Resources:
This is the 7th tutorial in the STM32 ADC series. In the previous tutorials we covered how to configure the ADC in STM32 F1, F4 and H7 series and how to use it in the single channel polling, interrupt and DMA modes to read the potentiometer data. We have also covered the Multiple channels in DMA Normal Mode, Circular Mode and Multiple Channels with DMA.
You Do not need to go through the previous tutorials in order to understand this one. But a basic knowledge of ADC configuration is needed.

Why Do We Need an External Trigger for ADC?
In most STM32 ADC tutorials, conversions are often started by software. While this works for simple applications, it has limitations in terms of timing precision and CPU load. Using an external trigger — typically generated by a hardware timer, PWM, or another peripheral — allows the ADC to start sampling and converting automatically at precise, consistent intervals. This is especially important in real-time applications, such as motor control, sensor fusion, or signal processing, where consistent timing and synchronization are critical.
External triggers ensure that ADC conversions are not affected by software delays, interrupt routines, or varying CPU load. When combined with DMA, this approach allows high-speed, continuous data acquisition without occupying the processor, freeing it for other tasks.
For Precise and Consistent Sampling Intervals
Software-triggered conversions depend on the CPU executing instructions, which may vary slightly due to interrupts, background tasks, or code execution delays. In contrast, hardware-triggered ADCs use a dedicated timer or peripheral signal, ensuring that each conversion starts exactly at the programmed interval. This guarantees uniform sampling, which is critical for applications like waveform analysis, audio data capture, or any measurement requiring accurate timing.
To Synchronize ADC with Other Peripherals
When ADC sampling needs to be coordinated with other peripherals, such as PWM outputs for motor control or timer events in a control loop, an external trigger ensures perfect synchronization. For example, you can configure a timer to generate a trigger signal at the exact moment a PWM pulse occurs, ensuring that the ADC captures the signal at a consistent point in the cycle.
To Reduce CPU Overhead
With software-triggered ADC, the CPU must explicitly start each conversion. This adds overhead and may limit the maximum achievable sampling rate. Using an external trigger in combination with DMA in circular mode offloads the CPU completely: conversions and data transfers occur automatically, allowing the processor to focus on other critical tasks.
To Improve Multi-Channel ADC Timing
When scanning multiple ADC channels in sequence, external triggers ensure that each set of channel conversions starts at the same instant every cycle. This guarantees consistent timing across channels and reduces timing jitter, which is essential for synchronized sensor readings or real-time signal processing.
The table below summarises the differences between Software Start and External trigger source.
| Feature | Software Start | External Trigger |
|---|---|---|
| Timing Precision | Varies depending on CPU execution and interrupts | Fixed and precise, controlled by hardware (timers or peripherals) |
| CPU Load | High, CPU must start each conversion | Low, CPU can remain free during conversions |
| Synchronization with Peripherals | Difficult to achieve | Easy, perfect alignment with timers, PWM, or external events |
| Multi-Channel Consistency | May vary if software delays occur | Consistent timing for all channels |
| Use Case | Simple testing, occasional ADC reads | Real-time control, waveform sampling, multi-channel synchronized measurements |
How External Trigger Works: Timing Diagram
Below is an image illustrating the sequence of events when using an external trigger with the STM32 ADC:
- EXT Trigger: A timer or external event triggers the ADC conversion.
- Sampling: The ADC samples the input signal.
- Conversion: The sampled signal is converted to a digital value.
- EOC (End of Conversion): Data becomes available, optionally transferred via DMA.
STM32F103C8 CubeMX Configuration
In this section, we will configure the STM32F103C8 ADC using CubeMX. You’ll learn how to select ADC channels, set sampling times, configure external triggers, and enable DMA or continuous conversion modes.
ADC Configuration
Below is the image showing the ADC configuration for multiple channels.
I have enabled 4 channels of the ADC1. This is where the 4 potentiometers will be connected to.
Since we are using 4 different Channels of ADC1, set the Number of Conversions (under ADC_Regular_ConversionMode) to 4. This will automatically enable the Scan Conversion Mode, which is necessary in case of Multiple Channels.
You can configure the Rank and Sampling Time for each channel. The Rank determines the sequence in which the channels will be converted.
The Continuous Conversion Mode should be Disabled. Doing so will make sure the ADC does not start another conversion for all the channels automatically. Instead we will use the timer’s event to start the conversion. This way we can control the sampling rate of the ADC channels.
The External Trigger Conversion Source is set to Timer3 Trigger out Event. So whenever the Timer3 will generate an event, it will start the conversion in the ADC1.
In the DMA section, add the DMA request for the ADC1. Also make sure that the DMA is configured in the Circular Mode. In this mode the DMA will transfer the data continuously.
The F103C8 has 12 bit ADC resolution by default and we don’t have the option to configure it. Therefore the data width for the DMA must be set to Half-Word (16 bits).
Timer Configuration
We will use Timer3’s event to trigger the ADC conversion. Before we configure the timer, we must find more details about where this timer is connected to. Below is the image showing some details about it.
The second half of the image above is taken from the F103C8 Datasheet. It shows that the TIM3 is connected to the APB1 Bus. The first Half of the image is showing the clock configuration for this project. The APB1 Timer clock is running at 72MHz clock, so this will be the TIM3 clock as well.
We will now configure the TIM3’s Prescaler and ARR to reduce this clock to the desired ADC sampling rate we need.
We will first use the internal clock as the clock source for TIM3, which is running at 72 MHz. To generate a suitable trigger for the ADC, we configure the prescaler and auto-reload register (ARR) as follows.
Step 1: Apply the Prescaler
The prescaler divides the timer clock:
After the prescaler, the timer counts at 10 kHz.
Step 2: Apply the Auto-Reload Register (ARR)
The ARR determines how many timer ticks occur before an update event (overflow) is generated:
This means the timer will generate an update event every 0.1 s, which we can use to trigger the ADC conversion.
Step 3: Select the Trigger Event
In CubeMX, choose “Update Event” in the ADC Trigger Event selection. This configures the ADC to start a conversion each time the TIM3 counter overflows.
How it Works
- Using this method ensures precise, hardware-controlled ADC sampling at 10 Hz.
- TIM3 counter starts from 0 and counts up.
- When the counter reaches the ARR value, it overflows.
- This overflow generates an update event, which is then used as the external trigger for the ADC.
STM32F446 CubeMX Configuration
Similar to the STM32F103C8 configuration, here we will see how to configure the STM32F446RE. We will start with the ADC configuration first.
ADC Configuration
Below is the image showing the ADC configuration for multiple channels.
I have enabled 4 channels of the ADC1. This is where the 4 potentiometers will be connected to.
Since we are using 4 different Channels of ADC1, set the Number of Conversions (under ADC_Regular_ConversionMode) to 4. This will automatically enable the Scan Conversion Mode, which is necessary in case of Multiple Channels.
You can configure the Rank and Sampling Time for each channel. The Rank determines the sequence in which the channels will be converted.
The Continuous Conversion Mode should be Disabled. Doing so will make sure the ADC does not start another conversion for all the channels automatically. Instead we will use the timer’s event to start the conversion. This way we can control the sampling rate of the ADC channels.
The External Trigger Conversion Source is set to Timer2 Trigger out Event. So whenever the Timer2 will generate an event, it will start the conversion in the ADC1.
The DMA Continuous Request must also be Enabled. This is to make sure that the DMA requests the data continuously from the ADC. This mode should be kept Enabled while using the DMA in Circular mode.
The End of Conversion Selection should be set at the end of all the conversions. Doing this will make sure that the Conversion complete interrupt in only triggered when all the 4 channels (one complete sequence) have been converted.
In the DMA section, add the DMA request for the ADC1. Also make sure that the DMA is configured in the Circular Mode. In this mode the DMA will transfer the data continuously. Set the data width as per the ADC Resolution. I have configured the ADC with 12bits resolution, therefore the data width is set to half word (16bits).
Timer Configuration
We are using Timer2’s event to trigger the ADC conversion. Before we configure the timer, we must find more details about where this timer is connected to. Below is the image showing some details about it.
The First half of the image above is taken from the F446RE Datasheet. It shows that the TIM2 is connected to the APB1 Bus. The Second Half of the image is showing the clock configuration for this project. The APB1 Timer clock is running at 90MHz clock, so this will be the TIM2 clock as well.
We will now configure the TIM2’s Prescaler and ARR to reduce this clock to the desired ADC sampling rate we need.
We will first enable the internal clock as the clock source for TIM2, which is running at 90 MHz. To generate a trigger suitable for the ADC, we configure the prescaler and auto-reload register (ARR) as follows.
Step 1: Apply the Prescaler
The prescaler divides the timer clock to slow it down:
After applying the prescaler, TIM2 counts at 10 kHz.
Step 2: Apply the Auto-Reload Register (ARR)
The ARR determines how many timer ticks occur before an update event (overflow) is generated:
This means TIM2 will generate an update event every 0.1 s, which will serve as the ADC trigger.
Step 3: Configure ADC Trigger Event
In CubeMX, select “Update Event” as the ADC trigger source. This ensures that each time TIM2 overflows, it triggers an ADC conversion automatically.
How It Works
- TIM2 counter starts at 0 and increments with each tick of the prescaled clock.
- When the counter reaches the ARR value (1000), it overflows.
- The overflow generates an update event, which is then used by the ADC as an external trigger.
- This setup ensures precise, hardware-timed ADC sampling at 10 Hz without CPU intervention.
STM32H750 CubeMX Configuration
Let’s configure the STM32H750 Microcontroller now. We will again start with the ADC configuration first.
ADC Configuration
Below is the image showing the ADC configuration for multiple channels.
I have enabled 4 channels of the ADC1. This is where the 4 potentiometers will be connected to.
Since we are using 4 different Channels of ADC1, set the Number of Conversions (under ADC_Regular_ConversionMode) to 4. This will automatically enable the Scan Conversion Mode, which is necessary in case of Multiple Channels.
You can configure the Rank and Sampling Time for each channel. The Rank determines the sequence in which the channels will be converted.
The Continuous Conversion Mode should be Disabled. Doing so will make sure the ADC does not start another conversion for all the channels automatically. Instead we will use the timer’s event to start the conversion. This way we can control the sampling rate of the ADC channels.
The External Trigger Conversion Source is set to Timer1 Trigger out Event. So whenever the Timer1 will generate an event, it will start the conversion in the ADC1.
The Conversion Data Management Mode should be set to DMA Circular. This is to make sure that the DMA does requests the data continuously from the ADC. This mode should be used while using the DMA in Circular mode.
The End of Conversion Selection should be set at the end of sequence of conversion. Doing this will make sure that the Conversion complete interrupt in only triggered when all the 4 channels (one complete sequence) have been converted.
In the DMA section, add the DMA request for the ADC1. Also make sure that the DMA is configured in the Circular Mode. In this mode the DMA will transfer the data continuously. I have configured the ADC resolution of 16bits, therefore the data width is set to Half-Word (16bits).
Timer Configuration
We are using Timer2’s event to trigger the ADC conversion. Before we configure the timer, we must find more details about where this timer is connected to. Below is the image showing some details about it.
The First half of the image above is taken from the H750 Datasheet. It shows that the TIM1 is connected to the APB2 Bus. The Second Half of the image is showing the clock configuration for this project. The APB2 Timer clock is running at 240MHz clock, so this will be the TIM1 clock as well.
We will now configure the TIM1’s Prescaler and ARR to reduce this clock to the desired ADC sampling rate we need.
We will first enable the internal clock as the clock source for TIM1, which is running at 240 MHz. To generate a trigger suitable for the ADC, we configure the prescaler and auto-reload register (ARR) as follows.
Step 1: Apply the Prescaler
The prescaler reduces the timer clock to a lower frequency:
After applying the prescaler, TIM1 counts at 10 kHz.
Step 2: Apply the Auto-Reload Register (ARR)
The ARR determines how many timer ticks occur before an update event (overflow) is generated:
This means TIM1 will generate an update event every 0.1 s, which will serve as the ADC trigger.
Step 3: Configure ADC Trigger Event
In CubeMX, select “Update Event” as the ADC trigger source. This ensures that each time TIM1 overflows, it triggers an ADC conversion automatically.
How It Works
- TIM1 counter starts at 0 and increments with each tick of the prescaled clock.
- When the counter reaches the ARR value (1000), it overflows.
- The overflow generates an update event, which is used by the ADC as an external trigger.
- This setup ensures precise, hardware-timed ADC sampling at 10 Hz without CPU intervention.
Cortex M7 Related Changes
In this section we will cover the configuration and code exclusively needed for the cortex M7 devices.
We know that as per ST’s recommendation, we should use the Instruction and Data cache to improve the system performance. But if the cache are enabled, the DMA will always have the cache coherency issue. This is why we will use the Memory Processing Unit (MPU) of the cortex M7 to deal with the cache coherency.
Below is the image showing the MPU configuration in the cortex M7 Devices.
As you can see in the image above, I have enabled both Instruction and Data Cache (ICache & DCache).
We also need to enable the MPU in the MPU_PRIVILEGED_DEFAULT mode. Here I am choosing the Base Address region 0x30000000, this is the region for the RAM_D2 and we will relocate our buffer in this region.
- Here I have selected the 32 Bytes region, since it’s the least size available. The ADC Buffer is going to be 20 bytes in size.
- The rest of the configuration is to set the region as non-cacheable region. This would prevent the cache coherency issue between the CPU and the DMA.
In the main file, we need to relocate the ADC_VAL array to the RAM_D2 Region, 0x30000000. We can do this by using the section attribute as shown below.
__attribute__((section(".adcarray"))) uint16_t ADC_VAL[4];Here I am relocating the ADC_VAL array to the section “.adcarray“. The section (.adcarray) will be defined in the flash script file as shown below.
.mysection (NOLOAD):
{
. = ABSOLUTE(0x30000000);
*(.adcarray)
} >RAM_D2As you can see above, the section (.adcarray) is linked to the region RAM_D2 (0x30000000).
The rest of the code remains the same as we used in the DMA section.
Wiring Diagram: Connect Potentiometers to STM32
Below is the image showing the connection between the potentiometers and the H750.
As shown in the image above, four potentiometers are connected to four input pins of the MCU, each corresponding to a separate ADC channel. These pins allow the ADC to read the analog voltage from each potentiometer independently.
The potentiometers are powered from the MCU’s 3.3 V supply, and their wipers provide a variable voltage to the ADC inputs, ranging from 0 V to 3.3 V. This setup allows us to measure and monitor the voltage level of each potentiometer in real time, demonstrating multi-channel ADC operation on the STM32 microcontroller.
STM32 Code for ADC External Trigger
The code will remain the same for all the STM32 MCUs. If there are any changes, I will specify in this section itself.
Definitions
Let’s define some variables, which we will use in the main function later.
//uint16_t ADC_VAL[4];
__attribute__((section(".adcarray"))) uint16_t ADC_VAL[4]; // cortex M7 onlyADC_VAL is an array of 4 elements of 16 bit in size. We will use this array to store the converted ADC Value. Even if you are using 10bits, 12bits or 14bits resolution the ADC_VAL will still be defined as a 16 bit variable.
The main function
Below is the main function.
int main()
{
....
HAL_TIM_Base_Start(&htim1);
HAL_ADC_Start_DMA(&hadc1, ADC_VAL, 4);
while (1)
{
}
}Inside the main function we will first start the TIM1 in the base mode. This will start will Timer’s counter, which will start counting up. Once the counter overflows, an event will trigger, which will start the ADC conversions. The counter than resets back to 0 and starts counting UP again.
Next we will start the ADC in DMA Mode.The parameter ADC_VAL is the array where we want to store the converted data, and 4 is the number of conversions we want the DMA to transfer.
Once the ADC finishes all the conversions, an interrupt will trigger and the ADC Conversion Callback will be called.
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef *hadc)
{
HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_1);
}Inside this callback we will toggle the pin PA1. This pin toggles each time the callback is called and hence it can be used to calculate the time interval of the callback function. We will measure it on the scope.
Result of STM32 ADC External Trigger
Below is the gif showing the ADC channel data on the debugger.
As you can see above, the ADC data is updating every 100ms. This is because we have set the Timer’s output to 10Hz. To confirm if this is indeed 100ms, we can view the toggling time of the pin PA1 on the logic analyzer. Below is the image showing the same.
As you can see above, the pin PA1 remains HIGH and LOW for 100ms. This means that the pin Toggles every 100ms. This is because the Conversion Complete Callback is called every 100ms. Which signifies that the ADC sampling frequency is set to 10Hz.
Video Tutorial
STM32 ADC External Trigger – Video Tutorial
In this tutorial, we demonstrate how to configure the ADC on STM32 microcontrollers to start conversions using an external trigger. You’ll learn how to select timers as trigger sources, configure update events, and synchronize multiple channels for precise, hardware-controlled sampling. A complete video walkthrough is included, showing CubeMX configuration, code implementation, and real hardware results step by step.
Watch the VideoConclusion
In this tutorial, we explored how to configure the ADC on STM32 microcontrollers to start conversions using an external hardware trigger, typically generated by a timer. We covered how to select the appropriate timer, configure its prescaler and auto-reload register (ARR), and use the update event as the trigger source for the ADC. The post also explained how to synchronize multiple ADC channels, enable DMA in circular mode, and achieve precise, consistent sampling intervals without relying on software-based triggers.
Using external triggers for ADC conversions provides hardware-timed precision, reduces CPU overhead, and ensures reliable multi-channel measurements. This approach is especially useful for real-time applications such as motor control, signal processing, or sensor monitoring, where predictable timing is critical. By understanding and implementing these concepts, developers can achieve accurate, efficient, and scalable ADC-based data acquisition systems on STM32 microcontrollers.
Browse More STM32 ADC Tutorials
STM32 ADC Part 4 – Multiple Channels with DMA Circular Mode
STM32 ADC Part 5 – Read Multiple‑Channel without DMA
STM32 ADC Part 6 – ADC Conversion Time Explained
STM32 ADC Part 8 – Injected Conversion Mode
STM32 ADC Part 9 – ADC Hardware Oversampling Technique
STM32 ADC Part 10 – How to use ADC Reference Voltage
STM32 ADC Part 11 – How to use ADC in Differential Mode
STM32 ADC ext trigger project Download
Info
You can help with the development by DONATING Below.
To download the project, click the DOWNLOAD button.
STM32 ADC Multiple channels FAQs
No, the STM32 ADC can only be triggered by one selected timer/event at a time. For multiple timing sources, you must switch the trigger in software between conversions.
If the timer triggers faster than the ADC conversion time, some triggers will be missed, and data may be skipped or corrupted. Always calculate conversion time to match trigger frequency.
Yes, some STM32 models allow external EXTI pins or dedicated trigger pins to start ADC conversions, but not all ADCs support this feature.
DMA allows each externally-triggered conversion to be transferred to memory automatically. This ensures continuous sampling without CPU intervention, even at high trigger rates.
No, the ADC resolution and accuracy remain unchanged. External triggers only control when conversions start, not how the ADC samples or converts the signal.















Download button downloads PART4 not PART7
Thanks for informing. It has been fixed now.