Skip to main content
DSabo
Associate III
September 5, 2019
Question

ADC conversion using periodic timer

  • September 5, 2019
  • 2 replies
  • 640 views

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 */
 }
 
}

This topic has been closed for replies.

2 replies

waclawek.jan
Super User
September 6, 2019

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

JW

DSabo
DSaboAuthor
Associate III
September 13, 2019

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