2020-07-16 09:58 AM
To control a DC motor driver I need to set one pin permanently high and the other is inverse PWM.
If I want to reverse the motor direction I need to swap these settings.
So I configured both pins as PWM output.
But if I want to set one output pin high the following code is ignored:
HAL_GPIO_WritePin(GPIOA, MOTOR_IN1_Pin, GPIO_PIN_SET);
The pin stays low, maybe because the pin is officially not in GPIO mode?
So I thought ok setting 100% duty has the same effect, but when I measure on the scope you see small glitches to zero volt.
So my question can be solved two ways:
How do I make my PWM output pin accept also WritePin commands?
OR
How can I get rid of the small glitches in my 100% duty cycle?
Solved! Go to Solution.
2020-07-16 11:43 AM
> So I thought ok setting 100% duty has the same effect
It should work without glitches. Lets say TIM1 counts up with 1 kHz frequency (prescaler 7999 at 8 MHz clock) and you want a period of 100ms. So you set up a counter period of 99. With a PWM pulse setting of 0 you get 0% PWM and with a PWM pulse setting of 100 you get 100% PWM.
Anyway, you can toggle the mode of the pin between PWM and GPIO. Using HAL this is a bit of overhead, as GPIO init (for another pin) is
/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(LED_GPIO_Port, LED_Pin, GPIO_PIN_RESET);
/*Configure GPIO pin : LED_Pin */
GPIO_InitStruct.Pin = LED_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(LED_GPIO_Port, &GPIO_InitStruct);
whereas PWM output mode init is (code in HAL_TIM_MspPostInit):
GPIO_InitStruct.Pin = GPIO_PIN_9|GPIO_PIN_10;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
GPIO_InitStruct.Alternate = GPIO_AF2_TIM1;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
the only difference is the .Mode which can be switched easily at the register level (GPIOx->MODER).
If already at register level: Once you have PM mode running, there is a forced output mode for each channel, by setting the OCxM bits in the TIMx_CCMRx register to to 100 rsp. 101. See reference manual.
2020-07-16 11:43 AM
> So I thought ok setting 100% duty has the same effect
It should work without glitches. Lets say TIM1 counts up with 1 kHz frequency (prescaler 7999 at 8 MHz clock) and you want a period of 100ms. So you set up a counter period of 99. With a PWM pulse setting of 0 you get 0% PWM and with a PWM pulse setting of 100 you get 100% PWM.
Anyway, you can toggle the mode of the pin between PWM and GPIO. Using HAL this is a bit of overhead, as GPIO init (for another pin) is
/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(LED_GPIO_Port, LED_Pin, GPIO_PIN_RESET);
/*Configure GPIO pin : LED_Pin */
GPIO_InitStruct.Pin = LED_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(LED_GPIO_Port, &GPIO_InitStruct);
whereas PWM output mode init is (code in HAL_TIM_MspPostInit):
GPIO_InitStruct.Pin = GPIO_PIN_9|GPIO_PIN_10;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
GPIO_InitStruct.Alternate = GPIO_AF2_TIM1;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
the only difference is the .Mode which can be switched easily at the register level (GPIOx->MODER).
If already at register level: Once you have PM mode running, there is a forced output mode for each channel, by setting the OCxM bits in the TIMx_CCMRx register to to 100 rsp. 101. See reference manual.
2024-10-28 07:57 AM - edited 2024-10-28 07:59 AM
For anybody stumbling upon the same behaviour:
The glitching at 100% duty-cycle is probably due to calculating the duty-cycle to be a % of TIMx->ARR. The calculated value probably is just not the real 100%, but something a bit below. So when setting the duy-cycle, just make an extra if-statement that handles those 100% to be the actual value of ARR
if (duty == 100) {
TIMx->CCRx = TIMx->ARR;
}
2024-10-28 10:25 AM
The code above guarantees the glitch. To get full duty, set CCR to ARR + 1.
The problem does not exist in a properly written code. If you want to express duty in percent, set the period to 100 (so set ARR to 99), then load your percent value to CCR - no arithmetics needed. You may regulate the PWM frequency by setting the prescaler in PSC register.