View previous topic :: View next topic |
Author |
Message |
aaronik19
Joined: 25 Apr 2011 Posts: 297
|
If statement in isr |
Posted: Tue Dec 24, 2019 4:46 pm |
|
|
Dear all,
I made a small code that every 1 second an ISR is executed and in this ISR there is an if...then...else statement. But i am noticing that after about 12 minutes, the isr is not executing every 1 second but every 1.4 seconds. I think that the if statement is too long to be handled in ISR. Is there a better way to use if statement and keep the isr as short as possible? |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Tue Dec 24, 2019 8:00 pm |
|
|
Post your
1. Timer setup code in main().
2. Isr routine.
3. PIC oscillator setup code (#fuses and #use delay() )
Also post if a crystal or the internal oscillator is used.
4. Post your PIC. |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9243 Location: Greensville,Ontario
|
|
Posted: Wed Dec 25, 2019 5:21 am |
|
|
Along with PCM Ps comments...
ISRs must be short and quick so
NO floating point math
NO printing
NO 'complex' math
NO delays of any kind
Try to use only 8 bit unsigned variables
You should set 'flags' inside ISRs and let main() do what's needed.
as PCMP says..post your code
Jay |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Wed Dec 25, 2019 8:54 am |
|
|
The O.P. has not posted his code, so I will post a link to what I suspect
the problem might be:
Accuracy problem in timer0 interrupt -
http://www.ccsinfo.com/forum/viewtopic.php?t=49716
Read the replies by ckielstra and Ttelmah. |
|
|
aaronik19
Joined: 25 Apr 2011 Posts: 297
|
|
Posted: Wed Dec 25, 2019 12:01 pm |
|
|
Dear All,
Sorry I had some problems with my mail..now everything is ok. Well the code is:
Code: | #include <mainrtc.h>
int count_s;
#INT_RTCC
void RTCC_isr(void)
{
count_s++;
if (count_s == 60)
{
output_toggle(PIN_B4);
}
else
output_toggle(PIN_B3);
}
void main()
{
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_16); //1.0 s overflow
enable_interrupts(INT_RTCC);
enable_interrupts(GLOBAL);
setup_low_volt_detect(FALSE);
while(TRUE)
{
}
} |
I made the code simple for you to explain. I made the Timer0 to overflow every 1s but after about some seconds, it starts to increase...instead of 11s..12s..13.. it is 11.05...12.07 etc
I am using PIC18F248 and crystal of 4MHz. |
|
|
aaronik19
Joined: 25 Apr 2011 Posts: 297
|
|
Posted: Wed Dec 25, 2019 12:38 pm |
|
|
I also read the post "Accuracy problem in timer0 interrupt" and i know that inside ISR there is code that take time to be executed. I am just asking if there is another way I can work to reduce this time. |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9243 Location: Greensville,Ontario
|
|
Posted: Wed Dec 25, 2019 12:55 pm |
|
|
Two items I see
1) you don't select 8bit or 16 bit mode for the timer
2) you don't preset the counter
I'll assume the mode is 8 bit.. the 'default' but you should check that.
The lower byte of the timer0 counter is anything on powerup, so at lest for the first interrupt it could be almost any time, after that it should always be 256*16 microseconds, I think. But that's only 4,096 us NOT 1 second.
4MHz clk/4=1 us to timer.....
I'm waiting for turkey so maybe I'm not thinking right !?
Jay |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Wed Dec 25, 2019 1:06 pm |
|
|
temtronic, I compiled it and it defaults to 16 bit.
aaronik19,
Your code doesn't give a 1 second interrupt period.
It gives an interrupt period of 1.048576 seconds.
The math:
Instruction clock divided by prescaler:
1 MHz / 16 = 62500 Hz clock for Timer0.
Timer0 clock / size of 16-bit Timer0:
62500 / 65536 = 0.9536743 Hz interrupt rate
Convert rate to period:
1 / 0.9536743 Hz = 1.048576 seconds per interrupt. |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9243 Location: Greensville,Ontario
|
|
Posted: Wed Dec 25, 2019 1:42 pm |
|
|
hmm... according to the datasheet, it 'should' be 8 bit mode, so I assume CCS defaults to 16 bit mode...
Thanks for checking !
beginning to smell like turkey here, can't get much done......
'tis the season' 1
Cheers
Jay |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Wed Dec 25, 2019 2:25 pm |
|
|
Here is the compiled code, below. It's putting 0x83 into T0CON.
That value makes bit 6 = 0, which gives a 16-bit counter.
This is from the data sheet:
Quote: |
bit 6 T08BIT: Timer0 8-bit/16-bit Control bit
1 = Timer0 is configured as an 8-bit timer/counter
0 = Timer0 is configured as a 16-bit timer/counter |
See the value in bold below:
Quote: |
.................... void main()
00C6: CLRF TBLPTRU
00C8: BCF RCON.IPEN
00CA: BSF 07.7
00CC: BSF ADCON1.PCFG0
00CE: BSF ADCON1.PCFG1
00D0: BSF ADCON1.PCFG2
00D2: BCF ADCON1.PCFG3
.................... {
.................... setup_timer_0(RTCC_INTERNAL|RTCC_DIV_16); //1.0 s overflow
00D4: MOVLW 83
00D6: MOVWF T0CON
.................... enable_interrupts(INT_RTCC);
00D8: BSF INTCON.T0IE
.................... enable_interrupts(GLOBAL);
00DA: MOVLW C0
00DC: IORWF INTCON,F
.................... setup_low_volt_detect(FALSE);
00DE: CLRF LVDCON
....................
.................... while(TRUE)
.................... {
00E0: BRA 00E0
....................
.................... } |
|
|
|
aaronik19
Joined: 25 Apr 2011 Posts: 297
|
|
Posted: Wed Dec 25, 2019 2:54 pm |
|
|
Dear all...infact it is 16 bit. I set it from the wizard. |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9243 Location: Greensville,Ontario
|
|
Posted: Wed Dec 25, 2019 3:14 pm |
|
|
I must be getting old and fussy....
..OK, turkey's not done yet either....so...
Curious, I opened up the CCS manual....
and in the setup_timer_0(mode).... information
"PIC18XXX only: RTCC_OFF, RTCC_8_BIT"
Even though uChip defaults the PIC to 8 bit mode, CCS defaults to 16 bit mode !!
I'd have expected an 'RTCC_16_BIT' option as it's NOT the factory default.
The only way you'd really know is to dump the listing....
Oh well, learned something today..
Jay |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Wed Dec 25, 2019 7:19 pm |
|
|
Try this method. See if it works better.
Code: |
#include <18F46K22.h>
#fuses XT, NOWDT, BROWNOUT, PUT, NOPLLEN
#use delay(clock=4M)
#define T0_PRELOAD (65536 - 62500) // Count for 62500 T0 clocks
int count_s = 0;
// Timer0 is in 16-bit mode. It interrupts once per second.
#INT_TIMER0
void TIMER0_isr(void)
{
set_timer0(T0_PRELOAD + get_timer0()); // Adjust for interrupt overhead
count_s++;
if(count_s == 60)
{
output_toggle(PIN_B4);
count_s = 0; // Need to reset count_s if it reaches 60
}
else
output_toggle(PIN_B3);
}
//======================================
void main(void)
{
setup_timer_0(T0_INTERNAL | RTCC_DIV_16); // T0 clock = 62.5 KHz
set_timer0(T0_PRELOAD);
enable_interrupts(INT_TIMER0);
clear_interrupt(INT_TIMER0);
enable_interrupts(GLOBAL);
while(TRUE);
} |
|
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9243 Location: Greensville,Ontario
|
|
Posted: Fri Dec 27, 2019 1:18 pm |
|
|
Thre's also this....
http://www.ccsinfo.com/forum/viewtopic.php?t=26177
a SW RTC that I've used on several PICs over the years, though I prefer a HW RTC giving the PIC an interrupt every second. HW RTC also has battery backup, usually some CMOS RAM as well.
just another option to consider.
Jay |
|
|
aaronik19
Joined: 25 Apr 2011 Posts: 297
|
|
Posted: Sun Dec 29, 2019 2:04 am |
|
|
Dear All,
I continue to read about timers on PIC Micro and on the PIC18F248 there is an option to make external crystal for timer 1 T1OSI and T1OSO. So I think that if I can connect 32.768kHz crystal and 33pF to ground I might get a perfect 1 second interrupt.
the code that I tried from PCM worked good...thanks |
|
|
|