2024-04-18 05:16 AM
Hi, I'm using an STM32L053R6Tx chip
I've implemented at TMR2_interrupt hander it gets triggered on ARR overflow and CC1F
I'm using the interrupt to trigger a GPIO output to work like a PWM the
- GPIO is high when CNT is less than CCR1
- GPIO is low when CNT is greater than CCR1
(I couldn't use the PWM hardware pin because its not wired to the correct pin on the circuit board hence i have to do it manually)
the Timer 2 frequency with ARR = 200 is approx. 22khz
The code works as expected i.e. when CCR1 value triggers before the interrupt is completed e.g. for CCR1 values between 1-5 i.e. same PWM size for any value between 1-5. I expect this case. PWM is capped at approx. 2% (due to time it takes to execute the interrupt)
For CCR1 value > 10 up to 200 the GPIO works normally as expected e.g. is
CCR1 = 50 the PWM is 25%
CCR1 = 100 give 50% PWM
CCR1 = 200 give 100% PWM
The problem I have is when I set CCR1 values between 6-8 I get 100% PWM output.
Also note this only happens when I set the CCR1 value inside the interrupt. Alternatively if I set CCR1 = 6 only once and outside the interrupt then the PWM works fine.
Is there something that happens to the interrupts when you set CCR1 value inside the interrupt?
#NOTE Please consider answers carefully since interrupt code is more intricate that it seems.
Source code below
void TIM2_IRQHandler(void) {
if (READ_BIT(TIM2->SR, TIM_SR_UIF)) {
WRITE_REG(TIM2->CCR1, 3); //TODO: updating the register here to a value around 6 causes PWM to be full on
CLEAR_BIT(TIM2->SR, TIM_SR_UIF);
if (READ_REG(TIM2->CCR1) != 0) { //don't blip when zero
LED_SET_RED();
}
}
if (READ_BIT(TIM2->SR, TIM_SR_CC1IF)) {
LED_CLEAR_RED();
CLEAR_BIT(TIM2->SR, TIM_SR_CC1IF);
}
}
/**
* TIM2 CLK = 32MhZ
* TIM2 PSC = 8 = 4Mhz
* TIM2 ARR = 200 = 20khz
*/
void app_pwm_init() {
HAL_NVIC_SetPriority(TIM2_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(TIM2_IRQn);
__HAL_TIM_ENABLE_IT(&htim2, TIM_IT_UPDATE);
__HAL_TIM_ENABLE_IT(&htim2, TIM_IT_CC1);
HAL_TIM_Base_Start(&htim2);
WRITE_REG(TIM2->CCR1, 3);
}
static void MX_TIM2_Init(void)
{
/* USER CODE BEGIN TIM2_Init 0 */
/* USER CODE END TIM2_Init 0 */
TIM_ClockConfigTypeDef sClockSourceConfig = {0};
TIM_MasterConfigTypeDef sMasterConfig = {0};
TIM_OC_InitTypeDef sConfigOC = {0};
/* USER CODE BEGIN TIM2_Init 1 */
/* USER CODE END TIM2_Init 1 */
htim2.Instance = TIM2;
htim2.Init.Prescaler = 8;
htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
htim2.Init.Period = 200;
htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
htim2.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE;
if (HAL_TIM_Base_Init(&htim2) != HAL_OK)
{
Error_Handler();
}
sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
if (HAL_TIM_ConfigClockSource(&htim2, &sClockSourceConfig) != HAL_OK)
{
Error_Handler();
}
if (HAL_TIM_PWM_Init(&htim2) != 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_PWM1;
sConfigOC.Pulse = 0;
sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
if (HAL_TIM_PWM_ConfigChannel(&htim2, &sConfigOC, TIM_CHANNEL_1) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN TIM2_Init 2 */
/* USER CODE END TIM2_Init 2 */
}
Solved! Go to Solution.
2024-04-18 08:25 AM
> CLEAR_BIT(TIM2->SR, TIM_SR_UIF);
Don't use RMW to clear TIMx_SR bits.
Btw. you should also switch on compiler optimizations when working on timing sensitive code.
JW
2024-04-18 08:25 AM
> CLEAR_BIT(TIM2->SR, TIM_SR_UIF);
Don't use RMW to clear TIMx_SR bits.
Btw. you should also switch on compiler optimizations when working on timing sensitive code.
JW