Skip to main content
MattiaB
Associate III
June 19, 2026
Solved

DAC out doesn't work properly on STM32H562ZI

  • June 19, 2026
  • 6 replies
  • 93 views

Good morning everyone,
I need to drive an external pump using DAC out pheriperal.

I am working with an STM32H562ZI microcontroller and have followed the guide available at the following link: Getting started with DAC

Below is my current configuration:

/**
* @brief DAC1 Initialization Function
* @param None
* @retval None
*/
static void MX_DAC1_Init(void)
{

/* USER CODE BEGIN DAC1_Init 0 */

/* USER CODE END DAC1_Init 0 */

DAC_ChannelConfTypeDef sConfig = {0};

/* USER CODE BEGIN DAC1_Init 1 */

/* USER CODE END DAC1_Init 1 */

/** DAC Initialization
*/
hdac1.Instance = DAC1;
if (HAL_DAC_Init(&hdac1) != HAL_OK)
{
Error_Handler();
}

/** DAC channel OUT1 config
*/
sConfig.DAC_HighFrequency = DAC_HIGH_FREQUENCY_INTERFACE_MODE_ABOVE_80MHZ;
sConfig.DAC_DMADoubleDataMode = DISABLE;
sConfig.DAC_SignedFormat = DISABLE;
sConfig.DAC_SampleAndHold = DAC_SAMPLEANDHOLD_DISABLE;
sConfig.DAC_Trigger = DAC_TRIGGER_NONE;
sConfig.DAC_OutputBuffer = DAC_OUTPUTBUFFER_ENABLE;
sConfig.DAC_ConnectOnChipPeripheral = DAC_CHIPCONNECT_EXTERNAL;
sConfig.DAC_UserTrimming = DAC_TRIMMING_FACTORY;
if (HAL_DAC_ConfigChannel(&hdac1, &sConfig, DAC_CHANNEL_1) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN DAC1_Init 2 */

/* USER CODE END DAC1_Init 2 */

}

After that, I implemented the following example and expected to obtain a stepped waveform. However, the result is not as expected: the DAC seems to skip some steps, producing an irregular curve as shown in the image below:

#include <stdbool.h>

bool setRaw(uint16_t value_raw)
{
while(HAL_DAC_STATE_READY != HAL_DAC_GetState(&hdac1));
while((hdac1.Instance->SR & DAC_SR_DAC1RDY) == 0x00);

do {

HAL_DAC_SetValue(&hdac1, DAC_CHANNEL_1, DAC_ALIGN_12B_R,
value_raw);

} while(HAL_DAC_GetValue(&hdac1, DAC_CHANNEL_1) != value_raw);

return true;
}
/* USER CODE END 0 */

/**
* @brief The application entry point.
* @retval int
*/
int main(void)
{

/* USER CODE BEGIN 1 */

/* USER CODE END 1 */

/* MCU Configuration--------------------------------------------------------*/

/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();

/* USER CODE BEGIN Init */

/* USER CODE END Init */

/* Configure the system clock */
SystemClock_Config();

/* USER CODE BEGIN SysInit */

/* USER CODE END SysInit */

/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_DAC1_Init();

/* USER CODE BEGIN 2 */
HAL_DAC_Start(&hdac1, DAC_CHANNEL_1);
/* USER CODE END 2 */

/* Infinite loop */
/* USER CODE BEGIN WHILE */
uint32_t timeBetweenVariation = 100;

while (1)
{
/* USER CODE END WHILE */

/* USER CODE BEGIN 3 */
HAL_Delay(timeBetweenVariation);
setRaw(0);

HAL_Delay(timeBetweenVariation);
setRaw(1000);

HAL_Delay(timeBetweenVariation);
setRaw(2000);

HAL_Delay(timeBetweenVariation);
setRaw(3000);

HAL_Delay(timeBetweenVariation);
setRaw(4095);
}
/* USER CODE END 3 */
}

setRaw method performs other checks before doing HAL_DAC_SetValue. By performing the HAL_DAC_SetValue call directly doesn’t change. 

On the other hand, when I run the provided example code, the generated waveform is correct:

strange steps curve

using the example code insted seems the generated curve is correct:
 

example triangular curve

 

Could you please help me understand what I might be missing?

Thank you in advance,
Mattia

Best answer by MattiaB

Connecting the DAC pheriperal to a TIMER trigger the DAC start to work properly:
 

sConfig.DAC_Trigger = DAC_TRIGGER_T1_TRGO;

 

6 replies

Andrew Neil
Super User
June 19, 2026

using the example code insted seems the generated curve is correct

So look at how your code differs from the example code … ?

A complex system that works is invariably found to have evolved from a simple system that worked.A complex system designed from scratch never works and cannot be patched up to make it work.
MattiaB
MattiaBAuthor
Associate III
June 19, 2026

Changing only the main function it works.

The only difference is that I change every 100 ms the value and the values are not contigues each other (1000, 2000, ecc..).

The example perform a step of one unit (0,1,2, ecc...) every millisecond.

HAL_DAC_SetValue(&hdac1, DAC_CHANNEL_2, DAC_ALIGN_12B_R, dac_value);
if (dac_value < 4095) {
dac_value++;
} else {
dac_value=0;
}
HAL_Delay(1);

 

So why my solution cannot work?

Andrew Neil
Super User
June 19, 2026

No, that’s not the only difference!

 

You do all this:

    while(HAL_DAC_STATE_READY != HAL_DAC_GetState(&hdac1));
while((hdac1.Instance->SR & DAC_SR_DAC1RDY) == 0x00);

do {
HAL_DAC_SetValue( &hdac1, DAC_CHANNEL_1, DAC_ALIGN_12B_R, value_raw );
} while(HAL_DAC_GetValue(&hdac1, DAC_CHANNEL_1) != value_raw);

The example simply does HAL_DAC_SetValue

 

BTW: what’s the point of the return value from setRaw - it’s always true !?

A complex system that works is invariably found to have evolved from a simple system that worked.A complex system designed from scratch never works and cannot be patched up to make it work.
mƎALLEm
ST Technical Moderator
June 19, 2026

Hello,

Look at the DAC examples provided in the H5 Cube HAL package:

https://github.com/STMicroelectronics/STM32CubeH5/tree/main/Projects/NUCLEO-H563ZI/Examples/DAC

 

To give better visibility on the answered topics, please click "Best answer" on the reply which solved your issue or answered your question.
MattiaB
MattiaBAuthorBest answer
Associate III
June 19, 2026

Connecting the DAC pheriperal to a TIMER trigger the DAC start to work properly:
 

sConfig.DAC_Trigger = DAC_TRIGGER_T1_TRGO;