STM32 HAL Tutorial: Feedback Control Using DAC and ADC
Abstract
Learn how to implement closed-loop control on STM32 using DAC and ADC with HAL. Step-by-step guide for real-time analog feedback systems.
1. Introduction
Closed-loop control uses ADC measurements to adjust a DAC output dynamically:
- Example: Voltage regulator, motor control, or sensor calibration
- ADC reads the system output
- MCU adjusts DAC to achieve target value
By the end of this episode, you’ll be able to:
- Read analog input via ADC
- Adjust DAC output based on feedback
- Implement a simple control loop
2. Prerequisites
- STM32 board with ADC and DAC
- STM32CubeIDE installed
- Knowledge of HAL, DMA, and timers
3. Basic Closed-Loop Flow
1. Initialize ADC and DAC
2. Set target analog value
3. In a loop:
- Read ADC
- Compare to target
- Compute error
- Adjust DAC output
uint16_t adcValue = HAL_ADC_GetValue(&hadc1);
uint16_t dacValue = target + Kp * (target - adcValue);
HAL_DAC_SetValue(&hdac1, DAC_CHANNEL_1, DAC_ALIGN_12B_R, dacValue);
- Kp is proportional gain for simple feedback
4. Using DMA for Continuous Feedback
- Use ADC + DAC in DMA mode to reduce CPU load
- Circular buffer can hold multiple ADC samples
- Update DAC continuously based on buffer average
HAL_ADC_Start_DMA(&hadc1, (uint32_t*)adcBuffer, BUFFER_SIZE);
HAL_DAC_Start(&hdac1, DAC_CHANNEL_1);
- Loop computes average of ADC buffer → sets DAC
5. Hands-On Lab Example
1. Connect DAC output to the ADC channel
2. Initialize ADC to read input signal (make sure to click on the GPIO and + ADC)
3. Implement feedback loop to create a saw tooth waveform
/* USER CODE BEGIN PV */
uint32_t value_adc;
uint32_t value_dac=0;
/* USER CODE END PV */
/* USER CODE BEGIN 2 */
HAL_DAC_Start(&hdac1,DAC_CHANNEL_1);
HAL_DAC_SetValue(&hdac1, DAC_CHANNEL_1, DAC_ALIGN_12B_R, value_dac);
HAL_ADCEx_Calibration_Start(&hadc1);
HAL_ADC_Start(&hadc1);
/* USER CODE END 2 */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
HAL_ADC_Start(&hadc1);
HAL_ADC_PollForConversion(&hadc1,10);
value_adc=HAL_ADC_GetValue(&hadc1);
HAL_DAC_SetValue(&hdac1, DAC_CHANNEL_1, DAC_ALIGN_12B_R, value_dac);
value_dac++;
if(value_dac>4095){
value_dac=0;
}
HAL_Delay(1);
}
/* USER CODE END 3 */
4. Observe ADC and DAC registers, variables and the wave form using the scope
6. Advantages
- Real-time analog feedback without external circuitry
- Low CPU overhead if DMA is used
- Can implement sensor calibration, voltage control, or analog signal tracking


