cancel
Showing results for 
Search instead for 
Did you mean: 

Complementary outputs with dead-time?

Damien Ratazy
Associate III

Hello,

I'm trying to have complementary outputs with dead-time on CH1/CH2/CH3 and CH1/CH2/CH3N using TIM1 and Output Compare Mode on STM32F429.

So I configured STM32CubeMX like in the picture below :

0690X000006BskZQAS.png

And there is the portion of my code :

(for testing purposes, a button press changes the state of CH1/CH1N)

void TIM1_ItUpFcn()
{
		if (HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0)==1)
		{
			TIM1->CCER = 4;
		}
		else
			{
			TIM1->CCER = 5;
			}
}

That code changes CC1E/CC1NE bits.

As a result,on the scope, I do get my complementary outputs on CH1 and CH1N, they invert each other when I press the button, but with no deadtime! I don't understand why i don't have that deadtime, like explained below :

0690X000006BskUQAS.png

1 ACCEPTED SOLUTION

Accepted Solutions

So you have both CH1 and CH1N enabled in CCER, and CH1 set to OC1M = 0b001 i.e. set to active when match.

After enabling the timer, you should then see only one edge, first a falling one on CH1N, and then a rising one on CH1, delayed by 320 timer cycles.

You maybe expect that there is dead time inserted when you manipulate the outputs through CCER - this is not the case; dead time is related to the OCxREF signal and that does not change when you change CCER; see the Complementary outputs and dead-time insertion chapter in RM.

JW

View solution in original post

6 REPLIES 6

Read out and check/post the content of all TIM registers (mainly BDTR)

JW

Damien Ratazy
Associate III

Hello,

In debug mode, BDTR=0x0000ACC8 (‭1010 1100 1100 1000‬)

There is the TIM1+TIM7 init code :

void DTC_initialize(void)
{
  /* Registration code */
 
  /* initialize error status */
  rtmSetErrorStatus(DTC_M, (NULL));
 
  /* user code (Start function Body) */
 
  /*Store TIM7 data information and its handler */
  G_TIM_Data[G_NbTimConf] = &TIM7_DataLink;
  G_TIM_Handler[G_NbTimConf] = &htim7;
  G_NbTimConf++;                       /*Inc number of configured TIM */
 
  /*Store TIM information */
  TIM7_DataLink.TIM_Prescaler = 8999;
  TIM7_DataLink.TIM_APBClock = 90000000;
  TIM7_DataLink.TIM_ARR = 5000 - 1;
  TIM7_DataLink.TIM_Clock = 10000.0;
  TIM7_DataLink.TIM_Freq = 2.0;
  TIM7_DataLink.CH1_duty = 0.0;
  TIM7_DataLink.CH2_duty = 0.0;
  TIM7_DataLink.CH3_duty = 0.0;
  TIM7_DataLink.CH4_duty = 0.0;
  TIM7_DataLink.CH1_type = UNKNOWN;
  TIM7_DataLink.CH2_type = UNKNOWN;
  TIM7_DataLink.CH3_type = UNKNOWN;
  TIM7_DataLink.CH4_type = UNKNOWN;
 
  /* Interrupt vector initialization */
  TIM7_DataLink.ItUpFcn = NULL;
  TIM7_DataLink.ItTrgFcn = NULL;
  TIM7_DataLink.ItComFcn = NULL;
  TIM7_DataLink.ItBrkFcn = NULL;
  TIM7_DataLink.ItCcFcn = NULL;
 
  /* Auto-reload preload enable */
  SET_BIT((&htim7)->Instance->CR1, TIM_CR1_ARPE);
 
  /*Update register value with blocset value*/
  /*Prescaler*/
  __HAL_TIM_SET_PRESCALER(&htim7,TIM7_DataLink.TIM_Prescaler);
 
  /*Autoreload: ARR */
  __HAL_TIM_SetAutoreload(&htim7, 5000 - 1);
 
  /* Time Base start IT */
  HAL_TIM_Base_Start_IT(&htim7);
 
  /* Update interrupt function */
  TIM7_DataLink.ItUpFcn = TIM7_ItUpFcn;
 
  /* Start interrupt for Update event*/
  HAL_TIM_Base_Start_IT(&htim7);
 
  /*Store TIM1 data information and its handler */
  G_TIM_Data[G_NbTimConf] = &TIM1_DataLink;
  G_TIM_Handler[G_NbTimConf] = &htim1;
  G_NbTimConf++;                       /*Inc number of configured TIM */
 
  /*Store TIM information */
  TIM1_DataLink.TIM_Prescaler = 0;
  TIM1_DataLink.TIM_APBClock = 180000000;
  TIM1_DataLink.TIM_ARR = 3600 - 1;
  TIM1_DataLink.TIM_Clock = 1.8E+8;
  TIM1_DataLink.TIM_Freq = 50000.0;
  TIM1_DataLink.CH1_duty = 0.0;
  TIM1_DataLink.CH2_duty = 0.0;
  TIM1_DataLink.CH3_duty = 0.0;
  TIM1_DataLink.CH4_duty = 0.0;
  TIM1_DataLink.CH1_type = OUTPUT_COMP;
  TIM1_DataLink.CH2_type = OUTPUT_COMP;
  TIM1_DataLink.CH3_type = OUTPUT_COMP;
  TIM1_DataLink.CH4_type = UNKNOWN;
 
  /* Interrupt vector initialization */
  TIM1_DataLink.ItUpFcn = NULL;
  TIM1_DataLink.ItTrgFcn = NULL;
  TIM1_DataLink.ItComFcn = NULL;
  TIM1_DataLink.ItBrkFcn = NULL;
  TIM1_DataLink.ItCcFcn = NULL;
 
  /* Auto-reload preload enable */
  SET_BIT((&htim1)->Instance->CR1, TIM_CR1_ARPE);
 
  /*Update register value with blocset value*/
  /*Prescaler*/
  __HAL_TIM_SET_PRESCALER(&htim1,TIM1_DataLink.TIM_Prescaler);
 
  /*Autoreload: ARR */
  __HAL_TIM_SetAutoreload(&htim1, 3600 - 1);
 
  /*Set CH1 Pulse value*/
  __HAL_TIM_SetCompare(&htim1, TIM_CHANNEL_1, (uint32_t)((3600 - 1)/2));
 
  /*Set CH2 Pulse value*/
  __HAL_TIM_SetCompare(&htim1, TIM_CHANNEL_2, (uint32_t)((3600 - 1)/2));
 
  /*Set CH3 Pulse value*/
  __HAL_TIM_SetCompare(&htim1, TIM_CHANNEL_3, (uint32_t)((3600 - 1)/2));
 
  /* Wait for htim1 State READY */
  while ((&htim1)->State == HAL_TIM_STATE_BUSY) {
  }
 
  HAL_TIM_OC_Start(&htim1, TIM_CHANNEL_1);
 
  /* Enable the complementary OC output 1 */
  HAL_TIMEx_OCN_Start(&htim1, TIM_CHANNEL_1);
 
  /* Wait for htim1 State READY */
  while ((&htim1)->State == HAL_TIM_STATE_BUSY) {
  }
 
  HAL_TIM_OC_Start(&htim1, TIM_CHANNEL_2);
 
  /* Enable the complementary OC output 2 */
  HAL_TIMEx_OCN_Start(&htim1, TIM_CHANNEL_2);
 
  /* Wait for htim1 State READY */
  while ((&htim1)->State == HAL_TIM_STATE_BUSY) {
  }
 
  HAL_TIM_OC_Start(&htim1, TIM_CHANNEL_3);
 
  /* Enable the complementary OC output 3 */
  HAL_TIMEx_OCN_Start(&htim1, TIM_CHANNEL_3);
 
  /* Update interrupt function */
  TIM1_DataLink.ItUpFcn = TIM1_ItUpFcn;
 
  /* Start interrupt for Update event*/
  HAL_TIM_Base_Start_IT(&htim1);
  ;
  ;
  ;
  ;
}

And the rest of the registers? I don't Cube.

JW

Damien Ratazy
Associate III

Here you go

So you have both CH1 and CH1N enabled in CCER, and CH1 set to OC1M = 0b001 i.e. set to active when match.

After enabling the timer, you should then see only one edge, first a falling one on CH1N, and then a rising one on CH1, delayed by 320 timer cycles.

You maybe expect that there is dead time inserted when you manipulate the outputs through CCER - this is not the case; dead time is related to the OCxREF signal and that does not change when you change CCER; see the Complementary outputs and dead-time insertion chapter in RM.

JW

Damien Ratazy
Associate III

Okay, so I finally found how to turn ON CH1/CH2/CH3 and CH1/CH2/CH3N with the appropriate deadtime, using CCMR1 and CCMR2 registers (by setting bits 4-6 for OC1M, bits 12-14 for OC2M on CCMR1, bits 4-6 for OC3M on CCMR2).