cancel
Showing results for 
Search instead for 
Did you mean: 

Why ADC continuous readings from software are not possible?

PRedd.111
Associate III

I have STM32F303CCTX custom board.

IO Pin PB8 has a timer that triggers a gpio high for 200us and resets for 300us. creates a 1.8KHz wave with about 35% duty using plain timer mode. Timer IRQ handler also fires the adc conversion on pin PB0.

It continuously keeps running with no values for over a minute. Then suddenly exits to second for loop with the scans(mostly invalid values).

main.c

#define ADC_ARRY_SIZE   30
 
 
uint16_t adc_vals[ADC_ARRY_SIZE] = {0};
 
uint16_t adc_val = 0;
 
uint32_t adc_zero_count = 0;
 
uint32_t index_no = 0;
 
 
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef *hadc)
 
{
 
   adc_val = HAL_ADC_GetValue(&hadc3);
 
   if((adc_val != 0) && (index_no < ADC_ARRY_SIZE))
 
      adc_vals[index_no++] = adc_val;
 
   else if(adc_val == 0)
 
      adc_zero_count++;
 
}
 
void set_pwm2_duty(uint32_t duty_count)
 
{
 
     __HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_1, duty_count);
 
}
 
int main(void)
 
{
 
    adc_val = 0;
 
    adc_zero_count = 0;
 
    index_no = 0;
 
    adc_buffer_full = false;
 
    int i;
 
//Generated code begin
 
    HAL_Init();
 
    SystemClock_Config();
 
    MX_GPIO_Init();
 
   MX_ADC3_Init();
 
   MX_TIM2_Init();
 
   MX_TIM6_Init();
 
//generated code end
 
    set_laser_pwm_duty(3000);
 
   HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_1);
 
   HAL_GPIO_WritePin(GPIOB, GPIO_PIN_5, GPIO_PIN_RESET);
 
   HAL_GPIO_WritePin(GPIOGPIOB, GPIO_PIN_8, GPIO_PIN_SET);
 
   HAL_TIM_Base_Start_IT(&htim6);//start pulse timer
 
   adc_trigger = true;
 
    while (1)
 
    {
 
      /* USER CODE END WHILE */
 
 
      /* USER CODE BEGIN 3 */
 
      if(index_no >= 30)
 
            break;
 
      HAL_Delay(1);
 
 
   }
 
   HAL_TIM_Base_Stop(&htim6);//start blink timer
 
   HAL_TIM_PWM_Stop(&htim2, TIM_CHANNEL_1);
 
   HAL_ADC_Stop_IT(&hadc3);
 
   for(i=0;i<ADC_ARRY_SIZE;i++)
 
      ladc_vals[i] = adc_vals[i];
 
   for(;;);
 
}

1 ACCEPTED SOLUTION

Accepted Solutions
PRedd.111
Associate III

The issue in ADC setup. The sampling cycles were too low at 1.5 cycles. It needed at least 19 cycles to get a non zero value.

View solution in original post

9 REPLIES 9
TDK
Guru

If index_no is modified in an interrupt you should define it as volatile.

If you feel a post has answered your question, please click "Accept as Solution".

How are we supposed to debug this?

It won't advance the pointer for an indeterminate time if the ADC returns zero.

How do you know these are invalid values? Do have some plot or independent capture of the signals you can align?

A more rational approach to this is to use DMA into the array, and trigger the ADC directly with the TIM

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..

I did put break point on timer irq handler and it never fired.​ That seems to be the main issue.

As for debug, it's quite simple. The task is to get periodic adc samples which is where the timer comes to focus. You can attach a dc supply to a Single ended adc channel and set it up to give 10 mV at 25 mA.​

Tried it. Same issue.​

This assumes I'm interested in racking this up and testing it, the code's not even buildable.

My point would be to supply enough of your experimental data that one could look at what's happening from afar, and not have to repeat and understand observations I might not be able to reproduce in 2 minutes or less.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..

Here is a simple timer code where the callback doesnt work. Apparntly the IRQ handler in the stm32f3xx_it.c does get called. Most of it is system generated.

Main.c

Here is a simple timer code where the callback doesnt work. Apparntly the IRQ handler in the stm32f3xx_it.c does get called. Most of it is system generated.

main.c

/* USER CODE END Header */
 
/* Includes ------------------------------------------------------------------*/
#include "main.h"
 
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
 
/* USER CODE END Includes */
 
/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
 
/* USER CODE END PTD */
 
/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
 
/* USER CODE END PD */
 
/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */
 
/* USER CODE END PM */
 
/* Private variables ---------------------------------------------------------*/
TIM_HandleTypeDef htim6;
 
/* USER CODE BEGIN PV */
 
/* USER CODE END PV */
 
/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_TIM6_Init(void);
/* USER CODE BEGIN PFP */
 
/* USER CODE END PFP */
 
/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
void HAL_TIM_Period_ElapsedCallBack(TIM_HandleTypeDef *htim)
{
	//if(htim != &htim6)
	//	return;
	GPIO_PinState pulse_state;
	pulse_state = HAL_GPIO_ReadPin(PULSE_GPIO_Port, PULSE_Pin);
	if(pulse_state == GPIO_PIN_SET)
	{
		HAL_GPIO_WritePin(PULSE_GPIO_Port, PULSE_Pin, GPIO_PIN_RESET);
		__HAL_TIM_SET_AUTORELOAD(&htim6, 2560);
	}
	else
	{
		HAL_GPIO_WritePin(PULSE_GPIO_Port, PULSE_Pin, GPIO_PIN_SET);
		__HAL_TIM_SET_AUTORELOAD(&htim6, 1430);
	}
	HAL_TIM_Base_Start_IT(&htim6);
}
/* USER CODE END 0 */
 
/**
  * @brief  The application entry point.
  * @retval int
  */
int main(void)
{
  /* USER CODE BEGIN 1 */
 
  /* USER CODE END 1 */
  
 
  /* MCU Configuration--------------------------------------------------------*/
 
  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();
 
  /* USER CODE BEGIN Init */
 
  /* USER CODE END Init */
 
  /* Configure the system clock */
  SystemClock_Config();
 
  /* USER CODE BEGIN SysInit */
 
  /* USER CODE END SysInit */
 
  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_TIM6_Init();
  /* USER CODE BEGIN 2 */
  HAL_TIM_Base_Start_IT(&htim6);
  /* USER CODE END 2 */
 
  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */
 
    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}
 
/**
  * @brief System Clock Configuration
  * @retval None
  */
void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
 
  /** Initializes the CPU, AHB and APB busses clocks 
  */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
  RCC_OscInitStruct.HSEState = RCC_HSE_ON;
  RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;
  RCC_OscInitStruct.HSIState = RCC_HSI_ON;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
  RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL3;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }
  /** Initializes the CPU, AHB and APB busses clocks 
  */
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
 
  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
  {
    Error_Handler();
  }
}
 
/**
  * @brief TIM6 Initialization Function
  * @param None
  * @retval None
  */
static void MX_TIM6_Init(void)
{
 
  /* USER CODE BEGIN TIM6_Init 0 */
 
  /* USER CODE END TIM6_Init 0 */
 
  TIM_MasterConfigTypeDef sMasterConfig = {0};
 
  /* USER CODE BEGIN TIM6_Init 1 */
 
  /* USER CODE END TIM6_Init 1 */
  htim6.Instance = TIM6;
  htim6.Init.Prescaler = 9;
  htim6.Init.CounterMode = TIM_COUNTERMODE_UP;
  htim6.Init.Period = 1439;
  htim6.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE;
  if (HAL_TIM_Base_Init(&htim6) != HAL_OK)
  {
    Error_Handler();
  }
  sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
  sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
  if (HAL_TIMEx_MasterConfigSynchronization(&htim6, &sMasterConfig) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN TIM6_Init 2 */
 
  /* USER CODE END TIM6_Init 2 */
 
}
 
/**
  * @brief GPIO Initialization Function
  * @param None
  * @retval None
  */
static void MX_GPIO_Init(void)
{
  GPIO_InitTypeDef GPIO_InitStruct = {0};
 
  /* GPIO Ports Clock Enable */
  __HAL_RCC_GPIOF_CLK_ENABLE();
  __HAL_RCC_GPIOB_CLK_ENABLE();
 
  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(GPIOB, GPIO_PIN_5|PULSE_Pin, GPIO_PIN_RESET);
 
  /*Configure GPIO pins : PB5 PULSE_Pin */
  GPIO_InitStruct.Pin = GPIO_PIN_5|PULSE_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
 
}
 
/* USER CODE BEGIN 4 */
 
/* USER CODE END 4 */
 
/**
  * @brief  This function is executed in case of error occurrence.
  * @retval None
  */
void Error_Handler(void)
{
  /* USER CODE BEGIN Error_Handler_Debug */
  /* User can add his own implementation to report the HAL error return state */
 
  /* USER CODE END Error_Handler_Debug */
}
 
#ifdef  USE_FULL_ASSERT
/**
  * @brief  Reports the name of the source file and the source line number
  *         where the assert_param error has occurred.
  * @param  file: pointer to the source file name
  * @param  line: assert_param error line source number
  * @retval None
  */
void assert_failed(char *file, uint32_t line)
{ 
  /* USER CODE BEGIN 6 */
  /* User can add his own implementation to report the file name and line number,
     tex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
  /* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */
 

main.h

/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __MAIN_H
#define __MAIN_H
 
#ifdef __cplusplus
extern "C" {
#endif
 
/* Includes ------------------------------------------------------------------*/
#include "stm32f3xx_hal.h"
 
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
 
/* USER CODE END Includes */
 
/* Exported types ------------------------------------------------------------*/
/* USER CODE BEGIN ET */
 
/* USER CODE END ET */
 
/* Exported constants --------------------------------------------------------*/
/* USER CODE BEGIN EC */
 
/* USER CODE END EC */
 
/* Exported macro ------------------------------------------------------------*/
/* USER CODE BEGIN EM */
 
/* USER CODE END EM */
 
/* Exported functions prototypes ---------------------------------------------*/
void Error_Handler(void);
 
/* USER CODE BEGIN EFP */
 
/* USER CODE END EFP */
 
/* Private defines -----------------------------------------------------------*/
#define PULSE_Pin GPIO_PIN_8
#define PULSE_GPIO_Port GPIOB
/* USER CODE BEGIN Private defines */
 
/* USER CODE END Private defines */
 
#ifdef __cplusplus
}
#endif
 
#endif /* __MAIN_H */

Attached the full project.

The timer callback in main.c is not getting called while the irq handler in it.c is getting called. you can see it when you un-comment the gpio toggle in it.

Never mind. There were typo's in the callback function name in main.c. So it was not linked to irq handler. It was mapped as a seperate function.

Working project attached.

PRedd.111
Associate III

The issue in ADC setup. The sampling cycles were too low at 1.5 cycles. It needed at least 19 cycles to get a non zero value.