2024-08-29 08:17 AM - last edited on 2024-08-29 08:21 AM by SofLit
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);
}
Solved! Go to Solution.
2024-08-30 07:15 AM
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.
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.
2024-08-29 08:51 AM - edited 2024-08-29 08:53 AM
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)
2024-08-30 04:54 AM - edited 2024-08-30 05:01 AM
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
2024-08-30 05:08 AM - edited 2024-08-30 07:06 AM
Did you use one pulse mode?
(++) HAL_TIM_OnePulse_Init and HAL_TIM_OnePulse_ConfigChannel: to use the Timer
in One Pulse Mode.
2024-08-30 05:30 AM
Yes, I tried both, with one pulse mode is active I only get 1 pulse instead of 10
2024-08-30 07:15 AM
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.
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.
2024-09-02 03:26 AM
Indeed. if I correctly undestand that I can use only timers with RCR
Also, what do you think about fluctuation after the timer is running out?
2024-09-02 03:38 AM
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.
2024-09-02 07:03 AM
thank you! I measure 100 Mhz