Skip to main content
Parmin Nayani
Associate III
April 4, 2024
Solved

STM32F4 ADC DMA and Timer1 trigger

  • April 4, 2024
  • 2 replies
  • 2482 views

Hello all,

I want to take ADC reading at regular intervals based on timer 1 (used OC mode). The timer must trigger the ADC to take a reading and the ADC in turn will trigger the DMA to transfer the ADC reading to memory. To check that the timer is running I am toggling a GPIO_PIN. This pin toggles but conversion is not getting triggered.

I have enabled one OC1 output pin toggle and that is toggling.  One more point is, the following call triggers one conversion.

HAL_ADC_Start_DMA (&hadc1, (uint32_t *)adc_buf,ADC_BUF_LEN);

I am missing the link to TIM1 OC1 and ADC start conversion whenever the OC1 match occurs. 

Can someone help please? 

Below is the ADC init code.

void MX_ADC1_Init(void)
{
__HAL_RCC_ADC1_CLK_ENABLE();
hadc1.Instance = ADC1;
hadc1.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV8;
hadc1.Init.Resolution = ADC_RESOLUTION_12B;
hadc1.Init.ScanConvMode = DISABLE; //
hadc1.Init.ContinuousConvMode = DISABLE; //
hadc1.Init.DiscontinuousConvMode = ENABLE; //
hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;

hadc1.Init.ExternalTrigConv = ADC_EXTERNALTRIGCONV_T1_CC1; // Is this correct?

hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
hadc1.Init.NbrOfConversion = 1; //
hadc1.Init.DMAContinuousRequests = DISABLE; //
hadc1.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
if (HAL_ADC_Init(&hadc1) != HAL_OK)
{
Error_Handler();
}

sConfig.Channel = ADC_CHANNEL_10; //ADC_CHANNEL_VBAT;
sConfig.Rank = 1;
sConfig.SamplingTime = ADC_SAMPLETIME_3CYCLES;
if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
{
Error_Handler();
}
}

 

 

Best answer by mƎALLEm

Hello,

I've created a project based on STM32F407-DISCO board on which the ADC is triggered by TIM1-CC1 event. DMA has been used in circular mode to transfer the converted data to the memory.

The converted channel is the internal Temperature sensor.

Hope it helps.

 

2 replies

ST Employee
April 4, 2024

Hello @Parmin Nayani

Could you also share the TIM configuration, your ADC config looks correct (sharing your project would be optimal) 

>>hadc1.Init.ExternalTrigConv = ADC_EXTERNALTRIGCONV_T1_CC1; // Is this correct?

You need to ensure that the ExternalTrigConv is set to the correct timer output compare event, so that's correct if you're using TIM1_CH1

Also, make sure that ExternalTrigConvEdge is set to the appropriate edge (rising, falling, or both) that you want to trigger the conversion. 

You can also check this valuable article: Using Timers to Trigger ADC conversions periodically

 

To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.
Parmin Nayani
Associate III
April 4, 2024

Hello Sarra and SofLit,

Thank you for your replies. I did a check on the ADC_CR2 bits by reading them. I found the value after all the initializations, to be 0x400. Just the EOCS bit is set. So I did a brute force setting of the EXTEN bits by 

ADC1->CR2 |= 0x30000000;   How to set these bits through the HAL call?

After this to start one set of conversions I called -> HAL_ADC_Start_DMA (&hadc1, (uint32_t *)adc_buf,ADC_BUF_LEN);  This seems to convert. TIM1_CH1 event value is 0000 so left it as it is. Sharing the project is no issue but the entire code is in a mess. I have several unused functions etc. I am posting the ADC init code. Here is the timer code

void MX_TIM1_Init(void)

{

GPIO_InitTypeDef GPIO_InitStruct;

TIM_OC_InitTypeDef sConfigOC = {0};

TIM_ClockConfigTypeDef sClockSourceConfig = {0};

TIM_MasterConfigTypeDef sMasterConfig = {0};





/* USER CODE BEGIN TIM2_Init 0 */

__HAL_RCC_TIM1_CLK_ENABLE();



__HAL_RCC_GPIOA_CLK_ENABLE();

/**TIM2 GPIO Configuration

PA5 ------> TIM2_CH1

*/

GPIO_InitStruct.Pin = GPIO_PIN_8;

GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;

GPIO_InitStruct.Pull = GPIO_NOPULL;

GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;

GPIO_InitStruct.Alternate = GPIO_AF1_TIM1;

HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

/* USER CODE END TIM2_Init 0 */

/* USER CODE BEGIN TIM2_Init 1 */

/* USER CODE END TIM2_Init 1 */

htim1.Instance = TIM1;

htim1.Init.Prescaler = 0;

htim1.Init.CounterMode = TIM_COUNTERMODE_UP;

htim1.Init.Period = 10000;

htim1.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;

htim1.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE; // shadow register used?

if (HAL_TIM_Base_Init(&htim1) != HAL_OK)

{

Error_Handler();

}



sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;

if (HAL_TIM_ConfigClockSource(&htim1, &sClockSourceConfig) != HAL_OK)

{

Error_Handler();

}



sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;

sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;

if (HAL_TIMEx_MasterConfigSynchronization(&htim1, &sMasterConfig) != HAL_OK)

{

Error_Handler();

}

sConfigOC.OCMode = TIM_OCMODE_TOGGLE; //TIM_OCMODE_TIMING;

sConfigOC.Pulse = 0;

sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;

sConfigOC.OCNPolarity = TIM_OCNPOLARITY_HIGH;

sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;

sConfigOC.OCIdleState = TIM_OCIDLESTATE_RESET;

sConfigOC.OCNIdleState = TIM_OCNIDLESTATE_RESET;

if (HAL_TIM_OC_ConfigChannel(&htim1, &sConfigOC, TIM_CHANNEL_1) != HAL_OK)

{

Error_Handler();

}

}

 

mƎALLEm
mƎALLEmBest answer
Technical Moderator
April 4, 2024

Hello,

I've created a project based on STM32F407-DISCO board on which the ADC is triggered by TIM1-CC1 event. DMA has been used in circular mode to transfer the converted data to the memory.

The converted channel is the internal Temperature sensor.

Hope it helps.

 

To give better visibility on the answered topics, please click "Best answer" on the reply which solved your issue or answered your question.
mƎALLEm
Technical Moderator
April 4, 2024

Hello,

  • Which STM32F4 part number you're using?
  • You need to enable continuous mode on ADC and DMA :

SofLit_1-1712227660859.png

  • This is the list of ADC internal triggers for regular channel conversion (from RM0090:(

SofLit_0-1712227542428.png

 

 

To give better visibility on the answered topics, please click "Best answer" on the reply which solved your issue or answered your question.