cancel
Showing results for 
Search instead for 
Did you mean: 

Output Compare stay on actual voltage level

dominik
Senior

I need an output compare trigger output with toggle function, and the start/stop should be on the correct frequency. Start is ok now, Stop I like to stay on the actual volatge level (high or low)

The problem now I face is when I turn off the timer with HAL_TIM_OC_Stop_IT(&htim20, TIM_CHANNEL_1);

then the output Pin goes to sConfigOC.OCIdleState = TIM_OCIDLESTATE_RESET;

and when in this moment the Pin was high, it goes to the low state

it should stay on the actual level on Stop.

I tried to reconfig the Timer in the IRQ but this is not working. Is this possible to do with the OutputCompare?

in the Timer IRQ:

void setStepper_Timer(const uint16_t TimerCounter) {
 
    __HAL_TIM_SetAutoreload(&htim20, TimerCounter);
    __HAL_TIM_SetCompare(&htim20, TIM_CHANNEL_1, TimerCounter);
 
    //check if the timer is stopped
    if (TIM_CHANNEL_STATE_GET(&htim20, TIM_CHANNEL_1) == HAL_TIM_CHANNEL_STATE_READY) {
        __HAL_TIM_SetCounter(&htim20, 0);
 
        /* Generate an update event to reload the Prescaler
        and the repetition counter (only for advanced timer) value immediately */
        TIM20->EGR = TIM_EGR_UG;
 
        //start the timer
        HAL_TIM_OC_Start_IT(&htim20, TIM_CHANNEL_1);
    }
}
 

in the Timer IRQ

void stopStepper_Timer(const bool bStop, const bool bSetState) {
    static bool bStopPending = false;
    static bool bPinLevel = false;
 
    TIM_OC_InitTypeDef sConfigOC = {0};
 
    //invert the PinLevelState
    bPinLevel = !bPinLevel;
 
    if (bSetState) {
        bStopPending = bStop;
    } else {
        if (bStopPending) {
/*
            //set the idle state according to the actual Output State on the PIN
            if (bPinLevel) {
                sConfigOC.OCIdleState = TIM_OCIDLESTATE_SET;
            } else {
                sConfigOC.OCIdleState = TIM_OCIDLESTATE_RESET;
            }
            sConfigOC.OCMode = TIM_OCMODE_TOGGLE;
            sConfigOC.Pulse = 0;
            sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
            sConfigOC.OCNPolarity = TIM_OCNPOLARITY_HIGH;
            sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
            //sConfigOC.OCIdleState = TIM_OCIDLESTATE_RESET;
            sConfigOC.OCNIdleState = TIM_OCNIDLESTATE_RESET;
            if (HAL_TIM_OC_ConfigChannel(&htim20, &sConfigOC, TIM_CHANNEL_1) != HAL_OK) {
                Error_Handler();
            }
*/
            HAL_TIM_OC_Stop_IT(&htim20, TIM_CHANNEL_1);
            bStopPending = false;
        }
    }
}
/* TIM20 init function */
void MX_TIM20_Init(void) {
    TIM_ClockConfigTypeDef sClockSourceConfig = {0};
    TIM_MasterConfigTypeDef sMasterConfig = {0};
    TIM_OC_InitTypeDef sConfigOC = {0};
    TIM_BreakDeadTimeConfigTypeDef sBreakDeadTimeConfig = {0};
 
    htim20.Instance = TIM20;
    htim20.Init.Prescaler = 149;
    htim20.Init.CounterMode = TIM_COUNTERMODE_UP;
    htim20.Init.Period = 50000;
    htim20.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
    htim20.Init.RepetitionCounter = 0;
    htim20.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE;
    if (HAL_TIM_Base_Init(&htim20) != HAL_OK) {
        Error_Handler();
    }
    sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
    if (HAL_TIM_ConfigClockSource(&htim20, &sClockSourceConfig) != HAL_OK) {
        Error_Handler();
    }
    if (HAL_TIM_OC_Init(&htim20) != HAL_OK) {
        Error_Handler();
    }
    sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
    sMasterConfig.MasterOutputTrigger2 = TIM_TRGO2_RESET;
    sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
    if (HAL_TIMEx_MasterConfigSynchronization(&htim20, &sMasterConfig) != HAL_OK) {
        Error_Handler();
    }
    sConfigOC.OCMode = TIM_OCMODE_TOGGLE;
    sConfigOC.Pulse = 0;
    sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
    sConfigOC.OCNPolarity = TIM_OCNPOLARITY_HIGH;
    sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
    sConfigOC.OCIdleState = TIM_OCIDLESTATE_RESET;
    sConfigOC.OCNIdleState = TIM_OCNIDLESTATE_RESET;
    if (HAL_TIM_OC_ConfigChannel(&htim20, &sConfigOC, TIM_CHANNEL_1) != HAL_OK) {
        Error_Handler();
    }
    __HAL_TIM_ENABLE_OCxPRELOAD(&htim20, TIM_CHANNEL_1);
    sBreakDeadTimeConfig.OffStateRunMode = TIM_OSSR_DISABLE;
    sBreakDeadTimeConfig.OffStateIDLEMode = TIM_OSSI_DISABLE;
    sBreakDeadTimeConfig.LockLevel = TIM_LOCKLEVEL_OFF;
    sBreakDeadTimeConfig.DeadTime = 0;
    sBreakDeadTimeConfig.BreakState = TIM_BREAK_DISABLE;
    sBreakDeadTimeConfig.BreakPolarity = TIM_BREAKPOLARITY_HIGH;
    sBreakDeadTimeConfig.BreakFilter = 0;
    sBreakDeadTimeConfig.BreakAFMode = TIM_BREAK_AFMODE_INPUT;
    sBreakDeadTimeConfig.Break2State = TIM_BREAK2_DISABLE;
    sBreakDeadTimeConfig.Break2Polarity = TIM_BREAK2POLARITY_HIGH;
    sBreakDeadTimeConfig.Break2Filter = 0;
    sBreakDeadTimeConfig.Break2AFMode = TIM_BREAK_AFMODE_INPUT;
    sBreakDeadTimeConfig.AutomaticOutput = TIM_AUTOMATICOUTPUT_DISABLE;
    if (HAL_TIMEx_ConfigBreakDeadTime(&htim20, &sBreakDeadTimeConfig) != HAL_OK) {
        Error_Handler();
    }
    HAL_TIM_MspPostInit(&htim20);
 
}

2 REPLIES 2

I don't understand Cube, but read description of TIMx_CCMR.OCxM but in TIM chapter of RM, you likely want to use the Force High mode.

JW

No, I like to use the toggle on Match Mode, but remain the actual value when I set the timer off with HAL_TIM_OC_Stop_IT.

I saw that after the HAL_TIM_OC_Stop_IT the Output is on Tri-State and not active low. Which command stops the timer but doesn't disable the Output LOW or HIGH Level? HAL_TIM_Base_Stop is not working.