2026-01-23 5:54 AM - edited 2026-01-23 5:58 AM
I'm using stm32u535 and would like to have zero crossing detection of supply voltage. I've requirement of 6ADC channels and all are configured in differential mode and adc clock is 25Mhz and resolution is 14 bit and dma circular mode is enabled. On channel 6 i e enabled analog watchdog and written logic in isr to toggle GPIO. I proved gpio and I see deviation. Can someone help here.
Here is my code snippet:
ADC and AWDG initialization:
hadc1.Instance = ADC1;
hadc1.Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV1;
hadc1.Init.Resolution = ADC_RESOLUTION_14B;
hadc1.Init.GainCompensation = 0;
hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
hadc1.Init.ScanConvMode = ADC_SCAN_ENABLE;
hadc1.Init.EOCSelection = ADC_EOC_SEQ_CONV;
hadc1.Init.LowPowerAutoWait = DISABLE;
hadc1.Init.ContinuousConvMode = ENABLE;
hadc1.Init.NbrOfConversion = 8;
hadc1.Init.DiscontinuousConvMode = DISABLE;
hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START;
hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
hadc1.Init.DMAContinuousRequests = ENABLE;
hadc1.Init.TriggerFrequencyMode = ADC_TRIGGER_FREQ_HIGH;
hadc1.Init.Overrun = ADC_OVR_DATA_PRESERVED;
hadc1.Init.LeftBitShift = ADC_LEFTBITSHIFT_NONE;
hadc1.Init.ConversionDataManagement = ADC_CONVERSIONDATA_DMA_CIRCULAR;
hadc1.Init.OversamplingMode = DISABLE;
if (HAL_ADC_Init(&hadc1) != HAL_OK)
{
Error_Handler();
}
/** Configure Analog WatchDog 1
*/
AnalogWDGConfig.WatchdogNumber = ADC_ANALOGWATCHDOG_1;
AnalogWDGConfig.WatchdogMode = ADC_ANALOGWATCHDOG_SINGLE_REG;
AnalogWDGConfig.Channel = ADC_CHANNEL_11;
AnalogWDGConfig.ITMode = ENABLE;
AnalogWDGConfig.HighThreshold = 8284 ;
AnalogWDGConfig.LowThreshold = 8100 ;
AnalogWDGConfig.FilteringConfig = ADC_AWD_FILTERING_NONE;
if (HAL_ADC_AnalogWDGConfig(&hadc1, &AnalogWDGConfig) != HAL_OK)
{
Error_Handler();
}
/** Configure Regular Channel
*/
sConfig.Channel = ADC_CHANNEL_1;
sConfig.Rank = ADC_REGULAR_RANK_1;
sConfig.SamplingTime = ADC_SAMPLETIME_5CYCLE;
sConfig.SingleDiff = ADC_DIFFERENTIAL_ENDED;
sConfig.OffsetNumber = ADC_OFFSET_NONE;
sConfig.Offset = 0;
if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
{
Error_Handler();
}
Interrupt ISR
if ((READ_REG(hadc->Instance->ISR) & ADC_ISR_AWD1) != RESET)
{
#if 1
volatile uint32_t ndtr = __HAL_DMA_GET_COUNTER(hadc->DMA_Handle);
volatile uint32_t safe_ndtr = ndtr % 8192;
volatile uint32_t linear_pos = (8192 - safe_ndtr) % 8192;
// Channel 7 (index 6 in each scan of 8)
volatile uint32_t current_scan = linear_pos / 8;
volatile uint16_t ch7_index = (current_scan * 8) + 7;
ch7_index %= 8192; // Circular wrap
volatile uint16_t current_ch7 = gRawDMACircularBuffer.rawDataBuffer[ch7_index];
//volatile uint16_t current_ch7 = HAL_ADC_GetValue(hadc);
volatile static uint16_t prev_ch7 = 8192,expect = 1;
if (prev_ch7 <= 8100 && current_ch7 >= 8284) {
toggle_LED();
Zx = 1;
}
else if (prev_ch7 >= 8284 && current_ch7 <= 8100) {
toggle_LED();
Zx = 1;
}
__HAL_ADC_CLEAR_FLAG(hadc, ADC_FLAG_AWD1);
prev_ch7 = current_ch7;
#endif
}