2025-05-13 6:59 AM - edited 2025-05-13 7:00 AM
Hello.
I have a problem with the ADC on the custom board with the STM32WB55 chip. I am using a divider and should get something around 2V, but I always get the maximum value - 4095.
I am using this code that I saw in the ST examples.
HAL_GPIO_WritePin(ADC_OUT_GPIO_Port, ADC_OUT_Pin, GPIO_PIN_SET);
HAL_Delay(50);
if (HAL_ADCEx_Calibration_Start(&hadc1, ADC_SINGLE_ENDED) != HAL_OK)
{
Error_Handler();
}
if (HAL_ADC_Start_DMA(&hadc1, (uint32_t*)aADCxConvertedData, BATTERY_ARRAY_SIZE) != HAL_OK) {
HAL_GPIO_WritePin(ADC_OUT_GPIO_Port, ADC_OUT_Pin, GPIO_PIN_RESET);
Error_Handler();
}
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc) {
if(hadc->Instance == ADC1) {
if (HAL_ADC_Stop_DMA(&hadc1) != HAL_OK) {
Error_Handler();
}
HAL_GPIO_WritePin(ADC_OUT_GPIO_Port, ADC_OUT_Pin, GPIO_PIN_RESET);
uint32_t sum_mv = 0;
for (uint32_t i = 0; i < BATTERY_ARRAY_SIZE; i++) {
aADCxConvertedData_Voltage_mVolt[i] = __ADC_CALC_DATA_VOLTAGE(VDDA_APPLI, aADCxConvertedData[i]);
sum_mv += aADCxConvertedData_Voltage_mVolt[i];
}
uint16_t avg_mv = sum_mv / BATTERY_ARRAY_SIZE;
ubDmaTransferStatus = 1;
}
}
I put a breakpoint on ubDmaTransferStatus and see what it measures.
I use this same code on the nucleo board by shorting PC1 and PC0 with a wire and seeing normal results, around 3294-3296 mV.
This is not a hardware problem, I measured the output of the divider on the pin with an oscilloscope and saw around 2V. I also tested it on two devices.
I attach a project that works with nucleo, maybe this will help somehow.
Please help me.
Regards.
Solved! Go to Solution.
2025-05-13 10:02 AM
@IlliaGx wrote:It's internally connected to the VDDA.
Only on packages which do not have a VREF+ pin.
Your schematic shows that you do have the pin - so you do need to connect it.
This is why it's always important to show the full schematic!
Similarly only last week: https://community.st.com/t5/stm32-mcus-embedded-software/adc-just-giving-raw-value-of-4095-on-all-channels/m-p/800046/highlight/true#M63103
2025-05-13 11:14 AM
Yes, you were right. Thank you very much! Can you please tell me how to configure VREFBUF? I don't have this parameter in the cube.
2025-05-13 11:25 AM
The settings for VREFBUF are under SYS.
2025-05-13 3:25 PM - edited 2025-05-14 6:22 AM
I think I did it. Thank you very much!
2025-05-14 6:22 AM
Now it shows something more realistic. If instead of the real 1.72 V the ADC reads 1.1 V (at VDDA_APPLI 2500), is this a problem, or is it normal and I just need to adjust the correction factor?
2025-05-14 6:35 AM
If the voltage is 1.72 V, you should be reading 1.72 V, within perhaps 50 mV or so. The debugging process goes a lot better if you show us what you're doing.
General tips for ADC accuracy are here:
How to optimize the ADC accuracy in the STM32 MCUs - Application note
2025-05-14 6:50 AM
Hello.
Thanks for your reply.
I use the same functions that I described at the beginning of the post (check the collected array with the debugger). I also used the VREFBUF setting that you provided me.
2025-05-14 7:08 AM
@IlliaGx wrote:Now it shows something more realistic. If instead of the real 1.72 V the ADC reads 1.1 V (at VDDA_APPLI 2500), is this a problem, or is it normal and I just need to adjust the correction factor?
VDDA_APPLI should be renamed to avoid confusion. In the macro the argument is called __VREFANALOG_VOLTAGE__. VDDA has nothing to do with it.
If you followed the link @TDK send you, then you would have known that reading from a high impedance source affects the measurement. Increasing the sampling time would help a bit. But it's better to use a buffer.
2025-05-14 7:47 AM
Yes, I did ADC_SAMPLETIME_640CYCLES_5, and now I get 1.64V. Thanks!
2025-05-14 8:58 AM
Adding a capacitor can help too. This would absorb some of the current from the sampling and hold phase of acquisition. This might improve it even further. It will also double as a low pass filter.