2021-10-23 01:31 AM
I am trying to set up an example project for ADC with DMA using HAL library.
I am sampling a slow ramp function from 0-3.3V over 2500ms.
For conventional ADC setup:
When debugging the code I can see that the retrieved ADC value the full 12 bits.
For ADC with DMA:
When debugging I see 2 possible issues.
->Firstly, the retrieved ADC value is 8-bit. The value only reaches 255 then overflows and starts at 0 again.
->Secondly, the buffer array does not seem to populate in either normal or circular fashion. Only the first element is populated with this above mentioned 8-bit value.
My ADC and DMA setup is as follows:
static void MX_ADC1_Init(void)
{
ADC_ChannelConfTypeDef sConfig = {0};
hadc1.Instance = ADC1;
hadc1.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV8;
hadc1.Init.Resolution = ADC_RESOLUTION_12B;
hadc1.Init.ScanConvMode = DISABLE;
hadc1.Init.ContinuousConvMode = DISABLE;
hadc1.Init.DiscontinuousConvMode = DISABLE;
hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START;
hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
hadc1.Init.NbrOfConversion = 1;
hadc1.Init.DMAContinuousRequests = ENABLE;
hadc1.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
if (HAL_ADC_Init(&hadc1) != HAL_OK)
{
Error_Handler();
}
sConfig.Channel = ADC_CHANNEL_0;
sConfig.Rank = 1;
sConfig.SamplingTime = ADC_SAMPLETIME_28CYCLES;
if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
{
Error_Handler();
}
}
static void MX_DMA_Init(void)
{
/* DMA controller clock enable */
__HAL_RCC_DMA2_CLK_ENABLE();
/* DMA interrupt init */
/* DMA2_Stream4_IRQn interrupt configuration */
HAL_NVIC_SetPriority(DMA2_Stream4_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(DMA2_Stream4_IRQn);
hdma_adc1.Instance = DMA2_Stream4;
hdma_adc1.Init.Channel = DMA_CHANNEL_0;
hdma_adc1.Init.Direction = DMA_PERIPH_TO_MEMORY;
hdma_adc1.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_adc1.Init.MemInc = DMA_MINC_ENABLE;
hdma_adc1.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;
hdma_adc1.Init.MemDataAlignment = DMA_MDATAALIGN_WORD;
hdma_adc1.Init.Mode = DMA_CIRCULAR;
hdma_adc1.Init.Priority = DMA_PRIORITY_HIGH;
hdma_adc1.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
}
Solved! Go to Solution.
2021-10-23 03:02 AM
The gist of the code is as follows:
ADC_HandleTypeDef hadc1;
DMA_HandleTypeDef hdma_adc1;
uint16_t adcVal[10];
int main(){
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_ADC1_Init();
MX_DMA_Init();
HAL_ADC_Start_DMA(&hadc1, (uint32_t*)adcVal, 10);
while(1){ }
}
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)
{
//
HAL_GPIO_TogglePin(UserLed_GPIO_Port, UserLed_Pin);
HAL_Delay(250);
}
2021-10-25 02:42 AM
Hello @TCloe.1 ,
According to this part of your code, I would advise you this update: the MX_DMA_Init() shall be called BEFORE any other peripheral initialization.
This is a limitation with CubeMx v6.3.0 and it will be fixed in the next release.
When your question is answered, please close this topic by choosing Select as Best. This will help other users find that answer faster.
Imen
2021-10-25 03:24 AM
Looking at your code, I can see that you are setting up the width of data-transfer in hdma_adc1.init inside MX_DMA_Init().
But I don't see anywhere in the code you've shown that tells the HAL to use those values in hdma_adc1 to configure the capture. And without that, who knows what width the transfer will be.
You'd need to do something along the lines of
hadc1.DMA_Handle = &hdma_adc1;
prior to calling HAL_ADC_Start_DMA()
(I should add that I don't use HAL so I haven't learned the correct way to use it)
Hope this helps,
Danish
2021-10-25 06:43 AM
> MX_ADC1_Init();
> MX_DMA_Init();
DMA initialization needs to be before ADC initialization.
Maybe one day ST will fix the bug they introduced in CubeMX regarding initialization order. Until then, we all get to spend time debugging odd behavior on posts like these.
2021-10-25 07:56 AM
Thank you this was the issue.