2025-05-23 3:19 AM
Hello !
I have to admit that I am stumped on this problem, I've been trying to make it work for the past few days.
My issue is with an STM32F301K8T6 (LQFP32) and its ADCs : I have two reflective optical sensors (ITR8307) that are connected to ADC_CHANNEL_12 and ADC_CHANNEL_11. The value read with an oscilloscope are good (they are read directly on the pin so it isn't a soldering issue), they are going from roughly 3.3V to 0.6V.
The issue is that the value read from the code doesn't really change, it gives me some random value on startup and oscillates around it, almost as if it was floating. I have tried polling for a single channel, scan mode, DMA, setting the sample time very high and very low, but nothing works... The impedance of the circuit is pretty low (a few kOhms at most), and it works perfectly with an ESP32.
All of the VDD and VSS pins are reading the correct values, however one thing I've noticed is the value given by the ADCs are shifting when I apply 0V or 3.3V to the PA1 pin. This pin is just the ADC_CHANNEL_2 so I don't really why it would be the case...
I would be very grateful for any advice or idea !
Below is the code that I've used for initializing the ADC and the main loop.
static void MX_ADC1_Init(void)
{
ADC_ChannelConfTypeDef sConfig = {0};
hadc1.Instance = ADC1;
hadc1.Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV1;
hadc1.Init.Resolution = ADC_RESOLUTION_12B;
hadc1.Init.ScanConvMode = ADC_SCAN_ENABLE;
hadc1.Init.ContinuousConvMode = DISABLE;
hadc1.Init.DiscontinuousConvMode = ENABLE;
hadc1.Init.NbrOfDiscConversion = 1;
hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START;
hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
hadc1.Init.NbrOfConversion = 2;
hadc1.Init.DMAContinuousRequests = DISABLE;
hadc1.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
hadc1.Init.LowPowerAutoWait = DISABLE;
hadc1.Init.Overrun = ADC_OVR_DATA_OVERWRITTEN;
if (HAL_ADC_Init(&hadc1) != HAL_OK)
{
Error_Handler();
}
sConfig.Channel = ADC_CHANNEL_12;
sConfig.Rank = ADC_REGULAR_RANK_1;
sConfig.SingleDiff = ADC_SINGLE_ENDED;
sConfig.SamplingTime = ADC_SAMPLETIME_181CYCLES_5;
sConfig.OffsetNumber = ADC_OFFSET_NONE;
sConfig.Offset = 0;
if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
{
Error_Handler();
}
sConfig.Channel = ADC_CHANNEL_11;
sConfig.Rank = ADC_REGULAR_RANK_2;
if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
{
Error_Handler();
}
}
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_ADC1_Init();
MX_USART1_UART_Init();
while (1)
{
uint16_t rawValues[2];
char msg[20];
HAL_ADC_Start(&hadc1);
HAL_ADC_PollForConversion(&hadc1, 100);
rawValues[0]=HAL_ADC_GetValue(&hadc1);
rawValues[1]=HAL_ADC_GetValue(&hadc1);
HAL_ADC_Stop(&hadc1);
sprintf(msg, "Val : %hu \r\t\t", rawValues[0]);
HAL_UART_Transmit(&huart1, (uint8_t *) msg, strlen(msg), HAL_MAX_DELAY);
sprintf(msg, "Val2 : %hu \r\n", rawValues[1]);
HAL_UART_Transmit(&huart1, (uint8_t *) msg, strlen(msg), HAL_MAX_DELAY);
HAL_Delay(1000);
}
}
2025-05-23 4:04 AM
Hi,
1. missing calibration - do calibrate first. ->
HAL_ADCEx_Calibration_Start(&hadc1, ADC_SINGLE_ENDED);
2. try only 1 rank and no continuous setting or anything, just plain normal 1 conversion. Check, if correct values then.
2025-05-23 7:15 AM
Use DMA to convert multiple values. The ADC does not buffer data like you are expecting here.