Skip to main content
Damien Ratazy
Associate III
Aug 12, 2018 10:16 PM UTC
Solved

Complementary outputs with dead-time?

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

    This topic has been closed for replies.
    waclawek.jan
    waclawek.janBest answer
    Super User
    Aug 13, 2018 4:41 PM UTC

    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

    6 replies

    waclawek.jan
    Super User
    Aug 13, 2018 5:58 AM UTC

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

    JW

    Damien Ratazy
    Associate III
    Aug 13, 2018 3:21 PM UTC

    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);
     ;
     ;
     ;
     ;
    }

    waclawek.jan
    Super User
    Aug 13, 2018 4:02 PM UTC

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

    JW

    Damien Ratazy
    Associate III
    Aug 13, 2018 4:12 PM UTC

    Here you go

    waclawek.jan
    waclawek.janBest answer
    Super User
    Aug 13, 2018 4:41 PM UTC

    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
    Aug 14, 2018 8:27 AM UTC

    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).