The following code works fine generating TIM_CH1 PWM on pin PA8, at ~720 Hz.
I want to learn how to generate an overflow interrupt event and call a handler function.
In this case the handler calls a LED toggle on PC13.
But of course, something goes wrong. I think the problem is not the TIM1 initialization because the timer works fine.
I added the necessary code to make the overflow interrupt work. The interrupt function is never called.
I ask myself if Arduino is having priority with its own interrupts that it uses for e.g. delay() and delayMicroseconds() functions, and if the interrupts() function works for STM32 micros under this environment.
If the following functions are commented, the timer returns to normal, if not, the main loop crashes or never executes. No PWM and no interrupts.
Code: Select all
NVIC_SetPriority(TIM1_IRQn, 1); // Set the interrupt priority
NVIC_EnableIRQ(TIM1_IRQn); // Enable the interrupt

Any ideas to make this program work wil be very much appreciated. Here is my code.
Thank you - Roberto
Code: Select all
/* TIM1 CH1 - 720 Hz PWM on PA8 */
#define PERIOD 50000
#define DUTY 5000
#define PRESCALER 1
#define DIV 720
#define LED (1 << 13)
static int d;
void TIM1_IRQHandler(void)
{
if (TIM1->SR & TIM_SR_UIF) // Check if overflow event occurred
{
// Handle the interrupt here
ToggleLED();
// Clear the interrupt flag
TIM1->SR &= ~TIM_SR_UIF;
}
}
void ToggleLED(void)
{
static unsigned int div = DIV;
if (--div == 0)
{
GPIOC->ODR ^= LED; // Toggle the pin state
div = DIV;
}
}
void setup()
{
// Enable peripheral clocks
RCC->APB2ENR |= RCC_APB2ENR_IOPAEN;
RCC->APB2ENR |= RCC_APB2ENR_IOPCEN;
RCC->APB2ENR |= RCC_APB2ENR_TIM1EN;
// Set PA8 as alternate function output push-pull
GPIOA->CRH &= ~(GPIO_CRH_CNF8 | GPIO_CRH_MODE8);
GPIOA->CRH |= GPIO_CRH_CNF8_1; /* 10: Alternate function output Push-pull */
GPIOA->CRH |= GPIO_CRH_MODE8_1; /* 10: Output mode, max speed 2 MHz. */
// Configure LED as general-purpose output, push-pull mode, maximum speed
GPIOC->CRH &= ~(0xF << 20); // Clear configuration bits
GPIOC->CRH |= (0x3 << 20); // Set mode bits to general-purpose output
// MOE: Main output enable
TIM1->BDTR |= TIM_BDTR_MOE;
/****** Configure TIM1 ********/
// Set the prescaler value to achieve the desired PWM frequency
TIM1->PSC = PRESCALER; // Divide the 72 MHz clock by 8
// Set the duty cycle of TIM1 channel 1
TIM1->CCR1 = DUTY;
TIM1->CR1 &= ~TIM_CR1_CEN; // Disable TIM1
/* Reinitialize all registers */
TIM1->EGR = TIM_EGR_UG;
// Set the auto-reload value to determine the PWM period
TIM1->ARR = PERIOD; // Set the period
// CC1S: Capture/Compare 1 selection
TIM1->CCMR1 &= ~TIM_CCMR1_CC1S;
// OC1M[2:0]: Output Compare 1 mode
TIM1->CCMR1 |= TIM_CCMR1_OC1M_1 | TIM_CCMR1_OC1M_2;
// CC1P: Capture/Compare 1 output polarity
TIM1->CCER &= ~TIM_CCER_CC1P; // Set polarity to active high
// CC1E: Capture/Compare 1 output enable.
TIM1->CCER |= TIM_CCER_CC1E;
// Enable TIM1 update interrupt
TIM1->DIER |= TIM_DIER_UIE;
// Enable the timer
TIM1->CR1 |= TIM_CR1_CEN;
NVIC_SetPriority(TIM1_IRQn, 1); // Set the interrupt priority
NVIC_EnableIRQ(TIM1_IRQn); // Enable the interrupt
interrupts();
}
void loop()
{
for (d = 1; d < PERIOD; ++d)
{
TIM1->CCR1 = d;
delayMicroseconds(300);
}
for( ; d > 0; --d)
{
TIM1->CCR1 = d;
delayMicroseconds(300);
}
}