2
\$\begingroup\$

I am using STM32F030F4P6. When I call this function my ADC starts successfully and I can read an ADC value in the ADC callback, but my MCU hangs at this function line. What is the problem?

My code is generated by st32mcubemx and my IDE is IAR. I have a problem with this line. My program prints "OK1" and the ADC runs successfully, but my MCU doesn't print "OK2". This is a part of my main code generated by cubeMX:

 /* USER CODE BEGIN 2 */ 
 uint8_t ret;
 printf("OK1!\r\n");
 ret = HAL_ADC_Start_IT(&hadc);
 if (ret != HAL_OK) printf("ERROR Start ADC\r\n");
 else printf("ADC start sucess!\r\n");
 printf("OK2!\r\n");
 /* USER CODE END 2 */

And this is my ADC init:

/* Includes ------------------------------------------------------------------*/
#include "adc.h"
/* USER CODE BEGIN 0 */
/* USER CODE END 0 */
ADC_HandleTypeDef hadc;
/* ADC init function */
void MX_ADC_Init(void)
{
 ADC_ChannelConfTypeDef sConfig = {0};
 /** Configure the global features of the ADC (Clock, Resolution, Data Alignment and number of conversion) 
 */
 hadc.Instance = ADC1;
 hadc.Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV1;
 hadc.Init.Resolution = ADC_RESOLUTION_12B;
 hadc.Init.DataAlign = ADC_DATAALIGN_RIGHT;
 hadc.Init.ScanConvMode = ADC_SCAN_DIRECTION_FORWARD;
 hadc.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
 hadc.Init.LowPowerAutoWait = DISABLE;
 hadc.Init.LowPowerAutoPowerOff = DISABLE;
 hadc.Init.ContinuousConvMode = ENABLE;
 hadc.Init.DiscontinuousConvMode = DISABLE;
 hadc.Init.ExternalTrigConv = ADC_SOFTWARE_START;
 hadc.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
 hadc.Init.DMAContinuousRequests = DISABLE;
 hadc.Init.Overrun = ADC_OVR_DATA_PRESERVED;
 if (HAL_ADC_Init(&hadc) != HAL_OK)
 {
 Error_Handler();
 }
 /** Configure for the selected ADC regular channel to be converted. 
 */
 sConfig.Channel = ADC_CHANNEL_4;
 sConfig.Rank = ADC_RANK_CHANNEL_NUMBER;
 sConfig.SamplingTime = ADC_SAMPLETIME_239CYCLES_5;
 if (HAL_ADC_ConfigChannel(&hadc, &sConfig) != HAL_OK)
 {
 Error_Handler();
 }
}
void HAL_ADC_MspInit(ADC_HandleTypeDef* adcHandle)
{
 GPIO_InitTypeDef GPIO_InitStruct = {0};
 if (adcHandle->Instance==ADC1)
 {
 /* USER CODE BEGIN ADC1_MspInit 0 */
 /* USER CODE END ADC1_MspInit 0 */
 /* ADC1 clock enable */
 __HAL_RCC_ADC1_CLK_ENABLE();
 
 __HAL_RCC_GPIOA_CLK_ENABLE();
 /**ADC GPIO Configuration 
 PA4 ------> ADC_IN4 
 */
 GPIO_InitStruct.Pin = GPIO_PIN_4;
 GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
 GPIO_InitStruct.Pull = GPIO_NOPULL;
 HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
 /* ADC1 interrupt Init */
 HAL_NVIC_SetPriority(ADC1_IRQn, 0, 0);
 HAL_NVIC_EnableIRQ(ADC1_IRQn);
 /* USER CODE BEGIN ADC1_MspInit 1 */
 /* USER CODE END ADC1_MspInit 1 */
 }
}
void HAL_ADC_MspDeInit(ADC_HandleTypeDef* adcHandle)
{
 if (adcHandle->Instance==ADC1)
 {
 /* USER CODE BEGIN ADC1_MspDeInit 0 */
 /* USER CODE END ADC1_MspDeInit 0 */
 /* Peripheral clock disable */
 __HAL_RCC_ADC1_CLK_DISABLE();
 
 /**ADC GPIO Configuration 
 PA4 ------> ADC_IN4 
 */
 HAL_GPIO_DeInit(GPIOA, GPIO_PIN_4);
 /* ADC1 interrupt Deinit */
 HAL_NVIC_DisableIRQ(ADC1_IRQn);
 /* USER CODE BEGIN ADC1_MspDeInit 1 */
 /* USER CODE END ADC1_MspDeInit 1 */
 }
}

This is my ADC callback:

void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)
{
 if (hadc->Instance == ADC1)
 {
 adc_val = HAL_ADC_GetValue(hadc);
 Vin = adc_val*0.001;
 printf("ADC val:%d Vin:%f\r\n",adc_val,Vin);
 }
}

And this is my error callback. At this, I receive ADC ERR:2 meaning HAL_ADC_ERROR_OVR. I am getting the ADC value in the callback but this happens.

void HAL_ADC_ErrorCallback(ADC_HandleTypeDef *hadc)
{
 uint32_t adc_error;
 printf("ADC ERR:%d\r\n",hadc->ErrorCode);
}
ocrdu
9,34123 gold badges33 silver badges43 bronze badges
asked Dec 25, 2019 at 6:32
\$\endgroup\$
4
  • 1
    \$\begingroup\$ Your callback functions are being called from the ADC interrupt. It's almost certain that you can't do printf from an interrupt, and that's what's causing your code to hang. \$\endgroup\$ Commented Dec 25, 2019 at 7:56
  • \$\begingroup\$ OK, when I comment on the printf and get the result in the live watch window my MCU hangs too. \$\endgroup\$ Commented Dec 25, 2019 at 9:41
  • 1
    \$\begingroup\$ Time to add some Breakpoints and step through the code? \$\endgroup\$ Commented Dec 25, 2019 at 13:54
  • \$\begingroup\$ The ADC implementation in STM32 works perfect with DMA and circular buffer. For this reason any singular conversions make no sense, unless you run out of free DMA channels. Just set up circular buffer, add all your ADC channels to it and start continuous DMA conversions. It will take zero CPU time afterwards and you can simply read converted values from memory as necessary \$\endgroup\$ Commented Mar 7, 2023 at 8:57

2 Answers 2

1
\$\begingroup\$

What happens is that the printf in the conversion completion callback is still printing when the next interrupt happens so it can't execute until printf is done and therefore the result is not read in time and overrun happens. So it is usually not a good idea to call printf in an interrupt context, unless you have written it yourself to make it re-entrant and make it write to a buffer, and still it might be too slow.

answered Dec 25, 2019 at 8:35
\$\endgroup\$
3
  • \$\begingroup\$ OK, when I comment on the printf and get the result in the live watch window my MCU hangs too. \$\endgroup\$ Commented Dec 25, 2019 at 9:41
  • \$\begingroup\$ Same issues probably apply to the live watch window. You need a less invasive way to check your program. Maybe toggle a bit that you can see with a scope?? \$\endgroup\$ Commented Jul 25, 2023 at 19:57
  • \$\begingroup\$ see electronics.stackexchange.com/a/105294/11684 \$\endgroup\$ Commented Jul 25, 2023 at 20:00
0
\$\begingroup\$

you have to use ret as HAL_StatusTypeDef and your program is not running because it is going into hardfault_handler use HAL_StatusTypeDef ret then use comparioson

answered Mar 17, 2024 at 10:48
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.