2024-04-04 02:51 AM - last edited on 2024-04-04 06:26 AM by SofLit
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();
}
}
Solved! Go to Solution.
2024-04-04 07:13 AM
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.
2024-04-04 03:30 AM
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.
2024-04-04 03:49 AM
Hello,
2024-04-04 04:50 AM - last edited on 2024-04-04 06:47 AM by SofLit
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();
}
}
2024-04-04 07:13 AM
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.
2024-04-04 08:42 AM
Hi SofLit,
Thank you very much for sharing the code. I will go through it and revert if I have any questions.
2024-04-04 08:44 AM
And please close the thread by accepting the solution if you estimate that I answered your original question.