STM32F407 discovery board. Basic Timer TIM6 and Interrupt to toggle LED without HAL driver
Hi
I am trying to better understand the registers and register manipulation to set up the following scenario:
Toggle LED on PD12 every 1 second via TIM6 and Interrupt Handler.
Below is my code. I enter the interrupt service routine (verified by setting a breakpoint in the ISR) and I toggle the LED (via step by step debugging within the ISR) . However, when I remove the breakpoint and run the code, the LED toggles at a much higher frequency. Could you please double check my code because I believe I have something wrong in my TIM6 setup. Thank you,
#include "stm32f4xx.h"
void funcIntInit();
void funcTimerInit();
void funcGPIOInit();
int main(void)
{
funcIntInit();
funcTimerInit();
funcGPIOInit();
for(;;);
}
void funcIntInit()
{
// Initialize the interrupt
__NVIC_EnableIRQ(TIM6_DAC_IRQn);
EXTI->IMR |= (1<<0);
EXTI->EMR |= (1<<0);
EXTI->FTSR &= ~(1<<0);
EXTI->RTSR |= (1<<0);
// SysCfg not needed for basic timer TIM6???
}
void funcTimerInit()
{
// Peripheral clock
RCC->APB1ENR |= (1<<4); // Enables APB1 bus to use Timer 6
// 2. Init timer
TIM6->CR1 |= (1<<0); // CEN: Enables counter
TIM6->CR1 &= ~(1<<1); // UDIS: Update event enabled
TIM6->CR1 |= (1<<2); // URS: Update request source enabled for overflow/underflow only
TIM6->CR1 &= ~(1<<3); // OPM: One Pulse Mode. Counter continues counting.
TIM6->CR1 &= ~(1<<7); // Auto reload preload enabled
TIM6->DIER |= (1<<0); // UIE: Update interrupt enabled
TIM6->EGR |= (1<<0); // UG: Update generation. Re-initializes the counter and updates registers
//TIM6->CNT = 0x00FA; // Counter goes up to 250 to have 1s timer ???
TIM6->PSC = 0xFA00; // Sets prescaler to 64000. Timer clock is now 16MHz/64000=250Hz
TIM6->ARR = 0x00FA; // Counter goes up to 250 to have 1s timer
}
void funcGPIOInit()
{
// Peripheral clock
RCC->AHB1ENR |= (1<<3); // Enables AHB1 to use GPIOD peripheral
// 2. Init GPIO
GPIOD->MODER |= (1<<24); // Sets GPIOD as Output
GPIOD->MODER &= ~(1<<25); // Sets GPIOD as Output (redundand because bit 25 is already 0 after reset)
GPIOD->OTYPER &= ~(1<<12); // Set PD12 as Push Pull
GPIOD->OSPEEDR &= ~(1<<24); // Sets speed on PD12 to low
GPIOD->OSPEEDR &= ~(1<<25); // Sets speed on PD12 to low
}
void TIM6_DAC_IRQHandler() // Overrides the weak implementation of the IRQ in the startup file
{
// Toggle LED
static uint8_t check = 1;
if(check)
{
GPIOD->ODR |= (1<<12); // Sets PD12
check = 0;
}
else
{
GPIOD->ODR &= ~(1<<12); // Clears PD12
check = 1;
}
__NVIC_ClearPendingIRQ(TIM6_DAC_IRQn);
}