2025-03-18 10:00 PM - edited 2025-03-18 10:09 PM
Hi
#include "stm32f4xx_hal.h"
// Define DAC handle and resolution
DAC_HandleTypeDef hdac;
#define DAC_RESOLUTION 1241
// Button press flag
volatile uint8_t button_pressed = 0;
// Function to initialize DAC
void DAC_Init(void)
{
__HAL_RCC_DAC_CLK_ENABLE(); // Enable DAC clock
hdac.Instance = DAC;
HAL_DAC_Init(&hdac); // Initialize DAC
DAC_ChannelConfTypeDef sConfig = {0};
sConfig.DAC_Trigger = DAC_TRIGGER_NONE;
sConfig.DAC_OutputBuffer = DAC_OUTPUTBUFFER_DISABLE; // Disable output buffer
HAL_DAC_ConfigChannel(&hdac, &sConfig, DAC_CHANNEL_1);
HAL_DAC_Start(&hdac, DAC_CHANNEL_1); // Start DAC
}
// Function to initialize button (PC13)
void Button_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
__HAL_RCC_GPIOC_CLK_ENABLE();
GPIO_InitStruct.Pin = GPIO_PIN_13;
GPIO_InitStruct.Mode = GPIO_MODE_IT_FALLING; // Falling edge trigger (button press)
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
// Enable EXTI interrupt for line 13 (PC13)
HAL_NVIC_SetPriority(EXTI15_10_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(EXTI15_10_IRQn);
}
// Interrupt handler for button press (PC13)
void EXTI15_10_IRQHandler(void)
{
static uint32_t last_interrupt_time = 0;
uint32_t interrupt_time = HAL_GetTick();
if (__HAL_GPIO_EXTI_GET_IT(GPIO_PIN_13) != RESET)
{
// Clear the interrupt flag
__HAL_GPIO_EXTI_CLEAR_IT(GPIO_PIN_13);
// Simple debounce check: ignore if the interrupt happens too quickly after the last one
if (interrupt_time - last_interrupt_time > 50) // 50 ms debounce
{
last_interrupt_time = interrupt_time;
// Set flag to indicate button press
button_pressed = 1;
}
}
}
// Ramp DAC function (0 to 1V and back)
void Ramp_DAC(void)
{
uint32_t dacValue;
int32_t direction = 1; // Ramp direction: 1 = up, -1 = down
while (1)
{
// Polling button press status in main loop
if (button_pressed)
{
// Set DAC to 0V (explicitly force DAC to 0)
HAL_DAC_SetValue(&hdac, DAC_CHANNEL_1, DAC_ALIGN_12B_R, 0);
// Stop the DAC output to force it to 0V
HAL_DAC_Stop(&hdac, DAC_CHANNEL_1);
break; // Stop the ramp
}
// Ramp the DAC value
if (direction == 1)
{
for (dacValue = 0; dacValue < DAC_RESOLUTION; dacValue++)
{
HAL_DAC_SetValue(&hdac, DAC_CHANNEL_1, DAC_ALIGN_12B_R, dacValue);
HAL_Delay(1); // Adjust ramp speed
}
direction = -1; // Change direction to ramp down
}
else
{
for (dacValue = DAC_RESOLUTION; dacValue > 0; dacValue--)
{
HAL_DAC_SetValue(&hdac, DAC_CHANNEL_1, DAC_ALIGN_12B_R, dacValue);
HAL_Delay(1); // Adjust ramp speed
}
direction = 1; // Change direction to ramp up
}
}
}
int main(void)
{
HAL_Init();
DAC_Init();
Button_Init();
Ramp_DAC();
while (1)
{
}
}
Thank you.
2025-03-19 1:53 AM - edited 2025-03-19 2:32 AM
Hello,
What do you mean by "the value 0 or close to zero"?
Already answered the question here.
As you've disabled the DAC output buffer:
sConfig.DAC_OutputBuffer = DAC_OUTPUTBUFFER_DISABLE; // Disable output buffer
The value of DAC OUT min is given in the datasheet: 0.5mV as Typical.
With measurement errors + PCB (NUCLEO is not optimized for analog) I don't think you can go lower than that.
2025-03-19 5:55 AM
Haven't we already covered this here:
https://community.st.com/t5/stm32-mcus-boards-and-hardware/nucleo-f446re-internal-dac/td-p/781954