2023-04-20 11:47 AM
Having some trouble with reading ADC channels on this unit only when using multiple channels. I have no problem using a single channel, but as soon as I expand it to two, or more, my readings are just garbage.
Code for working single channel:
hadc1.Instance = ADC1;
hadc1.Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV16;
hadc1.Init.Resolution = ADC_RESOLUTION_12B;
hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
hadc1.Init.ScanConvMode = ADC_SCAN_DISABLE;
hadc1.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
hadc1.Init.LowPowerAutoWait = DISABLE;
hadc1.Init.LowPowerAutoPowerOff = DISABLE;
hadc1.Init.ContinuousConvMode = DISABLE;
hadc1.Init.NbrOfConversion = 1;
hadc1.Init.DiscontinuousConvMode = DISABLE;
hadc1.Init.ExternalTrigConv = ADC_EXTERNALTRIG_T2_TRGO;
hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_RISING;
hadc1.Init.DMAContinuousRequests = ENABLE;
hadc1.Init.Overrun = ADC_OVR_DATA_PRESERVED;
hadc1.Init.SamplingTimeCommon1 = ADC_SAMPLETIME_1CYCLE_5;
hadc1.Init.SamplingTimeCommon2 = ADC_SAMPLETIME_160CYCLES_5;
hadc1.Init.OversamplingMode = ENABLE;
hadc1.Init.Oversampling.Ratio = ADC_OVERSAMPLING_RATIO_16;
hadc1.Init.Oversampling.RightBitShift = ADC_RIGHTBITSHIFT_NONE;
hadc1.Init.Oversampling.TriggeredMode = ADC_TRIGGEREDMODE_SINGLE_TRIGGER;
hadc1.Init.TriggerFrequencyMode = ADC_TRIGGER_FREQ_LOW;
sConfig.Channel = ADC_CHANNEL_9;
sConfig.Rank = ADC_REGULAR_RANK_1;
sConfig.SamplingTime = ADC_SAMPLINGTIME_COMMON_2;
if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
{
Error_Handler();
}
Them my own code: [relevant snips]
#define ADC_CHANNELS 1
uint32_t dmaBuffer[ADC_CHANNELS];
HAL_ADC_Start_DMA(&hadc1, &dmaBuffer, ADC_CHANNELS);
Values I read from dmaBuffer are exactly as I expect them to be.
Now, when I extend this to a secondary channel:
hadc1.Instance = ADC1;
hadc1.Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV16;
hadc1.Init.Resolution = ADC_RESOLUTION_12B;
hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
hadc1.Init.ScanConvMode = ADC_SCAN_ENABLE;
hadc1.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
hadc1.Init.LowPowerAutoWait = DISABLE;
hadc1.Init.LowPowerAutoPowerOff = DISABLE;
hadc1.Init.ContinuousConvMode = DISABLE;
hadc1.Init.NbrOfConversion = 2;
hadc1.Init.DiscontinuousConvMode = DISABLE;
hadc1.Init.ExternalTrigConv = ADC_EXTERNALTRIG_T2_TRGO;
hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_RISING;
hadc1.Init.DMAContinuousRequests = ENABLE;
hadc1.Init.Overrun = ADC_OVR_DATA_PRESERVED;
hadc1.Init.SamplingTimeCommon1 = ADC_SAMPLETIME_1CYCLE_5;
hadc1.Init.SamplingTimeCommon2 = ADC_SAMPLETIME_160CYCLES_5;
hadc1.Init.OversamplingMode = ENABLE;
hadc1.Init.Oversampling.Ratio = ADC_OVERSAMPLING_RATIO_16;
hadc1.Init.Oversampling.RightBitShift = ADC_RIGHTBITSHIFT_NONE;
hadc1.Init.Oversampling.TriggeredMode = ADC_TRIGGEREDMODE_SINGLE_TRIGGER;
hadc1.Init.TriggerFrequencyMode = ADC_TRIGGER_FREQ_LOW;
sConfig.Channel = ADC_CHANNEL_9;
sConfig.Rank = ADC_REGULAR_RANK_1;
sConfig.SamplingTime = ADC_SAMPLINGTIME_COMMON_2;
if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
{
Error_Handler();
}
/** Configure Regular Channel
*/
sConfig.Channel = ADC_CHANNEL_VREFINT;
sConfig.Rank = ADC_REGULAR_RANK_2;
if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
{
Error_Handler();
}
My custom code:
#define ADC_CHANNELS 2
uint32_t dmaBuffer[ADC_CHANNELS];
HAL_ADC_Start_DMA(&hadc1, dmaBuffer, ADC_CHANNELS);
The value in dmaBuffer[0] is "garbage" and dmaBuffer[1] is always 0.
I am not sure what's going on with this,. Any advice?
Solved! Go to Solution.
2023-04-21 12:20 AM
You get garbage because all data fit in first 32 bits - 16 bits as first conversion, next 16 bits as second conversion.
look at your DMA settings. Data width is propably HALF_WORLD (uint16_t) but your buffer is uint32_t. Change your buffer on uint16_t like this:
#define ADC_CHANNELS 2
uint16_t dmaBuffer[ADC_CHANNELS];
HAL_ADC_Start_DMA(&hadc1, (uint16_t*)dmaBuffer, ADC_CHANNELS);
2023-04-21 12:20 AM
You get garbage because all data fit in first 32 bits - 16 bits as first conversion, next 16 bits as second conversion.
look at your DMA settings. Data width is propably HALF_WORLD (uint16_t) but your buffer is uint32_t. Change your buffer on uint16_t like this:
#define ADC_CHANNELS 2
uint16_t dmaBuffer[ADC_CHANNELS];
HAL_ADC_Start_DMA(&hadc1, (uint16_t*)dmaBuffer, ADC_CHANNELS);
2023-04-21 04:13 AM
You're right. However, passing a uint16_t to HAL_ADC_Start throws an warning because it's expecting uint32_t. So there are 2 solutions.
Define the dma buffer as 16 bit, and cast is 32, or define the DMA buffer to a word.
Both worked. Thanks for the tip!
2023-04-21 04:16 AM
@Community member please marks best answer and we are closing topic :)