2022-01-08 12:36 PM - edited 2023-11-20 07:29 AM
Hello everyone.
I am working on a project, where It has 6 PWM channels, and there will be 3 channels active at time,
As all PWM channels must have the same frecuency, all PWMs channel must start and stop at the same time, I am trying to define TIM2 as MASTER and TIM3 as Slave.
I was testing some options, but I couldn´t move forward.......In order to SYNC (as much as possible) I set Master, Slave and CNT registers in both TIMs, so after that I defined a Breakpoint in order to check if **** are same or almost the same, but CNT from TIM2 and TIM3 are not the same, there are running not tight as I expected..
I was reading RM008 14.3.20 Timer synchronization and wrote the following lines in order to set TIM2 as Master and TIM3 as Slave (as I explained above, and it is not working)
TIM2->CR2 = TIM_TRGO_ENABLE;
TIM3->SMCR = TIM_TS_ITR1 | TIM_SMCR_SMS_2 | TIM_SMCR_SMS_1;
HAL_TIM_Base_Start_IT(&htim2);
HAL_TIM_Base_Start_IT(&htim3);
TIM2->CNT=0;
TIM3->CNT=0;
TIM2 and TIM3 are defined using CUBEMX, both timers have the same configuration at this point (setup time), but later when the program is running, when the Overflow interruption on TIM2 happened, I stop timers TIM2 and TIM3, define Master and Slave and Set **** to 0 (I am setting Master and slave every time overflow happened, I know it is not ok, but as I am just testing if clocks are working together, I guess, is not a big issue,
later I will move it outside of the loop, but I did that just to see how the clock is set when Debugger is fired just after set (manually) CNT registers to 0, STM32CUBE debugger shows TIM2/3 **** values are NOT equal...Here is a small list of 4 tests (using RESSUME button in Debug mode).
1° 2° 3° 4°
TIM2_CNT 19752 19636 24790 15430
TIM3_CNT 5351 20811 17058 7503
diff 14401 -1175 7732 7927
The value of **** shows me that TIM2 and TIM3 are not working in SYNC mode.... test N°2 show that TIM2 CNT is = 19636 and TIM3 CNT = 20811, when TIM2 CNT is set to Zero before TIM3 CNT....I know, Timers are not set correctly,
this is the TIM2 and TIM3 configuration done it by CUBMX:
static void MX_TIM2_Init(void)
{
/* USER CODE BEGIN TIM2_Init 0 */
/* USER CODE END TIM2_Init 0 */
TIM_ClockConfigTypeDef sClockSourceConfig = {0};
TIM_MasterConfigTypeDef sMasterConfig = {0};
TIM_OC_InitTypeDef sConfigOC = {0};
/* USER CODE BEGIN TIM2_Init 1 */
/* USER CODE END TIM2_Init 1 */
htim2.Instance = TIM2;
htim2.Init.Prescaler = 0;
htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
htim2.Init.Period = 65535;
htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
htim2.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE;
if (HAL_TIM_Base_Init(&htim2) != HAL_OK)
{
Error_Handler();
}
sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
if (HAL_TIM_ConfigClockSource(&htim2, &sClockSourceConfig) != HAL_OK)
{
Error_Handler();
}
if (HAL_TIM_PWM_Init(&htim2) != HAL_OK)
{
Error_Handler();
}
sMasterConfig.MasterOutputTrigger = TIM_TRGO_ENABLE;
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_ENABLE;
if (HAL_TIMEx_MasterConfigSynchronization(&htim2, &sMasterConfig) != HAL_OK)
{
Error_Handler();
}
sConfigOC.OCMode = TIM_OCMODE_PWM1;
sConfigOC.Pulse = 0;
sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
if (HAL_TIM_PWM_ConfigChannel(&htim2, &sConfigOC, TIM_CHANNEL_1) != HAL_OK)
{
Error_Handler();
}
sConfigOC.OCPolarity = TIM_OCPOLARITY_LOW;
if (HAL_TIM_PWM_ConfigChannel(&htim2, &sConfigOC, TIM_CHANNEL_2) != HAL_OK)
{
Error_Handler();
}
if (HAL_TIM_PWM_ConfigChannel(&htim2, &sConfigOC, TIM_CHANNEL_3) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN TIM2_Init 2 */
/* USER CODE END TIM2_Init 2 */
HAL_TIM_MspPostInit(&htim2);
}
/**
* @brief TIM3 Initialization Function
* @PAram None
* @retval None
*/
static void MX_TIM3_Init(void)
{
/* USER CODE BEGIN TIM3_Init 0 */
/* USER CODE END TIM3_Init 0 */
TIM_MasterConfigTypeDef sMasterConfig = {0};
TIM_OC_InitTypeDef sConfigOC = {0};
/* USER CODE BEGIN TIM3_Init 1 */
/* USER CODE END TIM3_Init 1 */
htim3.Instance = TIM3;
htim3.Init.Prescaler = 0;
htim3.Init.CounterMode = TIM_COUNTERMODE_UP;
htim3.Init.Period = 65535;
htim3.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
htim3.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE;
if (HAL_TIM_PWM_Init(&htim3) != HAL_OK)
{
Error_Handler();
}
sMasterConfig.MasterOutputTrigger = TIM_TRGO_ENABLE;
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_ENABLE;
if (HAL_TIMEx_MasterConfigSynchronization(&htim3, &sMasterConfig) != HAL_OK)
{
Error_Handler();
}
sConfigOC.OCMode = TIM_OCMODE_PWM1;
sConfigOC.Pulse = 0;
sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
if (HAL_TIM_PWM_ConfigChannel(&htim3, &sConfigOC, TIM_CHANNEL_1) != HAL_OK)
{
Error_Handler();
}
sConfigOC.OCPolarity = TIM_OCPOLARITY_LOW;
if (HAL_TIM_PWM_ConfigChannel(&htim3, &sConfigOC, TIM_CHANNEL_2) != HAL_OK)
{
Error_Handler();
}
if (HAL_TIM_PWM_ConfigChannel(&htim3, &sConfigOC, TIM_CHANNEL_3) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN TIM3_Init 2 */
/* USER CODE END TIM3_Init 2 */
HAL_TIM_MspPostInit(&htim3);
}
in few words, I need to control 6 PWMs channels, using Overflow interruption from TIM2, when INT is fire, the main program loads some value from an array to CCRs, here is an example of two PWMs ports:
if (R_negativo==0) // estamos entre el INDICE 0 y 1499, es semiciclo +
{
TIM2->CCR1=lookUptable1[LookUpTableIndiceUsar_R]; //Fase R Semiciclo +
TIM3->CCR1=0; //Fase R Semiciclo -
}
else
{
TIM2->CCR1=0; //Fase R Semiciclo +
TIM3->CCR1=lookUptable1[LookUpTableIndiceUsar_R]; //Fase R Semiciclo -
}
So, as all CCRs (there are 6, but 3 are active at the same time) must be loaded at the same time, that is the reason why I need to have TIM2 and TIM3 working as master/slave.
I hope you can understand my issue.
if you can help/guide me, I will appreciate any comments, advice...
Regards
Alfredo
Solved! Go to Solution.
2022-01-08 02:32 PM
> It means: I need to set up TIMX as Master (not used until now) and TIM2/TIM3 as Slave?
Yes, exactly.
> is that correct?
I believe so. If it doesn't work, post your full timer setup code and I will take a look.
Careful mixing register access and HAL functions. For the timer, I usually prefer direct register access. But I believe what you wrote should work.
2022-01-08 02:01 PM
Reading register values in the debugger is not a viable strategy for checking if they're synchronized. First, the timers do not stop by default when the debugger is paused. Second, the debugger is not reading them at the exact same time. In the case of fast timers, there is no hope they will be equal.
A better strategy would be to set up a PWM signal on both timers and verify on scope they put out the same signal.
If you want two timers exactly synchronized, set both of them in slave triggered mode set to start on the TRGO signal of a master timer, then start the master timer. There are other ways, but that one is straightforward. If you can live with a few counts difference, then setting CNT=0 in sequence like you're doing will suffice.
2022-01-08 02:22 PM
Hi TDK.
First, thanks alot for your comments, I will check it with my oscilloscope.
You said:If you want two timers exactly synchronized, set both of them in slave triggered mode set to start on the TRGO signal of a master timer, then start the master timer. There are other ways, but that one is straightforward. If you can live with a few counts difference, then setting CNT=0 in sequence like you're doing will suffice
It means: I need to set up TIMX as Master (not used until now) and TIM2/TIM3 as Slave?
for example:
TIM4 as Master (no used at this time)
TIM2 and TIM3 as Slave (timers handler of 6 PWM channels)
TIM4->CR2 = TIM_TRGO_ENABLE;
TIM2->SMCR = TIM_TS_ITR3 | TIM_SMCR_SMS_2 | TIM_SMCR_SMS_1;
TIM3->SMCR = TIM_TS_ITR3 | TIM_SMCR_SMS_2 | TIM_SMCR_SMS_1;
TIM2->CNT=0;
TIM3->CNT=0;
HAL_TIM_Base_Start_IT(&htim2); // Slave
HAL_TIM_Base_Start_IT(&htim3); // Slave
HAL_TIM_Base_Start_IT(&htim4); // Master
is that correct?
br
Alfredo
2022-01-08 02:32 PM
> It means: I need to set up TIMX as Master (not used until now) and TIM2/TIM3 as Slave?
Yes, exactly.
> is that correct?
I believe so. If it doesn't work, post your full timer setup code and I will take a look.
Careful mixing register access and HAL functions. For the timer, I usually prefer direct register access. But I believe what you wrote should work.
2022-01-08 04:51 PM
TDK.
STM32F103C8 has 4 timers:
TIM1 is used for general use, this timer trigger keypad scan, ADC triggering, etc.
TIM2&TIM3 are used by PWM Channels
TIM4 is uded for encoder, I have one encoder working on this TIM4, untik now, as TIM4 is used by an encoder channel, Normal timer is desabled, i guess, it is because encoder is a counter and it is using timer function.....
So, I can´t use an extra TIM as Master to control TIM2 and TIM3.
if there isn´t option to set TIM2 as Master and TIM3 as slave, I will need to use an extra micro (using I2C between then) in order to have an STM32 just to handle 6 PWM channels with 3 timer of 4.
Please, if you can confirm that TIM2 can´t be Master and TIM3 slave, at the same time TIM3 is handling 3 PWM channels and TIM4 too, in order to start to move some function to other STM32,
Alfredo
2022-01-13 03:39 AM
Hi TDK.
Finally TIM2 is working as Mater and TIM3 as Slave in STM32F103C8.
Here is the setup in both timers...
TIM2 as Master:
TIM3 as Slave:
This picture was taken when TIM2 and TIM3 were not working as master/Slave:
And now, when TIM2 and TIM3 started to work as master Slave (Slave in TRIGGERED Mode)
Thank alot for youe help.
now I have an issue working with I2C ( i am trying to connect 2 Blue Pill Borad with "STM32F103C8"), but until now, Slave can´t received any data, I will find if this issue was reported by other guy, if not I will open a new question in roder to get support from ST community.
Thank you TDK.
br
Alfredo
2022-01-13 03:40 AM
Hi TDK.
Finally TIM2 is working as Mater and TIM3 as Slave in STM32F103C8.
Here is the setup in both timers...
TIM2 as Master:
TIM3 as Slave:
This picture was taken when TIM2 and TIM3 were not working as master/Slave:
And now, when TIM2 and TIM3 started to work as master Slave (Slave in TRIGGERED Mode)
Thank alot for youe help.
now I have an issue working with I2C ( i am trying to connect 2 Blue Pill Borad with "STM32F103C8"), but until now, Slave can´t received any data, I will find if this issue was reported by other guy, if not I will open a new question in roder to get support from ST community.
Thank you TDK.
br
Alfredo