Skip to main content
dominik
Senior
April 25, 2021
Question

Output Compare stay on actual voltage level

  • April 25, 2021
  • 2 replies
  • 965 views

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

This topic has been closed for replies.

2 replies

waclawek.jan
Super User
April 26, 2021

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

dominik
dominikAuthor
Senior
April 26, 2021

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.