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


