cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F767: I would like to sample 5 channels on ADC1 using the DMA, and timer 1 triggering the conversions at a rate of 40 Hz.

james farrant
Associate II

The problem I am having is the flag in the HAL_ADC_ConvCmpltCallback() function is never set, so the "if" statement in my main while loop is never entered.

1 ACCEPTED SOLUTION

Accepted Solutions
james farrant
Associate II

Ok so I figured out what the problem was.

First of all thanks for the suggestion JW.

This project merged two separate STM32Cubemx projects that worked individually. A (usb writing app), and an (ADC + DMA + Timer 1 app). I copied and pasted all the code I thought necessary from the (ADC + DMA + Timer 1 app) to the (usb app).

I used the debugger to single step through the code while watching the ADC1 and Timer 1 memory values. Nothing was changing in the memory. I did the same thing in the original ADC + DMA + Timer 1 project and noticed that the memory values were updating correctly in the void HAL_ADC_MspInit(ADC_HandleTypeDef* hadc) function called from the file: stm32f7xx_hal_msp.c.

I compared the stm32f7xx_hal_msp.c files from both projects and found that I was missing the code shown below:

extern DMA_HandleTypeDef hdma_adc1;

void HAL_ADC_MspInit(ADC_HandleTypeDef* hadc)

{

 GPIO_InitTypeDef GPIO_InitStruct = {0};

 if(hadc->Instance==ADC1)

 {

 /* USER CODE BEGIN ADC1_MspInit 0 */

 /* USER CODE END ADC1_MspInit 0 */

  /* Peripheral clock enable */

  __HAL_RCC_ADC1_CLK_ENABLE();

  

  __HAL_RCC_GPIOA_CLK_ENABLE();

  /**ADC1 GPIO Configuration   

  PA0/WKUP   ------> ADC1_IN0

  PA1   ------> ADC1_IN1

  PA2   ------> ADC1_IN2

  PA3   ------> ADC1_IN3

  PA4   ------> ADC1_IN4 

  */

  GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3 

             |GPIO_PIN_4;

  GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;

  GPIO_InitStruct.Pull = GPIO_NOPULL;

  HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

  /* ADC1 DMA Init */

  /* ADC1 Init */

  hdma_adc1.Instance = DMA2_Stream0;

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

  hdma_adc1.Init.FIFOMode = DMA_FIFOMODE_DISABLE;

  if (HAL_DMA_Init(&hdma_adc1) != HAL_OK)

  {

   Error_Handler();

  }

  __HAL_LINKDMA(hadc,DMA_Handle,hdma_adc1);

  /* ADC1 interrupt Init */

  HAL_NVIC_SetPriority(ADC_IRQn, 0, 0);

  HAL_NVIC_EnableIRQ(ADC_IRQn);

 /* USER CODE BEGIN ADC1_MspInit 1 */

 /* USER CODE END ADC1_MspInit 1 */

 }

}

/**

* @brief ADC MSP De-Initialization

* This function freeze the hardware resources used in this example

* @param hadc: ADC handle pointer

* @retval None

*/

void HAL_ADC_MspDeInit(ADC_HandleTypeDef* hadc)

{

 if(hadc->Instance==ADC1)

 {

 /* USER CODE BEGIN ADC1_MspDeInit 0 */

 /* USER CODE END ADC1_MspDeInit 0 */

  /* Peripheral clock disable */

  __HAL_RCC_ADC1_CLK_DISABLE();

  

  /**ADC1 GPIO Configuration   

  PA0/WKUP   ------> ADC1_IN0

  PA1   ------> ADC1_IN1

  PA2   ------> ADC1_IN2

  PA3   ------> ADC1_IN3

  PA4   ------> ADC1_IN4 

  */

  HAL_GPIO_DeInit(GPIOA, GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3 

             |GPIO_PIN_4);

  /* ADC1 DMA DeInit */

  HAL_DMA_DeInit(hadc->DMA_Handle);

  /* ADC1 interrupt DeInit */

  HAL_NVIC_DisableIRQ(ADC_IRQn);

 /* USER CODE BEGIN ADC1_MspDeInit 1 */

 /* USER CODE END ADC1_MspDeInit 1 */

 }

}

/**

* @brief TIM_Base MSP Initialization

* This function configures the hardware resources used in this example

* @param htim_base: TIM_Base handle pointer

* @retval None

*/

void HAL_TIM_Base_MspInit(TIM_HandleTypeDef* htim_base)

{

 if(htim_base->Instance==TIM1)

 {

 /* USER CODE BEGIN TIM1_MspInit 0 */

 /* USER CODE END TIM1_MspInit 0 */

  /* Peripheral clock enable */

  __HAL_RCC_TIM1_CLK_ENABLE();

 /* USER CODE BEGIN TIM1_MspInit 1 */

 /* USER CODE END TIM1_MspInit 1 */

 }

}

/**

* @brief TIM_Base MSP De-Initialization

* This function freeze the hardware resources used in this example

* @param htim_base: TIM_Base handle pointer

* @retval None

*/

void HAL_TIM_Base_MspDeInit(TIM_HandleTypeDef* htim_base)

{

 if(htim_base->Instance==TIM1)

 {

 /* USER CODE BEGIN TIM1_MspDeInit 0 */

 /* USER CODE END TIM1_MspDeInit 0 */

  /* Peripheral clock disable */

  __HAL_RCC_TIM1_CLK_DISABLE();

 /* USER CODE BEGIN TIM1_MspDeInit 1 */

 /* USER CODE END TIM1_MspDeInit 1 */

 }

}

View solution in original post

5 REPLIES 5

Cube/HAL is open source, so you can debug it as any other code.

Observe the TIM registers to find out if it works as intended. Similarly observe ADC registers to find out if it is set up as needed and the conversions are started from the timer.

JW

james farrant
Associate II

Ok Thanks for the debugging suggestions. I will give this a shot.

berendi
Principal
uint8_t flag = 0;
/* ... */        
  while (1)
  {
    if(flag == 1){
      // Do something here
      flag = 0;
    }
  }

flag should be declared as volatile, otherwise the compiler might optimize the if statement away, because it has apparently no effect.

Every variable touched in an interrupt handler or by the DMA should be volatile.

james farrant
Associate II

Ok so I figured out what the problem was.

First of all thanks for the suggestion JW.

This project merged two separate STM32Cubemx projects that worked individually. A (usb writing app), and an (ADC + DMA + Timer 1 app). I copied and pasted all the code I thought necessary from the (ADC + DMA + Timer 1 app) to the (usb app).

I used the debugger to single step through the code while watching the ADC1 and Timer 1 memory values. Nothing was changing in the memory. I did the same thing in the original ADC + DMA + Timer 1 project and noticed that the memory values were updating correctly in the void HAL_ADC_MspInit(ADC_HandleTypeDef* hadc) function called from the file: stm32f7xx_hal_msp.c.

I compared the stm32f7xx_hal_msp.c files from both projects and found that I was missing the code shown below:

extern DMA_HandleTypeDef hdma_adc1;

void HAL_ADC_MspInit(ADC_HandleTypeDef* hadc)

{

 GPIO_InitTypeDef GPIO_InitStruct = {0};

 if(hadc->Instance==ADC1)

 {

 /* USER CODE BEGIN ADC1_MspInit 0 */

 /* USER CODE END ADC1_MspInit 0 */

  /* Peripheral clock enable */

  __HAL_RCC_ADC1_CLK_ENABLE();

  

  __HAL_RCC_GPIOA_CLK_ENABLE();

  /**ADC1 GPIO Configuration   

  PA0/WKUP   ------> ADC1_IN0

  PA1   ------> ADC1_IN1

  PA2   ------> ADC1_IN2

  PA3   ------> ADC1_IN3

  PA4   ------> ADC1_IN4 

  */

  GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3 

             |GPIO_PIN_4;

  GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;

  GPIO_InitStruct.Pull = GPIO_NOPULL;

  HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

  /* ADC1 DMA Init */

  /* ADC1 Init */

  hdma_adc1.Instance = DMA2_Stream0;

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

  hdma_adc1.Init.FIFOMode = DMA_FIFOMODE_DISABLE;

  if (HAL_DMA_Init(&hdma_adc1) != HAL_OK)

  {

   Error_Handler();

  }

  __HAL_LINKDMA(hadc,DMA_Handle,hdma_adc1);

  /* ADC1 interrupt Init */

  HAL_NVIC_SetPriority(ADC_IRQn, 0, 0);

  HAL_NVIC_EnableIRQ(ADC_IRQn);

 /* USER CODE BEGIN ADC1_MspInit 1 */

 /* USER CODE END ADC1_MspInit 1 */

 }

}

/**

* @brief ADC MSP De-Initialization

* This function freeze the hardware resources used in this example

* @param hadc: ADC handle pointer

* @retval None

*/

void HAL_ADC_MspDeInit(ADC_HandleTypeDef* hadc)

{

 if(hadc->Instance==ADC1)

 {

 /* USER CODE BEGIN ADC1_MspDeInit 0 */

 /* USER CODE END ADC1_MspDeInit 0 */

  /* Peripheral clock disable */

  __HAL_RCC_ADC1_CLK_DISABLE();

  

  /**ADC1 GPIO Configuration   

  PA0/WKUP   ------> ADC1_IN0

  PA1   ------> ADC1_IN1

  PA2   ------> ADC1_IN2

  PA3   ------> ADC1_IN3

  PA4   ------> ADC1_IN4 

  */

  HAL_GPIO_DeInit(GPIOA, GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3 

             |GPIO_PIN_4);

  /* ADC1 DMA DeInit */

  HAL_DMA_DeInit(hadc->DMA_Handle);

  /* ADC1 interrupt DeInit */

  HAL_NVIC_DisableIRQ(ADC_IRQn);

 /* USER CODE BEGIN ADC1_MspDeInit 1 */

 /* USER CODE END ADC1_MspDeInit 1 */

 }

}

/**

* @brief TIM_Base MSP Initialization

* This function configures the hardware resources used in this example

* @param htim_base: TIM_Base handle pointer

* @retval None

*/

void HAL_TIM_Base_MspInit(TIM_HandleTypeDef* htim_base)

{

 if(htim_base->Instance==TIM1)

 {

 /* USER CODE BEGIN TIM1_MspInit 0 */

 /* USER CODE END TIM1_MspInit 0 */

  /* Peripheral clock enable */

  __HAL_RCC_TIM1_CLK_ENABLE();

 /* USER CODE BEGIN TIM1_MspInit 1 */

 /* USER CODE END TIM1_MspInit 1 */

 }

}

/**

* @brief TIM_Base MSP De-Initialization

* This function freeze the hardware resources used in this example

* @param htim_base: TIM_Base handle pointer

* @retval None

*/

void HAL_TIM_Base_MspDeInit(TIM_HandleTypeDef* htim_base)

{

 if(htim_base->Instance==TIM1)

 {

 /* USER CODE BEGIN TIM1_MspDeInit 0 */

 /* USER CODE END TIM1_MspDeInit 0 */

  /* Peripheral clock disable */

  __HAL_RCC_TIM1_CLK_DISABLE();

 /* USER CODE BEGIN TIM1_MspDeInit 1 */

 /* USER CODE END TIM1_MspDeInit 1 */

 }

}

james farrant
Associate II

Also two missing functions from stm32f7_it.c were required. After that it worked perfectly.