2024-01-07 03:12 AM
Hı everyone, ı was trying to design basic timer project in register level about toggling on related led pin every 1 second. However, the led is on a few seconds after that it is off and never becoming on. When ı do the same project in HAL library, it worked well. By the way, I use APB1 as 84 MHz. Is there anything i missed out ?
/* Includes */
#include "stm32f4xx.h"
#include "stm32f4_discovery.h"
void RCC_Config()
{
RCC->CR |= 0x00030000; // HSEON and HSEONRDY enable
while(!(RCC->CR & 0x00020000)); // HSEON Ready Flag wait
RCC->CR |= 0x00080000; // CSS Enable
RCC->CR |= 0x01000000; // PLL ON
RCC->PLLCFGR |= 0x00400000; // PLL e HSE seçtik
RCC->PLLCFGR |= 0x00000004; // PLL M = 4
RCC->PLLCFGR |= 0x00005A00; // Pll N = 168
RCC->PLLCFGR |= 0x00000000; // PLL p = 2
RCC->CFGR |= 0x00000000; // AHB Prescaler = 1
RCC->CFGR |= 0x00080000; // APB2 Prescaler = 2
RCC->CFGR |= 0x00001400; // APB1 Prescaler = 4
RCC->CIR |= 0x00080000; // HSERDY Flag clear
RCC->CIR |= 0x00800000; // CSS Flag clear
}
void GPIO_Config()
{
RCC->AHB1ENR |= 0x00000008; // GPIOD active
GPIOD -> MODER |= 0x55000000; // 12-13-14-15 output
GPIOD->PUPDR = 0x00000000; // no pull-up, pull-down
}
void TIM_Config()
{
RCC->APB1ENR |= 1 << 0; // TIM2 clock enable
TIM2->CR1 |= 0 << 4; // Counter mode is upcounter (DIR)
TIM2->CR1 |= 0 << 5; // Center aligned mode edge-aligned mode (CMS)
TIM2->CR1 |= 0 << 8; // Set the clock divisixon to 1 (CKD)
//TIM2->CR1 |= 1 << 2; // only under ve overflow generate interrupt
TIM2->SMCR |= 0 << 0; // Internal clock source (SMS)
TIM2->EGR |= 1 << 0; // Tımer Update Generation ( UG: Update generation)
TIM2->DIER |= (1 << 0);
TIM2->PSC |= 41999; // 84000 MHz / (41999+1) = 2000 ( PSC[15:0]: Prescaler value) -> The counter clock frequency CK_CNT is equal to fCK_PSC / (PSC[15:0] + 1)
TIM2->ARR |= 1999; // 2000/2000 = 1 saniye => 1 saniyede bir 2000 (ARR=autoreload değeri) saydirmis oluruz.
//TIM2->CR1 &= ~(1<<0); // Tımer2 Counter Disable for now (CEN:Counter enable)
TIM2->CR1 |= (1<<0); //
}
void EXTI_Config()
{
NVIC_EnableIRQ(TIM2_IRQn);
}
void TIM2_IRQHandler(void)
{
if(TIM2->SR & (1<<0))
{
TIM2->SR &= ~(1<<0);
GPIOD->ODR ^= (1 << 12);
}
}
int main(void)
{
RCC_Config();
GPIO_Config();
TIM_Config();
EXTI_Config();
while (1)
{
}
}
void EVAL_AUDIO_TransferComplete_CallBack(uint32_t pBuffer, uint32_t Size){
/* TODO, implement your code here */
return;
}
uint16_t EVAL_AUDIO_GetSampleCallBack(void){
/* TODO, implement your code here */
return -1;
}
Solved! Go to Solution.
2024-01-07 06:48 AM
An easy way to figure it out is to compare the register values using HAL with the register values you're setting in your own program.
> TIM2->ARR |= 1999;
Don't use bit-wise modification here. If you want to set the value, set the value:
TIM2->ARR = 1999;
The default value for ARR is 0xFFFF, which means your statement has no effect and your timer is updating at 84 MHz / 42000 / 65536 = 0.03 Hz.
Also, using CMSIS defines will make your code a lot more readable and will cut down on typos. For example, instead of "TIM2->CR1 |= (1<<0);", do
TIM2->CR1 |= TIM_CR1_CEN;
2024-01-07 04:12 AM
It is missing enable global interrupts with __enable_irq().
2024-01-07 06:39 AM - edited 2024-01-07 06:51 AM
The errors in your code result from using magic numbers instead of bit names and using operators |=, &= instead of assignments. Without checking if the magic numbers are correct, I can easily see few problems.
1. ARR is set to 65535, so the timer period is > 32 s.
2. You reset the timer interrupt flag incorrectly, using &= instead of =. This works with your simple case but would cause problems if you use some other sources of timer interrupt.
3. PLL is enabled before setting the divisors. It's hard to guess what clock frequency will be used.
2024-01-07 06:48 AM
An easy way to figure it out is to compare the register values using HAL with the register values you're setting in your own program.
> TIM2->ARR |= 1999;
Don't use bit-wise modification here. If you want to set the value, set the value:
TIM2->ARR = 1999;
The default value for ARR is 0xFFFF, which means your statement has no effect and your timer is updating at 84 MHz / 42000 / 65536 = 0.03 Hz.
Also, using CMSIS defines will make your code a lot more readable and will cut down on typos. For example, instead of "TIM2->CR1 |= (1<<0);", do
TIM2->CR1 |= TIM_CR1_CEN;
2024-01-08 01:01 AM
thx the problem was below
TIM2->PSC |= 41999;
TIM2->ARR |= 1999;
these must have been what you explained
TIM2->PSC = 41999;
TIM2->ARR = 1999;