1
votes

So i have been trying to set up my ADC conversion on my Nucleo-L432KC and have been having a hard time. i recently have been working on a Nucleo-F303RE which is a 64 pin nucleo and my 5 channel ADC conversions using DMA where working great. I then decided to downgrade to a nucleo-L432KC (32 pin nucleo). i used the same steps i did for the F303 but this time it doesn't work. I looked in to it a bit and found that it would never enter the HAL_ADC_ConvCpltCallback. another post talking about it What is missing to make stm32 ADC DMA work? Transfer Compete does not occur. the solution of this post says that the core clock was to slow compared to the adc conversion clock and so did not wave the time to call the function. i was looking into the clock systeme on CubeMx and have a hard time with the clock set up. the f303RE was more strait forward and this one i get kinda lost. any one have some tips on what i should change to make this work. here is the cube mx set up: voila. here is my DMA set up:

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);

}

and here is my adc set up:

static void MX_ADC1_Init(void)
{
  ADC_ChannelConfTypeDef sConfig;

     /**Common config 
      */
  hadc1.Instance = ADC1;
  hadc1.Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV1;
  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.ContinuousConvMode = DISABLE;
  hadc1.Init.NbrOfConversion = 5;
  hadc1.Init.DiscontinuousConvMode = DISABLE;
  hadc1.Init.NbrOfDiscConversion = 1;
  hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START;
  hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
  hadc1.Init.DMAContinuousRequests = DISABLE;
  hadc1.Init.Overrun = ADC_OVR_DATA_PRESERVED;
  hadc1.Init.OversamplingMode = DISABLE;
  if (HAL_ADC_Init(&hadc1) != HAL_OK)
  {
    //_Error_Handler(__FILE__, __LINE__);
 }

  /**Configure Regular Channel 
   */
  sConfig.Channel = ADC_CHANNEL_8;
  sConfig.Rank = ADC_REGULAR_RANK_1;
  sConfig.SamplingTime = ADC_SAMPLETIME_47CYCLES_5;
  sConfig.SingleDiff = ADC_SINGLE_ENDED;
  sConfig.OffsetNumber = ADC_OFFSET_NONE;
  sConfig.Offset = 0;
  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
  {
    //_Error_Handler(__FILE__, __LINE__);
  }

    /**Configure Regular Channel 
    */
  sConfig.Channel = ADC_CHANNEL_9;
  sConfig.Rank = ADC_REGULAR_RANK_2;
  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
  {
    //_Error_Handler(__FILE__, __LINE__);
  }

    /**Configure Regular Channel 
    */
  sConfig.Channel = ADC_CHANNEL_10;
  sConfig.Rank = ADC_REGULAR_RANK_3;
  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
  {
    //_Error_Handler(__FILE__, __LINE__);
  }

    /**Configure Regular Channel 
    */
  sConfig.Channel = ADC_CHANNEL_11;
  sConfig.Rank = ADC_REGULAR_RANK_4;
  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
  {
    //_Error_Handler(__FILE__, __LINE__);
  }

    /**Configure Regular Channel 
    */
  sConfig.Channel = ADC_CHANNEL_12;
  sConfig.Rank = ADC_REGULAR_RANK_5;
  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
  {
    //_Error_Handler(__FILE__, __LINE__);
  }

}

and finally my code:

void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef& hadc){
    if(hadc.Instance == ADC1){
        adc_IT_flag = 1;
    }
}
void filtreRead(void){
    fenGlisflex(ADC_BUF[0],flex0);
    fenGlisflex(ADC_BUF[1],flex1);
    fenGlisflex(ADC_BUF[2],flex2);
    fenGlisflex(ADC_BUF[3],flex3);
    fenGlisflex(ADC_BUF[4],flex4);
    data_stable(flex0);
    data_stable(flex1);
    data_stable(flex2);
    data_stable(flex3);
    data_stable(flex4);
    adc_IT_flag = 0;
    HAL_ADC_Start_IT(&hadc1);
}
int main(void)
{
  HAL_Init();

  SystemClock_Config();

  MX_GPIO_Init();
  MX_DMA_Init();
  MX_USART2_UART_Init();
  MX_I2C1_Init();
  MX_USART1_UART_Init();
  MX_ADC1_Init();

  HAL_ADC_Start_DMA(&hadc1,(uint32_t*)ADC_BUF,5);
  HAL_ADC_Start_IT(&hadc1);

  while (1)
  {
      if(adc_IT_flag){
          filtreRead();
      }
  }
}

here is my new DMA Init function :

static void MX_DMA_Init(void) 
{
  /* DMA controller clock enable */
  __HAL_RCC_DMA1_CLK_ENABLE();



   hdma_adc1.Instance = DMA1_Channel1;
   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_PDATAALIGN_WORD;
   hdma_adc1.Init.Mode = DMA_CIRCULAR;
   hdma_adc1.Init.Priority = DMA_PRIORITY_LOW;
   HAL_DMA_DeInit(&hdma_adc1);
   HAL_DMA_Init(&hdma_adc1);

   //__HAL_LINKDMA(hadc, DMA_Handle, hdma_adc1);
  /* DMA interrupt init */
  /* DMA1_Channel1_IRQn interrupt configuration */
  HAL_NVIC_SetPriority(DMA1_Channel1_IRQn, 0, 0);
  HAL_NVIC_EnableIRQ(DMA1_Channel1_IRQn);

}
2

2 Answers

0
votes

In your MX_DMA_Init() function you are enabling the DMA IT, but you are missing the actual DMA configuration:

static void MX_DMA_Init(void) 
{
        /* Peripheral DMA init*/
        /* DMA controller clock enable */
        __HAL_RCC_DMA1_CLK_ENABLE();

        hdma_adc1.Instance = DMA1_Channel1;
        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_HALFWORD;
        hdma_adc1.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
        hdma_adc1.Init.Mode = DMA_NORMAL;
        hdma_adc1.Init.Priority = DMA_PRIORITY_HIGH;
        HAL_DMA_DeInit(&hdma_adc1);
        HAL_DMA_Init(&hdma_adc1);

        __HAL_LINKDMA(hadc, DMA_Handle, hdma_adc1);

        /* DMA interrupt init */
        HAL_NVIC_SetPriority(DMA1_Channel1_IRQn, 0, 0);
        HAL_NVIC_EnableIRQ(DMA1_Channel1_IRQn);

}

EDIT: a few other things If you want to use DMA, you should call HAL_ADC_Start_DMA() but not HAL_ADC_Start_IT(). If missing you should also add the handler into stm32xxxx_it.c file

void DMA1_Channel1_IRQHandler(void)
{
    /* Calling the peripheral interrupt handler */
    HAL_DMA_IRQHandler(&hdma_adc1);
}

I also suggest to use a 4-bytes multiple length for the DMA.

0
votes

So i found the problem. The HAL functions for DMA interrupts don't work in c++. I had converted my project in C++ and it wouldn't work as for the version that I made with the Nucleo-F303RE was in C. when i converted it to c++ it stopped working also.

EDIT: wow you will never guess what the error was.

void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef& hadc){
    if(hadc.Instance == ADC1){
        adc_IT_flag = 1;
    }
}

should actually be:

void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc){
    if(hadc.Instance == ADC1){
        adc_IT_flag = 1;
    }
}

the interrupt function wouldn't get called because of the pointer