cancel
Showing results for 
Search instead for 
Did you mean: 

ADC conversion using periodic timer

DSabo
Associate III

I want to use a periodic timer to trigger an ADC conversion (which uses DMA).

I have the periodic timer working OK on its own, and the ADC conversion with DMA working on its own... but when I try to put the two together it doesn't seem to trigger the conversion

ADC_HandleTypeDef hadcSensors;
DMA_HandleTypeDef hdma_adc1;
TIM_HandleTypeDef htim3;
 
TaskHandle_t pressureSensorTaskHandle;
TaskHandle_t adcSensorTaskHandle;
uint32_t ADC1ConvertedValues[2] = {0,0};
 
#define ADC_TIMER_PERIOD 4550
 
static void MX_DMA_Init(void);
void MX_TIM3_Init(void);
 
void PressureSensorTask(void *arg)
{
	int timerValue = 0;
	HAL_TIM_Base_Start(&htim3);
 
if (  HAL_ADC_Start_DMA(&hadcSensors, (uint32_t*)ADC1ConvertedValues, 2)!= HAL_OK)
		Error_Handler(__LINE__, __FILE__);
 
	while(true)
	{
		//Do something
	}
}
 
 
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)
{
	print(PRINT_ALWAYS,"%u::%u::%u\r\n", ADC1ConvertedValues[0], ADC1ConvertedValues[1],__HAL_TIM_GET_COUNTER(&htim3));
 
}
 
/**
  * @brief ADC1 Initialization Function
  * @param None
  * @retval None
  */
void MX_PressureSensor_Init(void)
{
	ADC_ChannelConfTypeDef sConfig = {0};
	BaseType_t createStatus = pdFAIL; // Init to fail to be safe
 
	/** Configure the global features of the ADC (Clock, Resolution, Data Alignment and number of conversion) */
	hadcSensors.Instance = ADC1;
	hadcSensors.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV4;
	hadcSensors.Init.Resolution = ADC_RESOLUTION_12B;
	hadcSensors.Init.ScanConvMode = DISABLE;
	hadcSensors.Init.ContinuousConvMode = DISABLE;
	hadcSensors.Init.DiscontinuousConvMode = DISABLE;
	hadcSensors.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_RISING;
	hadcSensors.Init.ExternalTrigConv = ADC_EXTERNALTRIGCONV_T3_TRGO;
	hadcSensors.Init.DataAlign = ADC_DATAALIGN_RIGHT;
	hadcSensors.Init.NbrOfConversion = 2;
	hadcSensors.Init.DMAContinuousRequests = DISABLE;
	hadcSensors.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
 
	if (HAL_ADC_Init(&hadcSensors) != HAL_OK)
	{
		Error_Handler(__LINE__, __FILE__);
	}
 
	/** Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time.	*/
 
	sConfig.Channel = ADC_CHANNEL_0;
	sConfig.Rank = PRESSURE_SENSOR_ADC_RANK;
	sConfig.SamplingTime = ADC_SAMPLETIME_3CYCLES;
	if (HAL_ADC_ConfigChannel(&hadcSensors, &sConfig) != HAL_OK)
	{
		Error_Handler(__LINE__, __FILE__);
	}
 
  sConfig.Channel = ADC_CHANNEL_14;
  sConfig.Rank = 2;
  if (HAL_ADC_ConfigChannel(&hadcSensors, &sConfig) != HAL_OK)
  {
    Error_Handler(__LINE__, __FILE__);
  }
 
	HAL_NVIC_SetPriority(ADC_IRQn, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY, 0);
	HAL_NVIC_EnableIRQ(ADC_IRQn);
 
	MX_DMA_Init();
 
	MX_TIM3_Init();
 
	createStatus = xTaskCreate(PressureSensorTask, "Pressure Sensor task", configMINIMAL_STACK_SIZE,(void*) NULL,1, &pressureSensorTaskHandle);
	configASSERT(createStatus == pdPASS);
}
/**
  * @brief TIM3 Initialization Function
  * @param None
  * @retval None
  */
void MX_TIM3_Init(void)
{
 
  /* USER CODE BEGIN TIM3_Init 0 */
 
  /* USER CODE END TIM3_Init 0 */
 
  TIM_ClockConfigTypeDef sClockSourceConfig = {0};
  TIM_MasterConfigTypeDef sMasterConfig = {0};
  TIM_OC_InitTypeDef sConfigOC = {0};
 
 
  /* USER CODE BEGIN TIM3_Init 1 */
  __HAL_RCC_TIM3_CLK_ENABLE();
  /* USER CODE END TIM3_Init 1 */
  htim3.Instance = TIM3;
  htim3.Init.Prescaler = 84000;
  htim3.Init.CounterMode = TIM_COUNTERMODE_UP;
  htim3.Init.Period = ADC_TIMER_PERIOD;
  htim3.Init.ClockDivision = TIM_CLOCKDIVISION_DIV4;
  htim3.Init.RepetitionCounter = 0;
  htim3.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE;
  if (HAL_TIM_Base_Init(&htim3) != HAL_OK)
  {
    Error_Handler(__LINE__, __FILE__);
  }
 
  HAL_NVIC_SetPriority(TIM3_IRQn, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY, 0);
  HAL_NVIC_EnableIRQ(TIM3_IRQn);
/*  sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
  if (HAL_TIM_ConfigClockSource(&htim3, &sClockSourceConfig) != HAL_OK)
  {
    Error_Handler(__LINE__, __FILE__);
  }
  if (HAL_TIM_OC_Init(&htim3) != HAL_OK)
  {
    Error_Handler(__LINE__, __FILE__);
  }
  sMasterConfig.MasterOutputTrigger = TIM_TRGO_UPDATE;
  sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
  if (HAL_TIMEx_MasterConfigSynchronization(&htim3, &sMasterConfig) != HAL_OK)
  {
    Error_Handler(__LINE__, __FILE__);
  }
  sConfigOC.OCMode = TIM_OCMODE_TIMING;
  sConfigOC.Pulse = 0;
  sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
  sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
  if (HAL_TIM_OC_ConfigChannel(&htim3, &sConfigOC, TIM_CHANNEL_1) != HAL_OK)
  {
    Error_Handler(__LINE__, __FILE__);
  }
  /* USER CODE BEGIN TIM3_Init 2 */
 
  /* USER CODE END TIM3_Init 2 */
 
}
 
/** 
  * Enable DMA controller clock
  */
static void MX_DMA_Init(void) 
{
 
  /* DMA controller clock enable */
  __HAL_RCC_DMA2_CLK_ENABLE();
 
  /* DMA interrupt init */
  /* DMA2_Stream0_IRQn interrupt configuration */
  HAL_NVIC_SetPriority(DMA2_Stream0_IRQn, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY, 0);
  HAL_NVIC_EnableIRQ(DMA2_Stream0_IRQn);
 
}
 
/**
* @brief ADC MSP Initialization
* This function configures the hardware resources used in this example
* @param hadc: ADC handle pointer
* @retval None
*/
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_GPIOC_CLK_ENABLE();
    __HAL_RCC_GPIOA_CLK_ENABLE();
    __HAL_RCC_DMA2_CLK_ENABLE();
    /**ADC1 GPIO Configuration    
    PA0-WKUP     ------> ADC1_IN0
    PA1     ------> ADC1_IN1 
    */
    GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1;
    GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
	
	GPIO_InitStruct.Pin = GPIO_PIN_4;
    GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    HAL_GPIO_Init(GPIOC, &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);
 
  /* USER CODE BEGIN ADC1_MspInit 1 */
 
  /* USER CODE END ADC1_MspInit 1 */
  }
 
}

2 REPLIES 2

Read out and check the TIM, ADC and DMA registers' content.

JW

DSabo
Associate III

Gave up on this... it was easier to use a normal sw trigger and trigger it from a periodic freertos task