2022-05-26 08:21 AM
We're trying to read from the ADC from 2 channels by using EOC interrupts.
When we read the values seems like the channels are wired together.
As such we can't distinguish between whether they come from one channel or the
other.
Here is the code that we are using.
N.B. the Serial class is coming from the mbed framework.
#include <mbed.h>
#include <stm32l4xx_hal_adc.h>
#include <stm32l4xx_hal_adc_ex.h>
#include <stm32l4xx_hal_rcc.h>
#include <stm32l4xx_hal_rcc_ex.h>
Serial pc(USBTX, USBRX, 115200);
ADC_HandleTypeDef handle;
ADC_ChannelConfTypeDef ch1;
ADC_ChannelConfTypeDef ch2;
uint16_t values[2];
void ADC1_IRQHandler() { HAL_ADC_IRQHandler(&handle); }
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef *handle) {
static size_t i = 0;
values[i++] = HAL_ADC_GetValue(handle);
if (i >= 2) {
i = 0;
HAL_ADC_Stop_IT(handle);
}
};
int main() {
// setting the adc clock source
// getting the peripherals clocks already set
RCC_PeriphCLKInitTypeDef peripheral_clock_init;
HAL_RCCEx_GetPeriphCLKConfig(&peripheral_clock_init);
// the prescaler requires a synchronous clock source
peripheral_clock_init.AdcClockSelection = RCC_ADCCLKSOURCE_SYSCLK;
if (HAL_RCCEx_PeriphCLKConfig(&peripheral_clock_init) != HAL_OK) {
pc.printf("error in HAL_RCCEx_PeriphCLKConfig\n");
while (1)
;
}
// enabling the clock of the peripheral as required by the documentation
// in file stm32l4xx_hal_adc.c
__HAL_RCC_ADC_CLK_ENABLE();
// initialization
handle.Instance = ADC1;
handle.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV4;
handle.Init.DataAlign = ADC_DATAALIGN_RIGHT;
handle.Init.Resolution = ADC_RESOLUTION_12B;
handle.Init.ScanConvMode = ADC_SCAN_ENABLE;
handle.Init.ContinuousConvMode = ENABLE;
handle.Init.DiscontinuousConvMode = DISABLE;
handle.Init.ExternalTrigConv = ADC_SOFTWARE_START;
handle.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
handle.Init.Overrun = ADC_OVR_DATA_PRESERVED;
handle.Init.OversamplingMode = DISABLE;
handle.Init.NbrOfConversion = 2;
if (HAL_ADC_Init(&handle) != HAL_OK) {
pc.printf("Error in ADC Init\n");
while (1)
;
}
if (not HAL_ADCEx_Calibration_GetValue(&handle, ADC_SINGLE_ENDED)) {
HAL_ADCEx_Calibration_Start(&handle, ADC_SINGLE_ENDED);
}
ch1.Channel = ADC_CHANNEL_5;
ch1.Rank = ADC_REGULAR_RANK_1;
ch1.SamplingTime = ADC_SAMPLETIME_47CYCLES_5;
ch1.OffsetNumber = ADC_OFFSET_NONE;
ch1.Offset = 0;
ch1.SingleDiff = ADC_SINGLE_ENDED;
ch2.Channel = ADC_CHANNEL_6;
ch2.Rank = ADC_REGULAR_RANK_2;
ch2.SamplingTime = ADC_SAMPLETIME_47CYCLES_5;
ch2.OffsetNumber = ADC_OFFSET_NONE;
ch2.Offset = 0;
ch2.SingleDiff = ADC_SINGLE_ENDED;
if (HAL_ADC_DeInit(&handle) != HAL_OK) {
pc.printf("Error in ADC DeInit\n");
while (1)
;
}
if (HAL_ADC_ConfigChannel(&handle, &ch1) != HAL_OK) {
pc.printf("error in adc config channel 1\n");
while (1)
;
}
if (HAL_ADC_ConfigChannel(&handle, &ch2) != HAL_OK) {
pc.printf("error in adc config channel 2\n");
while (1)
;
}
if (HAL_ADC_Init(&handle) != HAL_OK) {
pc.printf("Error in ADC Init 2\n");
while (1)
;
}
__NVIC_SetVector(ADC1_IRQn, (uint32_t)ADC1_IRQHandler);
HAL_NVIC_EnableIRQ(ADC1_IRQn);
HAL_NVIC_SetPriority(ADC1_IRQn, 0, 0);
while (1) {
if (HAL_ADC_Start_IT(&handle) != HAL_OK) {
pc.printf("Error in HAL_ADC_Start_IT\n");
while (1)
;
}
pc.printf("value1 %li, value2 %li\n", values[0], values[1]);
HAL_Delay(500);
}
}
Here is an example of the result we are having while we're moving the
potentiometer:
#A1 connected to 3v3
value1 0, value2 2746
value1 0, value2 2744
value1 0, value2 2745
value1 0, value2 2741
value1 0, value2 2745
value1 595, value2 2831
value1 594, value2 2832
value1 593, value2 2830
value1 596, value2 2833
value1 593, value2 2835
#A1 connected to ground
value1 2143, value2 1721
value1 2515, value2 1590
value1 2642, value2 1280
value1 2642, value2 1279
value1 2642, value2 1282
Here are the wirings of the two configurations:
2022-05-26 07:30 PM
points to check:
ADC_SAMPLETIME_47CYCLES_5 - 47.5 cycles used, may try something like hundreds of cycles, or largest value. potentiometer like 10k ohm or less may be used to match the analog input impedance.