cancel
Showing results for 
Search instead for 
Did you mean: 

How to enable Complementary Output and Normal Output with Output Compare in TIM

Hi,

I am having a hard time trying to configure the uC (STM32F446, but that is not important) to output a crafted signal via the Output Compare mode via DMA.

What I want is to output a digital signal, that is created via Toggling the Channel Output Pins with the Output Compare register. I can output the signal through one of the pins associated to the Channel or Negated Channel, but not both at the same time without adding some dirty code (I wish to use the HAL)

With "HAL_TIM_OC_Start_DMA" I can output the signal to the Normal channel and with HAL_TIM_OCN_Start_DMA I can output the signal through the Negated channel, But I cant get to find a way to output the same signal (or negated) through the Normal and Complementary Channels with the configuration options that the HAL provides.

The only way I have found to do it is by starting the OC with the normal HAL function "HAL_TIMEx_OCN_Start" and then "restarting it" with the DMA HAL function, like this:

 

 

    // Configure DMA
    dma2_tim_hndl.Instance = DMA2_Stream1;
    dma2_tim_hndl.Init.Channel = DMA_CHANNEL_6;
    dma2_tim_hndl.Init.Direction = DMA_MEMORY_TO_PERIPH;
    dma2_tim_hndl.Init.PeriphInc = DMA_PINC_DISABLE;
    dma2_tim_hndl.Init.MemInc = DMA_MINC_ENABLE;
    dma2_tim_hndl.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
    dma2_tim_hndl.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
    dma2_tim_hndl.Init.Mode = DMA_CIRCULAR;
    dma2_tim_hndl.Init.Priority = DMA_PRIORITY_LOW;

    hal_status = HAL_DMA_Init(&dma2_tim_hndl);
    STM_RETURN_ON_FALSE(hal_status == HAL_OK, hal_status, TAG, "DMA init failed");

    // Link DMA to TIM handle
    __HAL_LINKDMA(&tim_hndl, hdma[1], dma2_tim_hndl);

    // Configure TIM1
    tim_hndl.Instance = TIM1;
    tim_hndl.Init.Prescaler = 240;
    tim_hndl.Init.CounterMode = TIM_COUNTERMODE_UP;
    tim_hndl.Init.Period = 317;
    tim_hndl.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
    tim_hndl.Init.RepetitionCounter = 0;
    tim_hndl.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE;

    hal_status = HAL_TIM_OC_Init(&tim_hndl);
    STM_RETURN_ON_FALSE(hal_status == HAL_OK, hal_status, TAG, "TIM OC init failed");

    // Configure TIM1 Output Compare Channel 1
    tim_oc_conf.OCMode = TIM_OCMODE_TOGGLE;
    tim_oc_conf.Pulse = 1;
    tim_oc_conf.OCPolarity = TIM_OCPOLARITY_HIGH;
    tim_oc_conf.OCNPolarity = TIM_OCPOLARITY_HIGH;
    tim_oc_conf.OCFastMode = TIM_OCFAST_DISABLE;
    tim_oc_conf.OCIdleState = TIM_OCIDLESTATE_SET;
    tim_oc_conf.OCNIdleState = TIM_OCIDLESTATE_SET;

    // Configure Dead time
    tim_break_conf.OffStateRunMode = TIM_OSSR_ENABLE;
    tim_break_conf.OffStateIDLEMode = TIM_OSSI_DISABLE;
    

    hal_status = HAL_TIM_OC_ConfigChannel(&tim_hndl, &tim_oc_conf, TIM_CHANNEL_1);
    STM_RETURN_ON_FALSE(hal_status == HAL_OK, hal_status, TAG, "TIM OC config failed");

    // Start TIM1 with DMA
     hal_status = HAL_TIMEx_OCN_Start(&tim_hndl, TIM_CHANNEL_1);//(&tim_hndl, TIM_CHANNEL_1, (uint32_t*)&TIM1_OC_VALS, 20);
     STM_RETURN_ON_FALSE(hal_status == HAL_OK, hal_status, TAG, "DMA TIM OCN start failed");
     hal_status = HAL_TIM_OC_Start_DMA(&tim_hndl, TIM_CHANNEL_1, (uint32_t*)&TIM1_OC_VALS, 20);
     STM_RETURN_ON_FALSE(hal_status == HAL_OK, hal_status, TAG, "DMA TIM OC start failed");

 

 

I have seen in some old posts that there was before the option in "TIM_OCInitTypeDef" struct to set the param: "TIM_OutputNState" to TIM_OUTPUTNSTATE_ENABLE, but that option seems to be gone with the new (?) "TIM_OC_InitTypeDef"

 

So am I missing something??? I cant get to make it work without doing some writing directly to the TIM CCER register or using that ugly hack with the HAL

Thanks for your help and time

1 REPLY 1

BTW, yes, I have configured both GPIO to the correct configuration, and yes, I have gotten it to work with the hack of restarting the TIM once via the normal mode and the next time with the DMA function, but I wish to do it by configuring from the beginning or something like that

Here a picture of what I am trying to achieve:

lukilukeskywalker_0-1726249238254.png