1

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 Answers2

1

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

0

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.

LoriB
  • 356
  • 3
  • 7
  • awesome it would make sense XD its like if cubeMx didn't generate the dma settings that i gave it. – Soleil Anker-Baril Apr 16 '18 at 17:09
  • well i have tried it out and the interrupt is still not called. ill update the main post with the new DMA set up code. – Soleil Anker-Baril Apr 16 '18 at 17:26
  • also i checked my stm32F303re code and its the same and works fine. i really think it might be a clock problem. – Soleil Anker-Baril Apr 16 '18 at 17:37
  • the DMA settings where set up in the stm32l4xx_hal_msp.c – Soleil Anker-Baril Apr 16 '18 at 18:27
  • I added more comments. As regarding the CubeMx configuration, you have to enable the DMA in the relative tab within the ADC configuration. – LoriB Apr 17 '18 at 07:37
  • ok so i read a bit on how to use the half word and its pretty interesting ill try it out maybe ill have more luck. as for the rest is already set up how you proposed. maybe by working with the half buffers ill be able to have access to the information without having the clock problem. – Soleil Anker-Baril Apr 17 '18 at 13:41
  • still no interrupts. ill still try and find a solution to post it but for my current project i will use my Nucleo-F303RE instead, since i was able to have it work. – Soleil Anker-Baril Apr 17 '18 at 14:23