2018-04-25 04:01 AM
Hi all,
This is a question regarding STM32F0 TIM3.
I have written this code in keil compiler
/***** main.c*****/
&sharpinclude<stm32f0xx.h>
&sharpinclude<stm32f030x8.h>void GPIO_Init(void); void TIM3_Init(void);int main()
{ GPIO_Init(); // Intializing PA5 TIM3_Init(); while(1) {}
}void GPIO_Init()
{ // Enable clock for GPIOA RCC->AHBENR |= (1<<17); //Configuration of PA5 GPIOA->MODER |= (1<<10); // PA5 as general purpose output mode GPIOA->OTYPER &= ~(1<<5); // PA5 as output push pull GPIOA->OSPEEDR |= ((1<<10)|(1<<11)); // PA5 at high speed GPIOA->PUPDR &= ~((1<<10)|(1<<11)); // PA5 as no pull-up, pull-down GPIOA->ODR = 0; // PA5 as Output Low}void TIM3_Init()
{ RCC->APB1ENR |= (1<<1); // Enable clock for TIM3 TIM3->PSC = 999; // Int clk divided by 1000(999+1) TIM3->ARR = 7999; // Counts from 0 to 7999 TIM3->DIER = 1; // Update interrupt enable __NVIC_SetPriority(TIM3_IRQn, 0); // Set TIM3 interrupt vector priority to 0 __NVIC_EnableIRQ(TIM3_IRQn); // Enable TIM3 interrupt vector TIM3->CR1 = 1; // Enable TIM3 counter }void ISR()
{ TIM3->SR = 0; GPIOA->ODR ^= (1<<5); // Toggle PA5 Output}/**** it.c*****/
void ISR(void);
void TIM3_IRQHandler(void){ ISR();}Here system clock freq and timer clock freq is 8Mhz(internal oscillator).
when I run this code I found that my led on PA5 toggles per second that should be as per code.
But there is an problem in output that when microcontroller is done reset by a reset button the PA5 Is immediately high and then toggles @ per second i.e. the tim3 generate a update interrupt when it is enabled. I want that first interrupt should come after timer completion means 1 sec. so that when I reset the microcontroller output can be at low and after 1 sec it toggles( goes high) and so on.
'My question is why microcontroller is making High to the UIF bit TIM3->SR reg. when TIM3 counting is enabled. I think it should be after timer completion'.
Waclawek.Jan
‌ELMHIRI.Syrine
‌nullSolved! Go to Solution.
2018-04-29 08:18 AM
No, the counter does not need to be enabled. The problem is in timing between setting the Update event through EGR, and clearing the status flag.
https://community.st.com/0D50X00009XkaBtSAJ
JW
2018-04-25 04:19 PM
The value you write into the prescaler is not active immediately, only after the first period, as the register you are writing into is only a 'shadow' which gets copied into the active prescaler only upon Update (i.e. the first overflow).
The trick is in 'forcing' and update by writing one into TIMx_EGR.UG after you have written the TIMx_PSC value, but that also sets the update flag and would immediately trigger and interrupt; so you need to do this and then also clearing the bits in the TIMx_SR, before you enable the interrupts.
JW
2018-04-26 11:20 PM
,
,
I have updated the code as you suggested , kindly see the highlighted portion in the below code
/***** main.c*****/
♯ include<,stm32f0xx.h>,
,
♯ include<,stm32f030x8.h>,,
void GPIO_Init(void), ,,
void TIM3_Init(void),int main()
,
{,
,GPIO_Init(), , , , , , , , , // Intializing PA5,
,TIM3_Init(), ,,
,while(1),
,{,} ,
,
}void GPIO_Init()
,
{ ,,
,// Enable clock for GPIOA,
,RCC->,AHBENR |= (1<,<,17),,
,,
,//Configuration of PA5,
,GPIOA->,MODER |= (1<,<,10), , , , , , , , , , , , , // PA5 as general purpose output mode,
,GPIOA->,OTYPER &,= ~(1<,<,5), , , , , , , , , , , , // PA5 as output push pull,
,GPIOA->,OSPEEDR |= ((1<,<,10)|(1<,<,11)), // PA5 at high speed,
,GPIOA->,PUPDR &,= ~((1<,<,10)|(1<,<,11)), , // PA5 as no pull-up, pull-down,
,GPIOA->,ODR = 0, , , , , , , , , , , , // PA5 as Output Low,
}void TIM3_Init()
,
{,
,RCC->,APB1ENR |= (1<,<,1), , , , , , , , // Enable clock for TIM3,
,TIM3->,PSC = 999, , , , , , , , , , , // Int clk divided by 1000(999+1)TIM3->,EGR = 1, , , , , , , , , , , , , , // Forcing to generate a update
TIM3->,SR = 0, , , , , , , , , , , , , , , , // Clearing the UIF bit
,
,TIM3->,ARR = 7999, , , , , , , , , , , // Counts from 0 to 7999,
,TIM3->,DIER = 1, , , , , , , , , , , , // Update interrupt enable,
,__NVIC_SetPriority(TIM3_IRQn, 0), , , // Set TIM3 interrupt vector priority to 0,
,__NVIC_EnableIRQ(TIM3_IRQn), , , , , // Enable TIM3 interrupt vector,
,TIM3->,CR1 = 1, , , , , , , , , , , , // Enable TIM3 counter,
,,
}void ISR()
,
{,
, , ,TIM3->,SR = 0,,
, , ,GPIOA->,ODR ^= (1<,<,5), , , , , , ,// Toggle PA5 Output,
},
,
,
/**** it.c*****/
void ISR(void),
,
void TIM3_IRQHandler(void),
{,
,ISR(),,
}/*******************************code end here*******************************/
But it again generate a interrupt as timer counter enabled i.e. without any delay led toggles when reset button is pressed.
but if I ,change the TIM3_Init function as
void TIM3_Init()
,
{,
,RCC->,APB1ENR |= (1<,<,1), , , , , , , , // Enable clock for TIM3,
,TIM3->,PSC = 999, , , , , , , , , , , // Int clk divided by 1000(999+1)TIM3->,CR1 = 1, , , , , , , , , , , , , , // Enable Counter
TIM3->,EGR = 1, , , , , , , , , , , , , , // Forcing to generate a update
TIM3->,SR = 0, , , , , , , , , , , , , , , , // Clearing the UIF bit
TIM3->,CR1 = 0, , , , , , , , , , , , , ,// Disable the counter
TIM3->,CNT = 0, , , , , , , , , , , , , // Put counter value to 0 so that it can again start from 0
,
,TIM3->,ARR = 7999, , , , , , , , , , , // Counts from 0 to 7999,
,TIM3->,DIER = 1, , , , , , , , , , , , // Update interrupt enable,
,__NVIC_SetPriority(TIM3_IRQn, 0), , , // Set TIM3 interrupt vector priority to 0,
,__NVIC_EnableIRQ(TIM3_IRQn), , , , , // Enable TIM3 interrupt vector,
,TIM3->,CR1 = 1, , , , , , , , , , , , // Enable TIM3 counter again,
,,
},
In simple words before generating the Forced update by setting the TIM3->,EGR.UG bit first I am enabling the counter and then generate a ,forced update ,and clear the UIF bit in TIM3_SR reg. then
Disable the counter for a moment till the other other settings are done (ARR, UIE, Interrupt priority, tim3 vector enabled) and then again the counter enabled, So doing this, the code is working ok, means if I press the reset button after 1 sec led toggles not immediately.
Am I doing ,Right?
2018-04-28 02:47 AM
This is a mystery for me. The first variant should work well.
Can you please try to put after setting PSC some irrelevant code which would delay setting of EGR, for example
TIM3->PSC = 999; // Int clk divided by 1000(999+1)
TIM3->CCR1 = 0; // not needed but makes some delay
TIM3->EGR = 1; // Forcing to generate a update
Thanks
JW
2018-04-28 03:22 AM
yes, tried this but unfortunately it is not working.
void TIM3_Init()
{
RCC->APB1ENR |= (1<<1); // Enable clock for TIM3 TIM3->PSC = 999; // Int clk divided by 1000(999+1)TIM3->CCR1=0; // some delay
TIM3->EGR = 1; // Forcing to generate a update
TIM3->SR = 0; // Clearing the UIF bit
TIM3->ARR = 7999; // Counts from 0 to 7999 TIM3->DIER = 1; // Update interrupt enable __NVIC_SetPriority(TIM3_IRQn, 0); // Set TIM3 interrupt vector priority to 0 __NVIC_EnableIRQ(TIM3_IRQn); // Enable TIM3 interrupt vector TIM3->CR1 = 1; // Enable TIM3 counter }even i wrote TIM3->CCR1 = 0; continue 10 times to give more delay but its not having any effect.
I have seen in debugging that it generate the update i.e. sets the UIF. it means this Update event does not update the PSC. This update also generates if we don't write any delay statement after writing to PSC.
What i have learned here that to get the PSC updated on update event , counter should be enabled i.e. TIM3->CR1 = 1;
Thanks
2018-04-28 09:52 AM
'
when microcontroller is done reset by a reset button the PA5 Is immediately high
... i.e. the tim3 generate a update interrupt when it is enabled.'
the notion that TIMER3 caused PA5 high is not established. You may want to go through the datasheet and see what the reset state of the pin is. and if there are external parts that are pulling the pin high.
if i were you, i would try to be really sure that PA5 goes immediately high after a reset, and then try to pin down that problem. otherwise, you are simply chasing ghosts.
2018-04-29 08:18 AM
No, the counter does not need to be enabled. The problem is in timing between setting the Update event through EGR, and clearing the status flag.
https://community.st.com/0D50X00009XkaBtSAJ
JW
2018-05-02 05:03 AM
Sorry for late reply actually I was on holiday.
Thanks for your suggestion, I have tried code by putting some delay between TIM3->EGR = 1; and TIM3->SR = 0;
see this
void TIM3_Init()
{
RCC->APB1ENR |= (1<<1); // Enable clock for TIM3 TIM3->PSC = 999; // Int clk divided by 1000(999+1)TIM3->EGR = 1; // Forcing to generate a update
TIM3->CCR1=0; // some delay
_NOP; /
_NOP; /
_NOP; /
_NOP; /
TIM3->SR = 0; // Clearing the UIF bit
TIM3->ARR = 7999; // Counts from 0 to 7999 TIM3->DIER = 1; // Update interrupt enable __NVIC_SetPriority(TIM3_IRQn, 0); // Set TIM3 interrupt vector priority to 0 __NVIC_EnableIRQ(TIM3_IRQn); // Enable TIM3 interrupt vector TIM3->CR1 = 1; // Enable TIM3 counter }and it works.
Thanks