cancel
Showing results for 
Search instead for 
Did you mean: 

STM32LO Convert multiple ADCs using DMA

keebler411
Associate II

I'm trying to convert 3 ADC channels using DMA. But the variables don't seem to change when I watch them in the debugger. I know the conversion complete callback is executed because I breakpointed it. So this suggests that the DMA transfer is not executing and the buffer is not being filled. I'm using stm32cube to initialize my project so maybe I missed something. I've trimmed the generated code. Thanks.

ADC_HandleTypeDef hadc;
DMA_HandleTypeDef hdma_adc;
 
uint32_t uwADC8ConvertedValue = 0;
uint32_t uwADC10ConvertedValue = 0;
uint32_t uwADC11ConvertedValue = 0;
uint32_t adcBuffer[3];
 
/* USER CODE BEGIN 0 */
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef *AdcHandle) {
    uwADC8ConvertedValue = adcBuffer[0];
    uwADC10ConvertedValue = adcBuffer[1];
    uwADC11ConvertedValue = adcBuffer[2];
}
/* USER CODE END 0 */
 
int main(void)
{
  HAL_Init();
  SystemClock_Config();
  MX_GPIO_Init();
  MX_DMA_Init();
  MX_RTC_Init();
  MX_ADC_Init();
  MX_USART2_UART_Init();
  MX_USART5_UART_Init();
  MX_TIM2_Init();
 
  /* USER CODE BEGIN 2 */
    HAL_TIM_Base_Start_IT(&htim2);
  HAL_ADC_Start_IT(&hadc);
    HAL_ADC_Start_DMA(&hadc, adcBuffer, 3);
  /* USER CODE END 2 */
 
  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
    HAL_UART_Transmit(&huart2, TxBuffer, 15, 5000);
  GPIO_PinState userPBstate = OFF;
 
    while (1)
  {
 
  /* USER CODE END WHILE */
 
  /* USER CODE BEGIN 3 */
        HAL_GPIO_TogglePin(MODEM_PW_GPIO_Port, MODEM_PW_Pin);
        HAL_GPIO_TogglePin(CAM1_LD_GPIO_Port, CAM1_LD_Pin);
        HAL_GPIO_TogglePin(CAM1_PW_GPIO_Port, CAM1_PW_Pin);
        HAL_Delay(100);
 
        userPBstate = HAL_GPIO_ReadPin(USER_PB_GPIO_Port, USER_PB_Pin);
        if (userPBstate == ON) {
            HAL_UART_Transmit(&huart2, (uint8_t *)"User button pressed!\n\r", 22, 5000);
        }
        else {
            HAL_UART_Transmit(&huart2, (uint8_t *)"User button NOT pressed!\n\r", 26, 5000);
        }
 
    }       
  /* USER CODE END 3 */
 
}
 
/* ADC init function */
static void MX_ADC_Init(void)
{
 
  ADC_ChannelConfTypeDef sConfig;
 
    /**Configure the global features of the ADC (Clock, Resolution, Data Alignment and number of conversion) 
    */
  hadc.Instance = ADC1;
  hadc.Init.OversamplingMode = DISABLE;
  hadc.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV1;
  hadc.Init.Resolution = ADC_RESOLUTION_12B;
  hadc.Init.SamplingTime = ADC_SAMPLETIME_160CYCLES_5;
  hadc.Init.ScanConvMode = ADC_SCAN_DIRECTION_FORWARD;
  hadc.Init.DataAlign = ADC_DATAALIGN_RIGHT;
  hadc.Init.ContinuousConvMode = ENABLE;
  hadc.Init.DiscontinuousConvMode = DISABLE;
  hadc.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
  hadc.Init.ExternalTrigConv = ADC_SOFTWARE_START;
  hadc.Init.DMAContinuousRequests = ENABLE;
  hadc.Init.EOCSelection = ADC_EOC_SEQ_CONV;
  hadc.Init.Overrun = ADC_OVR_DATA_PRESERVED;
  hadc.Init.LowPowerAutoWait = DISABLE;
  hadc.Init.LowPowerFrequencyMode = DISABLE;
  hadc.Init.LowPowerAutoPowerOff = DISABLE;
  if (HAL_ADC_Init(&hadc) != HAL_OK)
  {
    _Error_Handler(__FILE__, __LINE__);
  }
 
    /**Configure for the selected ADC regular channel to be converted. 
    */
  sConfig.Channel = ADC_CHANNEL_8;
  sConfig.Rank = ADC_RANK_CHANNEL_NUMBER;
  if (HAL_ADC_ConfigChannel(&hadc, &sConfig) != HAL_OK)
  {
    _Error_Handler(__FILE__, __LINE__);
  }
 
    /**Configure for the selected ADC regular channel to be converted. 
    */
  sConfig.Channel = ADC_CHANNEL_10;
  if (HAL_ADC_ConfigChannel(&hadc, &sConfig) != HAL_OK)
  {
    _Error_Handler(__FILE__, __LINE__);
  }
 
    /**Configure for the selected ADC regular channel to be converted. 
    */
  sConfig.Channel = ADC_CHANNEL_11;
  if (HAL_ADC_ConfigChannel(&hadc, &sConfig) != HAL_OK)
  {
    _Error_Handler(__FILE__, __LINE__);
  }
 
}
 
/** 
  * Enable DMA controller clock
  */
static void MX_DMA_Init(void) 
{
  /* DMA controller clock enable */
  __HAL_RCC_DMA1_CLK_ENABLE();
 
  /* DMA interrupt init */
  /* DMA1_Channel1_IRQn interrupt configuration */
  HAL_NVIC_SetPriority(DMA1_Channel1_IRQn, 0, 0);
  HAL_NVIC_EnableIRQ(DMA1_Channel1_IRQn);
 
}

2 REPLIES 2
Marcin Mróz
Associate

Did You found solution? I would like to understand what's wrong with this code

keebler411
Associate II

Yes. The confusion arose from several places. First of all the stm32cube generated code changes from version to version so examples found on the web can be out-of-date. Second, the options/values IMHO for the adc configuration are named badly. Third, the included examples do not offer complete examples for all platforms, but more more importantly are not generated from stm32cube. So if cube is what you want to use it takes a bit of digging around to figure out how to configure a project to generate the same code as an example.

Lastly, just beginner stupidity. I was using interrupts previously although I haven't got that to work correctly yet either for multiple values. I read that that the DMA generates an interrupt upon conversion completion. I mistakenly thought I had to keep the previous adc interrupt enabled. So that means simply remove this line and it works:

HAL_ADC_Start_IT(&hadc);