2021-06-23 07:25 AM
I'm working on a project with an STM32F3 MCU and I've been running some test-code on register level, but I have had trouble with the timer and making pin PE8 blink. The result from this code is that it will turn the LED on but it won't toggle the pin so the LED isn't blinking. The following is the code that I'm running on keil uvision:
#include "stm32f303xc.h"
#include "system_stm32f3xx.h"
void CLOCK_config(void);
void GPIO_config(void);
void TIM1_init(void);
void CLOCK_config(void){
//ENABLE HSI CLOCK
RCC->CR |= RCC_CR_HSION;
while(!(RCC->CR & RCC_CR_HSIRDY));
//ENABLE TIM1
RCC->APB2ENR |= RCC_APB2ENR_TIM1EN;
//CONFIGURE CLOCK FOR PORTE
RCC->AHBENR |= RCC_AHBENR_GPIOEEN;
}
void GPIO_config(void){
//SET GPIOE8 AS OUTPUT MODE
GPIOE->MODER |= (1<<0x10U);
//SET GPIOE8 AS MEDIUM SPEED
GPIOE->OSPEEDR |= (1<<0x10U);
}
void TIM1_init(void){
//SET PRESCALER
TIM1->PSC |= 65000;
//SET RELOAD COUNTER VALUE
TIM1->ARR |= 100;
//ENABLE TIMER
TIM1->CR1 |= TIM_CR1_CEN;
}
int main(){
CLOCK_config();
GPIO_config();
TIM1_init();
while(1){
if(TIM1->SR & TIM_SR_UIF){
TIM1->SR &= ~TIM_SR_UIF;
GPIOE->BSRR ^= (1<<0x8U);
}
}
}
Is there something that I'm missing, because I thought that I had configured the peripherals correctly, although I'm a bit unsure about how the system clock should be configured? I wanted to keep it simple so I'm hoping for a solution that doesn't involve interrupts or changing the timer to the generic or basic timers.
2021-06-23 11:18 AM
> TIM1->SR &= ~TIM_SR_UIF;
If you want to only clear UIF, only write that bit as zero.
> GPIOE->BSRR ^= (1<<0x8U);
BSRR is write only. If you want to toggle a bit, use ODR, or use BSRR correctly (lower 16 bits to set, upper 16 bits to reset) to do so atomicly.
TIM1->SR = ~TIM_SR_UIF;
GPIOE->ODR ^= (1<<0x8U);
2021-06-23 01:09 PM
You should generally avoid using RMW operations (read-modify-write, i.e. |= &= ^= in C) except where strictly necessary.
The issue with clearing TIMx_SR.UIF by RMW is in this case just bad practice, not the one that causes the problems - but XORing BSRR is what causes malfunction, as TDK said above.
There's one more such "fatal" issue there - TIM1->ARR |= 100; as TIMx_ARR is initialized to 0xFFFF leaves ARR to be 0xFFFF, which is not what you want.
Also note, that while TIMx_PSC is by default zero so |= while not needed (and a bad practice too) will change it to the expected value, it will get "active" only after the next Update event (counter "rollover"), as prescaler is unconditionally preloaded. The net result is, that the first timer will be significantly shorter. Not something you'll particularly notice with a blinking LED, but you should know about it too.
JW
2021-06-23 11:43 PM
Thank you for the reply, the LED is still not blinking but I think I'm getting closer to an answer with this
2021-06-23 11:45 PM
Thank you for the reply, I appreciate it. I will try to initialize more accurately.