cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F4 ADC DMA and Timer1 trigger

Parmin Nayani
Associate III

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();
}
}

 

 

1 ACCEPTED SOLUTION

Accepted Solutions

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 on "Accept as Solution" on the reply which solved your issue or answered your question.

View solution in original post

6 REPLIES 6
Sarra.S
ST Employee

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.

SofLit
ST Employee

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 on "Accept as Solution" on the reply which solved your issue or answered your question.

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();

}

}

 

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 on "Accept as Solution" on the reply which solved your issue or answered your question.

Hi SofLit,

Thank you very much for sharing the code. I will go through it and revert if I have any questions. 

 

And please close the thread by accepting the solution if you estimate that I answered your original question.

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.