2012-09-04 08:14 AM
I need to generate a 20 ms interrupt into my firmware. HSE is 16 Mhz with STM8S208.
I put this initialization code into my firmware to accomplish that through the use of TIM3: #define PRESC TIM3_PRESCALER_32 uint16_t counter = 10000;//counter = counter / 4 * 3; //correction to run closer to a 20 ms period
TIM3_UpdateRequestConfig(TIM3_UPDATESOURCE_GLOBAL);
TIM3_TimeBaseInit(TIM3_PRESCALER_32, counter);
TIM3_UpdateDisableConfig(DISABLE);
TIM3_PrescalerConfig (PRESCALER_32, TIM3_PSCRELOADMODE_UPDATE);
TIM3_ARRPreloadConfig(ENABLE);
TIM3_ITConfig(TIM3_IT_UPDATE, ENABLE);
To achieve the desired 20 ms period I initialized the counter to 10000, so that (16 Mhz / 32 presc = 500 Khz) / 10000 = 50 Hz. Unfortunately the actual frequency is 75% of the expected one, so I need to uncomment the counter correction statement. Does someone why does this happen? Regards. Giorgio
2012-09-04 11:46 PM
Hmm, don't see anything wrong with the code.
But to have period 10000 I would use a counter value of 9999. Not that this would make a big difference here. Also, do you clear the timer's interrupt flag on entering your interrupt routine?2012-09-06 02:41 AM
Yes, 10000 to 999 doesn't make a big difference. To achieve the required timing I must set counter to 755.
Of course, I cleared the TIM3_IT_UPDATE into the handler: #ifdef _COSMIC_ @far @interrupt void TIM3_UPD_OVF_BRK_IRQHandler(void) #else /* _RAISONANCE_ */ void TIM3_UPD_OVF_BRK_IRQHandler(void) interrupt 15 #endif /* _COSMIC_ */ { TIM3_ClearITPendingBit(TIM3_IT_UPDATE); }2012-09-07 06:15 AM
Any ideas why this happens?
Shoud I consider it an harware bug? Regards2012-09-07 06:59 AM
I think a hardware bug in the timers is unlikely.
Another thing that comes to mind, do you generate an event source update after configuring the timer? Otherwise it is not guaranteed that all values are correctly loaded. with TIM3_GenerateEvent(TIM3_EVENTSOURCE_UPDATE)2012-09-07 07:30 AM
2012-09-10 04:05 AM
No changes even adding TIM3_GenerateEvent(TIM3_EVENTSOURCE_UPDATE) when timer is configured. Checked also the assembly produced by Raisonance compiler, seems to be ok (LDW issue mentioned on the reference):
; FUNCTION ?TIM3_TimeBaseInit (BEGIN) ; Register-parameter TIM3_Prescaler (A) is relocated (AUTO) ; Register YW is assigned to parameter TIM3_Period ; SOURCE LINE # 78 0000 51 EXGW X,Y ; SOURCE LINE # 82 0001 C7532A LD 0532AH,A ; SOURCE LINE # 84 0004 93 LDW X,Y 0005 9E LD A,XH 0006 C7532B LD 0532BH,A ; SOURCE LINE # 85 0009 909F LD A,YL 000B C7532C LD 0532CH,A ; SOURCE LINE # 86 000E 81 RET2012-09-10 10:46 AM
I tried your code with COSMIC and it worked first start. On a scope I get a nice 25 Hz (because of the WriteReverse)
int main(void) {
u16 counter = 9999; /* Switch to 16Mhz Crystal Osc clock */ CLK_ClockSwitchConfig(CLK_SWITCHMODE_AUTO, CLK_SOURCE_HSE, DISABLE, DISABLE); TIM3_DeInit(); //counter = counter / 4 * 3; //correction to run closer to a 20 ms period TIM3_UpdateRequestConfig(TIM3_UPDATESOURCE_GLOBAL); TIM3_TimeBaseInit(TIM3_PRESCALER_32, counter); TIM3_UpdateDisableConfig(DISABLE); TIM3_ARRPreloadConfig(ENABLE); TIM3_ITConfig(TIM3_IT_UPDATE, ENABLE); TIM3_GenerateEvent(TIM3_EVENTSOURCE_UPDATE); // Enable TIM3. TIM3_Cmd(ENABLE); GPIO_DeInit(GPIOD); GPIO_Init(GPIOD, GPIO_PIN_0, GPIO_MODE_OUT_PP_LOW_SLOW); // Enable interrupts (no, really). enableInterrupts(); // Infinite loop. while(1){ } } //--------------------------------------------- @far @interrupt void Timer3_Interrupt_Handler(void) { GPIO_WriteReverse(GPIOD, GPIO_PIN_0); // Clear the interrupt pending bit TIM3_ClearITPendingBit(TIM3_IT_UPDATE); }