pwm with one shot timer
Hi
I’m sucessfully running a timer in STM32F103xx as PWM generator on 4 CHs to drive 4 servos.
This generates pulses of variable length between 1ms and 2ms.
My Problem now is the update of the pulse length. I get a HAL_TIM_PeriodElapsedCallback and HAL_TIM_PWM_PulseFinishedCallback for each channel. There is no notification to do the writes to TIM2->CCRx, setting the pulse lenght, just in time. So there is a latency which I try to avoid.
I would like to start the timer with interrupt generation in one shot mode, then do my calculations after HAL_TIM_PeriodElapsedCallback und then start the timer again.
How to do this with CubeMX?
Is “output compare CHx” mode “inactive on match” “one pulse mode” the right way?
How to restart/trigger the thing?
timer “output compare CHx” mode “inactive on match” “one pulse mode” in CubeMX gives:
void MX_TIM2_Init(void) { TIM_MasterConfigTypeDef sMasterConfig; TIM_OC_InitTypeDef sConfigOC; htim2.Instance = TIM2; htim2.Init.Prescaler = 35; htim2.Init.CounterMode = TIM_COUNTERMODE_UP; htim2.Init.Period = 9999; htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; if (HAL_TIM_OC_Init(&htim2) != HAL_OK) { Error_Handler(); } if (HAL_TIM_OnePulse_Init(&htim2, TIM_OPMODE_SINGLE) != HAL_OK) { Error_Handler(); } sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET; sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE; if (HAL_TIMEx_MasterConfigSynchronization(&htim2, &sMasterConfig) != HAL_OK) { Error_Handler(); } sConfigOC.OCMode = TIM_OCMODE_INACTIVE; sConfigOC.Pulse = 0; sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH; sConfigOC.OCFastMode = TIM_OCFAST_DISABLE; if (HAL_TIM_OC_ConfigChannel(&htim2, &sConfigOC, TIM_CHANNEL_1) != HAL_OK) { Error_Handler(); } if (HAL_TIM_OC_ConfigChannel(&htim2, &sConfigOC, TIM_CHANNEL_2) != HAL_OK) { Error_Handler(); } if (HAL_TIM_OC_ConfigChannel(&htim2, &sConfigOC, TIM_CHANNEL_3) != HAL_OK) { Error_Handler(); } if (HAL_TIM_OC_ConfigChannel(&htim2, &sConfigOC, TIM_CHANNEL_4) != HAL_OK) { Error_Handler(); } HAL_TIM_MspPostInit(&htim2); }
When used like this there are interrupts but no pulses:
void main(void) { ... HAL_TIM_OC_Start_IT(&htim2, TIM_CHANNEL_1); HAL_TIM_OC_Start_IT(&htim2, TIM_CHANNEL_2); HAL_TIM_OC_Start_IT(&htim2, TIM_CHANNEL_3); HAL_TIM_OC_Start_IT(&htim2, TIM_CHANNEL_4); __HAL_TIM_ENABLE_IT(&htim2, TIM_IT_UPDATE); ... while (1) { if (PeriodElapsed == 1) { .... TIM2->CCR1 = servos[0]; TIM2->CCR2 = servos[1]; TIM2->CCR3 = servos[2]; TIM2->CCR4 = servos[3]; HAL_TIM_OC_Start_IT(&htim2, TIM_CHANNEL_1); HAL_TIM_OC_Start_IT(&htim2, TIM_CHANNEL_2); HAL_TIM_OC_Start_IT(&htim2, TIM_CHANNEL_3); HAL_TIM_OC_Start_IT(&htim2, TIM_CHANNEL_4); } } }
Sorry for the noise, since this is not an AC6 question.
Dieter