Skip to main content
Graduate II
August 29, 2024
Solved

Control amount of samples for timer STM32H7 via PWM?

  • August 29, 2024
  • 2 replies
  • 2146 views

Hello, I need to make 10 samples via Tim13 and PWM in STM32H7. I implemented the next script, but finally, on the oscilloscope, I saw about 50 samples every 0.1 sec. Do you know, how easily control the number of samples for Timer in stm32?

 

 

 

#include "main.h"
TIM_HandleTypeDef htim13;
void SystemClock_Config(void);
static void MPU_Config(void);
static void MX_GPIO_Init(void);
static void MX_TIM13_Init(void);

int main(void)
{
 MPU_Config();
 HAL_Init();
 SystemClock_Config();
 MX_GPIO_Init();
 MX_TIM13_Init();

uint32_t sample_counter = 0;
#define SAMPLE_COUNT 10

TIM13->PSC = 0; // No prescaling
TIM13->ARR = 1; // Minimum possible period
TIM13->CCR1 = 1; // 50% duty cycle
TIM13->RCR = 0; // No repetition
TIM13->CCMR1 |= (6 << 4);// PWM Mode 1 (not 2, as we want the output to be high when CNT < CCR1)
TIM13->CR1 &= ~TIM_CR1_OPM; // Disable One-pulse mode (we want continuous operation)
TIM13->CCER |= 1; // Capture/Compare 1 Enable
TIM13->BDTR |= TIM_BDTR_MOE; // Master Output enable
TIM13->CR1 |= TIM_CR1_CEN; // Enable the counter

while (1)
{
 if (sample_counter < SAMPLE_COUNT)
 {
 TIM13->CR1 |= TIM_CR1_CEN; // Enable the counter
 while(!(TIM13->SR & TIM_SR_UIF)){} // Wait for update event
 TIM13->SR &= ~1; // Clear the update event flag
 sample_counter++; // Increment the sample counter
 }
 else
 {
 TIM13->CR1 &= ~TIM_CR1_CEN; 
 HAL_Delay(0.1);
 sample_counter = 0;
 }
}

}

void SystemClock_Config(void)
{
 RCC_OscInitTypeDef RCC_OscInitStruct = {0};
 RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

 HAL_PWREx_ConfigSupply(PWR_LDO_SUPPLY);

 __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
 while(!__HAL_PWR_GET_FLAG(PWR_FLAG_VOSRDY)) {}
 __HAL_RCC_SYSCFG_CLK_ENABLE();
 __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE0);

 while(!__HAL_PWR_GET_FLAG(PWR_FLAG_VOSRDY)) {}

 RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
 RCC_OscInitStruct.HSIState = RCC_HSI_DIV1;
 RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
 RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
 RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;
 RCC_OscInitStruct.PLL.PLLM = 4;
 RCC_OscInitStruct.PLL.PLLN = 50;
 RCC_OscInitStruct.PLL.PLLP = 2;
 RCC_OscInitStruct.PLL.PLLQ = 4;
 RCC_OscInitStruct.PLL.PLLR = 2;
 RCC_OscInitStruct.PLL.PLLRGE = RCC_PLL1VCIRANGE_3;
 RCC_OscInitStruct.PLL.PLLVCOSEL = RCC_PLL1VCOWIDE;
 RCC_OscInitStruct.PLL.PLLFRACN = 0;
 if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
 {
 Error_Handler();
 }

 RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
 |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2
 |RCC_CLOCKTYPE_D3PCLK1|RCC_CLOCKTYPE_D1PCLK1;
 RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
 RCC_ClkInitStruct.SYSCLKDivider = RCC_SYSCLK_DIV1;
 RCC_ClkInitStruct.AHBCLKDivider = RCC_HCLK_DIV2;
 RCC_ClkInitStruct.APB3CLKDivider = RCC_APB3_DIV2;
 RCC_ClkInitStruct.APB1CLKDivider = RCC_APB1_DIV2;
 RCC_ClkInitStruct.APB2CLKDivider = RCC_APB2_DIV2;
 RCC_ClkInitStruct.APB4CLKDivider = RCC_APB4_DIV2;

 if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
 {
 Error_Handler();
 }
}

static void MX_TIM13_Init(void)
{
 TIM_OC_InitTypeDef sConfigOC = {0};
 htim13.Instance = TIM13;
 htim13.Init.Prescaler = 0;
 htim13.Init.CounterMode = TIM_COUNTERMODE_UP;
 htim13.Init.Period = 1;
 htim13.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
 htim13.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE;
 if (HAL_TIM_Base_Init(&htim13) != HAL_OK)
 {
 Error_Handler();
 }
 if (HAL_TIM_PWM_Init(&htim13) != HAL_OK)
 {
 Error_Handler();
 }
 if (HAL_TIM_OnePulse_Init(&htim13, TIM_OPMODE_SINGLE) != HAL_OK)
 {
 Error_Handler();
 }
 sConfigOC.OCMode = TIM_OCMODE_PWM1;
 sConfigOC.Pulse = 1;
 sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
 sConfigOC.OCFastMode = TIM_OCFAST_ENABLE;
 if (HAL_TIM_PWM_ConfigChannel(&htim13, &sConfigOC, TIM_CHANNEL_1) != HAL_OK)
 {
 Error_Handler();
 }
 HAL_TIM_MspPostInit(&htim13);
}


 

 

 

    This topic has been closed for replies.
    Best answer by TDK

    Created new project in CubeMX. Put the following statements in the main loop:

    HAL_TIM_PWM_Stop(&htim1, TIM_CHANNEL_1);
    HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1);
    HAL_Delay(100);

    And it gives the correct number of pulses. 11 in this case because i set RCR=10.

    TDK_1-1725026950801.png

    This is a bit cleaner with register access where all you have to do to send another pulse train is enable the timer:

    SET_BIT(TIM1->CR1, TIM_CR1_CEN);

     

     

    From your code:

    > HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1);
    > HAL_TIM_PWM_Stop(&htim1, TIM_CHANNEL_1);

    Don't stop the PWM immediately after you start it.

    2 replies

    Super User
    August 29, 2024

    For high speed pulses, which you have here, you're going to need to do it in hardware with the RCR register = 10 and with the timer in one pulse mode. If you set those up, and then enable the timer, it will do 10 pulses and disable when complete. Software is not going to be quick enough to stop after the last pulse and before the next one begins.

     

    However, TIM13 doesn't have an RCR register, so you'll need to swap to a timer that does (TIM1, 8, 16, 17)

    RonilAuthor
    Graduate II
    August 30, 2024

    thank you for your message. I started to use timer 1 with the next settings but didn't receive any result

     

     htim1.Instance = TIM1;
     htim1.Init.Prescaler = 0;
     htim1.Init.CounterMode = TIM_COUNTERMODE_UP;
     htim1.Init.Period = 1;
     htim1.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
     htim1.Init.RepetitionCounter = 10;
     htim1.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;

     

     in one pulse mode and without 

    with the next script I expected to see 10 samples, but actually it doesn't work like that

     

     MX_TIM1_Init();
     while (1)
     {
     /* USER CODE END WHILE */
     HAL_Delay(0.1);
     	 HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1);
     	 HAL_TIM_PWM_Stop(&htim1, TIM_CHANNEL_1);
    
     /* USER CODE BEGIN 3 */
     }

     

    Do you know what I did wrong?
    Actually I am not sure that  RCR register responsible for that 

    Super User
    August 30, 2024

    Did you use one pulse mode?

    (++) HAL_TIM_OnePulse_Init and HAL_TIM_OnePulse_ConfigChannel: to use the Timer
    in One Pulse Mode.

    Graduate II
    September 2, 2024

    That's no "fluctuation", it's called overshoot.

    It's probably due to bad scope-probe setup. For frequencies > 100kHz do NOT use the probe's GND cable, but a spring tip for GND directly attached to the probe's tip.

    What's the time scale of that scope pic? Can't really say if it's 20 ms or ns per division. If it's ms, then forget everything above, them you have some other circuit-related problem (load?), or configured the GPIO not correctly.

     

    RonilAuthor
    Graduate II
    September 2, 2024

    thank you! I measure 100 Mhz