2025-09-24 11:00 PM
Hello! How are you?
I'm having trouble again with the "TRGO" trigger event on the Master and Slave Timers. I need multi-channel PWM, but Timer 1 (the Master) and Timer 2 (which simply starts simultaneously with Timer 1) generate PWM with a single (initial) phase, and each timer operates on two PWM channel outputs. However, Slave Timers 15 and 3 should start generating PWM on their outputs (each timer uses two PWM channels) with some delay. This delay is provided by Timer Master 1 on its "TRGO" output, and I'm using the "OC3_REF" channel for this. Please see the diagram for this multi-channel PWM operation. Everything works perfectly, as expected, but only until all the specified Timers are stopped and then restarted. After that, Slave Timers 15 and 3 stop starting (see the screenshot of the oscilloscope display of all PWM channels for these Timers). I'll now provide the code for starting and stopping these Timers. There's a lot of code, so this is the most important part for now. I've already thoroughly reviewed the initial setup code for the Timers, and it no longer contains any problems, in my opinion. I've converted it to work directly with registers (not HAL), and everything works the same. I'll also provide the stop code in detail for now, since I believe the problem lies there. Please help. If you need any other code, I'll provide that, too. Thank you.
while (1)
{
Start_MultiPWM();
HAL_Delay(8000);
Stop_MultiPWM();
HAL_Delay(4000);
}
void Start_MultiPWM(void)
{
/* Setting up registers for Timers (exactly the same as for "HAL") */
SetupTimers(TIM3);
SetupTimers(TIM15);
SetupTimers(TIM2);
SetupTimers(TIM1);
/* For compatibility with "HAL" these structures also need to be initialized */
{
htim1.Instance = TIM1;
htim1.DMABurstState = HAL_DMA_BURST_STATE_READY;
TIM_CHANNEL_STATE_SET_ALL(&htim1, HAL_TIM_CHANNEL_STATE_READY);
TIM_CHANNEL_N_STATE_SET_ALL(&htim1, HAL_TIM_CHANNEL_STATE_READY);
htim1.State = HAL_TIM_STATE_READY;
htim2.Instance = TIM2;
htim2.DMABurstState = HAL_DMA_BURST_STATE_READY;
TIM_CHANNEL_STATE_SET_ALL(&htim2, HAL_TIM_CHANNEL_STATE_READY);
TIM_CHANNEL_N_STATE_SET_ALL(&htim2, HAL_TIM_CHANNEL_STATE_READY);
htim2.State = HAL_TIM_STATE_READY;
htim3.Instance = TIM3;
htim3.DMABurstState = HAL_DMA_BURST_STATE_READY;
TIM_CHANNEL_STATE_SET_ALL(&htim3, HAL_TIM_CHANNEL_STATE_READY);
TIM_CHANNEL_N_STATE_SET_ALL(&htim3, HAL_TIM_CHANNEL_STATE_READY);
htim3.State = HAL_TIM_STATE_READY;
htim15.Instance = TIM15;
htim15.DMABurstState = HAL_DMA_BURST_STATE_READY;
TIM_CHANNEL_STATE_SET_ALL(&htim15, HAL_TIM_CHANNEL_STATE_READY);
TIM_CHANNEL_N_STATE_SET_ALL(&htim15, HAL_TIM_CHANNEL_STATE_READY);
htim15.State = HAL_TIM_STATE_READY;
}
__attribute__((unused)) HAL_StatusTypeDef res;
/* Enable interrupts for TIM2 (we will use them to change duty cycle of its PWMs CH3 and CH4) */
res = HAL_TIM_Base_Start_IT(&htim2);
/* Enable interrupts for TIM3 (we will use them to change duty cycle of its PWMs CH3 and CH4) */
res = HAL_TIM_Base_Start_IT(&htim3);
/* Launch the PWM channels of the TIM15 Slave Timer (50 Hz, CH1 and CH1N) */
res = HAL_TIM_PWM_Start(&htim15, TIM_CHANNEL_1);
res = HAL_TIMEx_PWMN_Start(&htim15, TIM_CHANNEL_1);
/* Enable the corresponding channels for PWM 48kHz TIM3 (Slave for TIM1) */
res = HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_3);
res = HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_4);
HAL_Delay(50);
/* Launch the PWM channels TIM1 (50 Hz, CH1 and CH1N) */
res = HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1);
res = HAL_TIMEx_PWMN_Start(&htim1, TIM_CHANNEL_1);
HAL_Delay(50);
/* Start TIM1_OC3REF and this, after the required phase shift, will start TIM15 and TIM3 */
res = HAL_TIM_OC_Start(&htim1, TIM_CHANNEL_3);
/* Enable the corresponding channels for PWM 48kHz TIM2 */
res = HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_3);
res = HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_4);
__NOP();
}
void Stop_MultiPWM(void)
{
FullTimerReset(TIM2);
FullTimerReset(TIM3);
FullTimerReset(TIM15);
HAL_Delay(50);
FullTimerReset(TIM1);
TIM1->EGR = TIM_EGR_CC3G;
TIM1->SR = 0;
__HAL_RCC_TIM1_CLK_DISABLE();
__HAL_RCC_TIM2_CLK_DISABLE();
__HAL_RCC_TIM3_CLK_DISABLE();
__HAL_RCC_TIM15_CLK_DISABLE();
HAL_NVIC_DisableIRQ(TIM2_IRQn);
HAL_NVIC_DisableIRQ(TIM3_IRQn);
memset(&htim1, 0x00, sizeof(TIM_HandleTypeDef));
memset(&htim2, 0x00, sizeof(TIM_HandleTypeDef));
memset(&htim3, 0x00, sizeof(TIM_HandleTypeDef));
memset(&htim15, 0x00, sizeof(TIM_HandleTypeDef));
tim2_index = 0;
tim3_index = 0;
tim2_bottom = 0;
tim3_bottom = 0;
}
2025-09-24 11:06 PM
Here's the code for setting up the Timers registers. I converted it from the "HAL" version to write directly to the registers because I wanted to fully understand the problem and whether the Timers were being configured incorrectly. The Timers worked exactly the same way. After extensively studying the reference manual and these settings, I realized that everything is configured correctly and that's not where I thought the problem lay.
void SetupTimers(TIM_TypeDef* TIMx)
{
/* HAL_TIM_PWM_MspInit/HAL_TIM_Base_MspInit */
if (TIMx == TIM1)
{
__HAL_RCC_TIM1_CLK_ENABLE();
}
else if (TIMx == TIM2)
{
__HAL_RCC_TIM2_CLK_ENABLE();
TIMx->DIER = 0;
HAL_NVIC_SetPriority(TIM2_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(TIM2_IRQn);
}
else if (TIMx == TIM3)
{
__HAL_RCC_TIM3_CLK_ENABLE();
TIMx->DIER = 0;
HAL_NVIC_SetPriority(TIM3_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(TIM3_IRQn);
}
else if (TIMx == TIM15)
{
__HAL_RCC_TIM15_CLK_ENABLE();
}
TIMx->SR = 0;
/* HAL_TIM_PWM_Init */
{
uint32_t tmpcr1 = TIMx->CR1;
if (IS_TIM_COUNTER_MODE_SELECT_INSTANCE(TIMx))
{
/* Select the Counter Mode */
tmpcr1 &= ~(TIM_CR1_DIR | TIM_CR1_CMS);
tmpcr1 |= TIM_COUNTERMODE_UP;
}
if (IS_TIM_CLOCK_DIVISION_INSTANCE(TIMx))
{
/* Set the clock division */
tmpcr1 &= ~TIM_CR1_CKD;
tmpcr1 |= (uint32_t)TIM_CLOCKDIVISION_DIV1;
}
/* Set the auto-reload preload */
MODIFY_REG(tmpcr1, TIM_CR1_ARPE, TIM_AUTORELOAD_PRELOAD_DISABLE);
TIM1->CR1 = tmpcr1;
/* Set the Autoreload value */
TIMx->ARR = (uint32_t)1000;
if (TIMx == TIM1 || TIMx == TIM15)
{
/* Set the Prescaler value */
TIMx->PSC = 2879;
}
else if (TIMx == TIM2 || TIMx == TIM3)
{
/* Set the Prescaler value */
TIMx->PSC = 2;
}
if (IS_TIM_REPETITION_COUNTER_INSTANCE(TIMx))
{
/* Set the Repetition Counter value */
TIMx->RCR = 0;
}
/* Generate an update event to reload the Prescaler and the Repetition Counter
* (only for Advanced Timer) value immediately */
TIMx->EGR = TIM_EGR_UG;
/* Check if the update flag is set after the Update Generation, if so clear the UIF flag */
if (HAL_IS_BIT_SET(TIMx->SR, TIM_FLAG_UPDATE))
{
/* Clear the update flag */
CLEAR_BIT(TIMx->SR, TIM_FLAG_UPDATE);
}
}
/* HAL_TIM_SlaveConfigSynchro -> TIM_SlaveTimer_SetConfig */
if (TIMx == TIM3 || TIMx == TIM15)
{
/* Get the TIMx SMCR register value */
uint32_t tmpsmcr = TIMx->SMCR;
/* Reset the Trigger Selection Bits */
tmpsmcr &= ~TIM_SMCR_TS;
/* Set the Input Trigger source */
tmpsmcr |= TIM_TS_ITR0;
/* Reset the slave mode Bits */
tmpsmcr &= ~TIM_SMCR_SMS;
/* Set the slave mode */
tmpsmcr |= TIM_SLAVEMODE_TRIGGER;
/* Write to TIMx SMCR */
TIMx->SMCR = tmpsmcr;
/* Disable Trigger Interrupt */
TIMx->DIER &= ~(TIM_IT_TRIGGER);
/* Disable Trigger DMA request */
TIMx->DIER &= ~(TIM_DMA_TRIGGER);
}
/* HAL_TIMEx_MasterConfigSynchronization
* TIM1: MasterOutputTrigger = TIM_TRGO_OC3REF;
* MasterOutputTrigger2 = TIM_TRGO2_RESET; 0
* MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
* TIM2, TIM3, TIM15: MasterOutputTrigger = TIM_TRGO_RESET; 0
* MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE; 0
*/
{
/* Get the TIMx CR2 register value */
uint32_t tmpcr2 = TIMx->CR2;
/* Get the TIMx SMCR register value */
uint32_t tmpsmcr = TIMx->SMCR;
/* If the timer supports ADC synchronization through TRGO2, set the master mode selection 2 */
if (IS_TIM_TRGO2_INSTANCE(TIMx))
{
/* Clear the MMS2 bits */
tmpcr2 &= ~TIM_CR2_MMS2;
/* Select the TRGO2 source*/
tmpcr2 |= TIM_TRGO2_RESET;
}
/* Reset the MMS Bits */
tmpcr2 &= ~TIM_CR2_MMS;
/* Select the TRGO source */
tmpcr2 |= (TIMx == TIM1) ? TIM_TRGO_OC3REF : TIM_TRGO_RESET;
/* Update TIMx CR2 */
TIMx->CR2 = tmpcr2;
if (IS_TIM_SLAVE_INSTANCE(TIMx))
{
/* Reset the MSM Bit */
tmpsmcr &= ~TIM_SMCR_MSM;
/* Set master mode */
tmpsmcr |= TIM_MASTERSLAVEMODE_DISABLE;
/* Update TIMx SMCR */
TIMx->SMCR = tmpsmcr;
}
}
/* HAL_TIM_PWM_ConfigChannel -> TIM_CHANNEL_1 -> TIM_OC1_SetConfig */
if (TIMx == TIM1 || TIMx == TIM15)
{
/* Get the TIMx CCER register value */
uint32_t tmpccer = TIMx->CCER;
/* Disable the Channel 1: Reset the CC1E Bit */
TIMx->CCER &= ~TIM_CCER_CC1E;
/* Get the TIMx CR2 register value */
uint32_t tmpcr2 = TIMx->CR2;
/* Get the TIMx CCMR1 register value */
uint32_t tmpccmr1 = TIMx->CCMR1;
/* Reset the Output Compare Mode Bits */
tmpccmr1 &= ~TIM_CCMR1_OC1M;
tmpccmr1 &= ~TIM_CCMR1_CC1S;
/* Select the Output Compare Mode */
tmpccmr1 |= TIM_OCMODE_PWM1; /* OCMode */
/* Reset the Output Polarity level */
tmpccer &= ~TIM_CCER_CC1P;
/* Set the Output Compare Polarity */
tmpccer |= TIM_OCPOLARITY_HIGH; /* OCPolarity */
if (IS_TIM_CCXN_INSTANCE(TIMx, TIM_CHANNEL_1))
{
/* Reset the Output N Polarity level */
tmpccer &= ~TIM_CCER_CC1NP;
/* Set the Output N Polarity */
tmpccer |= TIM_OCNPOLARITY_HIGH; /* OCNPolarity */
/* Reset the Output N State */
tmpccer &= ~TIM_CCER_CC1NE;
}
if (IS_TIM_BREAK_INSTANCE(TIMx))
{
/* Reset the Output Compare and Output Compare N IDLE State */
tmpcr2 &= ~TIM_CR2_OIS1;
tmpcr2 &= ~TIM_CR2_OIS1N;
/* Set the Output Idle state */
tmpcr2 |= TIM_OCIDLESTATE_RESET; /* OCIdleState */
/* Set the Output N Idle state */
tmpcr2 |= TIM_OCNIDLESTATE_RESET; /* OCNIdleState */
}
/* Write to TIMx CR2 */
TIMx->CR2 = tmpcr2;
/* Write to TIMx CCMR1 */
TIMx->CCMR1 = tmpccmr1;
/* Set the Capture Compare Register value */
TIMx->CCR1 = 500; /* Pulse */
/* Write to TIMx CCER */
TIMx->CCER = tmpccer;
/* Set the Preload enable bit for channel1 */
TIMx->CCMR1 |= TIM_CCMR1_OC1PE;
/* Configure the Output Fast mode */
TIMx->CCMR1 &= ~TIM_CCMR1_OC1FE;
TIMx->CCMR1 |= TIM_OCFAST_DISABLE; /* OCFastMode */
}
/* HAL_TIM_PWM_ConfigChannel ->
* Timer Mode Chahhels
* TIM1 : TIM_OCMODE_ACTIVE : TIM_CHANNEL_3
* TIM2 and TIM3 : TIM_OCMODE_PWM1 : TIM_CHANNEL_3 and TIM_CHANNEL_4
*/
if (TIMx == TIM1 || TIMx == TIM2 || TIMx == TIM3)
{
/* Get the TIMx CCER register value */
uint32_t tmpccer = TIMx->CCER;
/* (*) Get the TIMx CR2 register value */
uint32_t tmpcr2 = TIMx->CR2;
/* (*) Get the TIMx CCMR2 register value */
uint32_t tmpccmrx = TIMx->CCMR2;
/* Disable the Channel 3: Reset the CC3E Bit */
TIMx->CCER &= ~TIM_CCER_CC3E;
/* TIM2 and TIM3: Channel 4 in 'TIM_OCMODE_PWM1' */
if (TIMx != TIM1)
{
/* Disable the Channel 4: Reset the CC4E Bit */
TIMx->CCER &= ~TIM_CCER_CC4E;
/* Reset the Output Compare mode and Capture/Compare selection Bits */
tmpccmrx &= ~TIM_CCMR2_OC4M;
tmpccmrx &= ~TIM_CCMR2_CC4S;
/* (*) Select the Output Compare Mode */
tmpccmrx |= (TIM_OCMODE_PWM1 << 8U);
/* Reset the Output Polarity level */
tmpccer &= ~TIM_CCER_CC4P;
/* Set the Output Compare Polarity */
tmpccer |= (TIM_OCPOLARITY_HIGH << 12U);
if (IS_TIM_CCXN_INSTANCE(TIMx, TIM_CHANNEL_4))
{
/* Reset the Output N Polarity level */
tmpccer &= ~TIM_CCER_CC4NP;
/* Set the Output N Polarity */
tmpccer |= (TIM_OCNPOLARITY_HIGH << 12U);
/* Reset the Output N State */
tmpccer &= ~TIM_CCER_CC4NE;
}
if (IS_TIM_BREAK_INSTANCE(TIMx))
{
/* Reset the Output Compare IDLE State */
tmpcr2 &= ~TIM_CR2_OIS4;
/* Reset the Output Compare N IDLE State */
tmpcr2 &= ~TIM_CR2_OIS4N;
/* Set the Output Idle state */
tmpcr2 |= (TIM_OCIDLESTATE_RESET << 6U);
/* Set the Output N Idle state */
tmpcr2 |= (TIM_OCNIDLESTATE_RESET << 6U);
}
}
/* Reset the Output Compare mode and Capture/Compare selection Bits */
tmpccmrx &= ~TIM_CCMR2_OC3M;
tmpccmrx &= ~TIM_CCMR2_CC3S;
/* Select the Output Compare Mode */
tmpccmrx |= (TIMx == TIM1) ? TIM_OCMODE_ACTIVE : TIM_OCMODE_PWM1;
/* Reset the Output Polarity level */
tmpccer &= ~TIM_CCER_CC3P;
/* Set the Output Compare Polarity */
tmpccer |= (TIM_OCPOLARITY_HIGH << 8U);
if (IS_TIM_CCXN_INSTANCE(TIMx, TIM_CHANNEL_3))
{
/* Reset the Output N Polarity level */
tmpccer &= ~TIM_CCER_CC3NP;
/* Set the Output N Polarity */
tmpccer |= (TIM_OCNPOLARITY_HIGH << 8U);
/* Reset the Output N State */
tmpccer &= ~TIM_CCER_CC3NE;
}
if (IS_TIM_BREAK_INSTANCE(TIMx))
{
/* Reset the Output Compare and Output Compare N IDLE State */
tmpcr2 &= ~TIM_CR2_OIS3;
tmpcr2 &= ~TIM_CR2_OIS3N;
/* Set the Output Idle state */
tmpcr2 |= (TIM_OCIDLESTATE_RESET << 4U);
/* Set the Output N Idle state */
tmpcr2 |= (TIM_OCNIDLESTATE_RESET << 4U);
}
/* Write to TIMx CR2 */
TIMx->CR2 = tmpcr2;
/* Write to TIMx CCMR2 */
TIMx->CCMR2 = tmpccmrx;
/* Set the Capture Compare Register value */
if (TIMx == TIM1)
{
TIMx->CCR3 = 250; /* Pulse TIM1_OC3REF */
}
else
{
TIMx->CCR3 = 0; /* Pulse TIM2_OC3REF */
TIMx->CCR4 = 0; /* Pulse TIM3_OC3REF */
}
/* Write to TIMx CCER */
TIMx->CCER = tmpccer;
/* Configure the "Channel 3" and "Channel 4" in PWM mode */
if (TIMx != TIM1)
{
/* Set the Preload enable bit for channel3 */
TIMx->CCMR2 |= TIM_CCMR2_OC3PE;
/* Configure the Output Fast mode */
TIMx->CCMR2 &= ~TIM_CCMR2_OC3FE;
TIMx->CCMR2 |= TIM_OCFAST_DISABLE; /* OCFastMode */
/* Set the Preload enable bit for channel4 */
TIMx->CCMR2 |= TIM_CCMR2_OC4PE;
/* Configure the Output Fast mode */
TIMx->CCMR2 &= ~TIM_CCMR2_OC4FE;
TIMx->CCMR2 |= TIM_OCFAST_DISABLE << 8U; /* OCFastMode */
}
}
/* HAL_TIMEx_ConfigBreakDeadTime */
if (TIMx == TIM1 || TIMx == TIM15)
{
/* Keep this variable initialized to 0 as it is used to configure BDTR register */
uint32_t tmpbdtr = 0U;
/* Set the Lock level, the Break enable Bit and the Polarity, the OSSR State,
* the OSSI State, the dead time value and the Automatic Output Enable Bit */
MODIFY_REG(tmpbdtr, TIM_BDTR_DTG, 150); /* DeadTime */
MODIFY_REG(tmpbdtr, TIM_BDTR_LOCK, TIM_LOCKLEVEL_OFF); /* LockLevel */
MODIFY_REG(tmpbdtr, TIM_BDTR_OSSR, TIM_OSSR_DISABLE); /* OffStateRunMode */
MODIFY_REG(tmpbdtr, TIM_BDTR_OSSI, TIM_OSSI_DISABLE); /* OffStateIDLEMode */
MODIFY_REG(tmpbdtr, TIM_BDTR_BKE, TIM_BREAK_DISABLE); /* BreakState */
MODIFY_REG(tmpbdtr, TIM_BDTR_BKP, TIM_BREAKPOLARITY_HIGH); /* BreakPolarity */
MODIFY_REG(tmpbdtr, TIM_BDTR_AOE, TIM_AUTOMATICOUTPUT_DISABLE); /* AutomaticOutput */
MODIFY_REG(tmpbdtr, TIM_BDTR_BKF, (0 << TIM_BDTR_BKF_Pos)); /* BreakFilter */
MODIFY_REG(tmpbdtr, TIM_BDTR_BKBID, TIM_BREAK_AFMODE_INPUT); /* BreakAFMode */
if (IS_TIM_BKIN2_INSTANCE(TIMx))
{
/* Set the BREAK2 input related BDTR bits */
MODIFY_REG(tmpbdtr, TIM_BDTR_BK2F, (0 << TIM_BDTR_BK2F_Pos)); /* Break2Filter */
MODIFY_REG(tmpbdtr, TIM_BDTR_BK2E, TIM_BREAK2_DISABLE); /* Break2State */
MODIFY_REG(tmpbdtr, TIM_BDTR_BK2P, TIM_BREAK2POLARITY_HIGH); /* Break2Polarity */
MODIFY_REG(tmpbdtr, TIM_BDTR_BK2BID, TIM_BREAK_AFMODE_INPUT); /* Break2AFMode */
}
/* Set TIMx_BDTR */
TIMx->BDTR = tmpbdtr;
}
/* ----------- HAL_TIM_MspPostInit ----------- */
GPIO_InitTypeDef GPIO_InitStruct = { 0 };
if (TIMx == TIM1)
{
__HAL_RCC_GPIOC_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
/* TIM1 GPIO Configuration
* PC0 ------> TIM1_CH1
* PA7 ------> TIM1_CH1N
*/
GPIO_InitStruct.Pin = GPIO_PIN_0;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF2_TIM1;
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
GPIO_InitStruct.Pin = GPIO_PIN_7;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF6_TIM1;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
}
else if (TIMx == TIM2)
{
__HAL_RCC_GPIOB_CLK_ENABLE();
/* TIM2 GPIO Configuration
* PB10 ------> TIM2_CH3
* PB11 ------> TIM2_CH4
*/
GPIO_InitStruct.Pin = GPIO_PIN_10 | GPIO_PIN_11;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF1_TIM2;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
}
else if (TIMx == TIM3)
{
__HAL_RCC_GPIOB_CLK_ENABLE();
/* TIM3 GPIO Configuration
* PB0 ------> TIM3_CH3
* PB1 ------> TIM3_CH4
*/
GPIO_InitStruct.Pin = GPIO_PIN_0 | GPIO_PIN_1;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF2_TIM3;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
}
else if (TIMx == TIM15)
{
__HAL_RCC_GPIOB_CLK_ENABLE();
/* TIM15 GPIO Configuration
* PB14 ------> TIM15_CH1
* PB15 ------> TIM15_CH1N
*/
GPIO_InitStruct.Pin = GPIO_PIN_14;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF1_TIM15;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
GPIO_InitStruct.Pin = GPIO_PIN_15;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF2_TIM15;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
}
}
2025-09-25 1:02 AM - edited 2025-09-25 1:03 AM
Read out and check/compare-to-working-state content of the TIM registers.
Try to reduce the problem as much as possible, e.g. write a minimal code which uses only one master-slave pair of timers.
JW