Creating timer in PIC

be80be

Joined Jul 5, 2008
2,072
It lost in space

Rich (BB code):
CORE-E0001: Stack over flow error occurred from instruction at 0x00000e
CORE-E0001: Stack over flow error occurred from instruction at 0x00000e
CORE-E0001: Stack over flow error occurred from instruction at 0x00000e
CORE-E0001: Stack over flow error occurred from instruction at 0x00000e
CORE-E0001: Stack over flow error occurred from instruction at 0x00000e
CORE-E0001: Stack over flow error occurred from instruction at 0x00000e
CORE-E0001: Stack over flow error occurred from instruction at 0x00000e
CORE-E0001: Stack over flow error occurred from instruction at 0x00000e
CORE-E0001: Stack over flow error occurred from instruction at 0x00000e
CORE-E0001: Stack over flow error occurred from instruction at 0x00000e
CORE-E0001: Stack over flow error occurred from instruction at 0x00000e
CORE-E0001: Stack over flow error occurred from instruction at 0x00000e
CORE-E0001: Stack over flow error occurred from instruction at 0x00000e
CORE-E0001: Stack over flow error occurred from instruction at 0x00000e
CORE-E0002: Stack under flow error occurred from instruction at 0x00001b
CORE-E0001: Stack over flow error occurred from instruction at 0x000005
CORE-E0001: Stack over flow error occurred from instruction at 0x000006
 

Thread Starter

RG23

Joined Dec 6, 2010
304
I would appreciate if anyone can make changes to my code and help me get those three timers from the single timer of 25 us
 

be80be

Joined Jul 5, 2008
2,072
Your looking at at 50,000 / 25 = 2000 ticks at 4mhz

So the easy way would be is let the timer0 run and set a flag at 40 ticks 1 ms

and increase a counter every time you hit 40, till you hit 50 ms set counter2 to increase
100 times and you have 500 ms

Preload the counters with the error that you have testing and you'll get real close.

Rich (BB code):
     btfss     INTCON,T0IF    ; wait here until Timer0 rolls over
     goto      ForeverLoop
     bcf       INTCON,T0IF    ; flag must be cleared in software
     incf      counter1      ; increment  variable
 
One mistake is your main code just runs right into your interrupt routine. Single stepping that in the simulator (get it working seriously) would have shown that really quickly.
 

Thread Starter

RG23

Joined Dec 6, 2010
304
Following is the code I tried
It works but the power PORTC,6 does not stay high all the time

Rich (BB code):
#include <p16F887.inc>
///variable definitions
org 0
Start:
goto SOC
org 4
goto ISR
 
 
ISR:
BCF STATUS, RP0
BCF STATUS, RP1 ; select Register Bank 0
 
btfsc INTCON,2 ; TMR0 int (25us timer)
goto label1
retfie
 
label1:
bcf INTCON,2
;movlw b'00000100'
;xorwf PORTA
incf count2,1
movf count2,0
sublw d'36'
btfsc STATUS,Z
call label2
movlw 0xFB
movwf TMR0
retfie
label2: 
;movlw b'00100000'
;xorwf PORTA
movlw d'0'
movwf count2
incf count3,1
movf count3,0
sublw d'9'
btfsc STATUS,Z
call label3
return
label3:
movlw b'00100000'
xorwf PORTB
movlw d'0'
movwf count3
incf count4,1
movf count4,0
sublw d'5'
btfsc STATUS,Z
call label4
return
label4:
movlw b'00100000'
xorwf PORTC
movlw d'0'
movwf count4
incf count5,1
movf count5,0
sublw d'10'
btfsc STATUS,Z
call label5
return
label5:
movlw b'00100000'
xorwf PORTA
movlw d'0'
movwf count5
return
 
Bank0:
movlw 0xFB
movwf TMR0
return
Bank1:
BSF STATUS, RP0
movlw 0x61
movwf OSCCON
movlw 0x00
movwf TRISA
movlw 0x00
movwf TRISB
movlw 0x00
movwf TRISC
movlw 0x00
movwf OPTION_REG
BCF STATUS,RP0 
return
 
SOC:
call Bank0
call Bank1
bcf INTCON,2
bsf INTCON,5
 
End
 
Last edited by a moderator:

John P

Joined Oct 14, 2008
2,026
I think what you're trying to achieve can be done, but 25usec is a fast interrupt rate. Assuming that you have an external crystal with the maximum frequency (20MHz) you have 125 instructions for each interrupt. That should be enough time to enter and leave the interrupt each time, and to run a counter that performs the operations you want--or at least, that sets flags that the main() routine can check to tell it to do those things.

The counter would increment at 5 megahertz. You haven't said whether you'd want the 3 events to occur simultaneously when the 500msec interval ends, but I'll assume that's the idea, and that allows counters that have no more than 16 bits each (use code /code markers for formatting):

Rich (BB code):
// Interrupt routine at 25usec, using TMR2
// Flags get cleared elsewhere
{
  static unsigned ctr1;            // This is a 16 bit quantity
  static unsigned byte ctr2;
  static unsigned byte ctr3;

  if (++ctr1 >= 50000)            // 10msec (50000 counts at 5MHz)
  {
    flag_10 = 1;
    ctr1 = 0;
    if (++ctr2 >= 5)                // 50msec
    {
      flag_50 = 1;
      ctr2 = 0;
      if (++ctr3 >= 10)            // 500msec
      {
        flag_500 = 1;
        ctr3 = 0;
      }
    }
  }

  // Insert other stuff to be done at 25usec intervals, but it had better be fast
}
 

Thread Starter

RG23

Joined Dec 6, 2010
304
Though I have defined timer0 as 25 us timer, I am getting 100 us timer

Does anyone have an idea why is it so?

Thanks
 
it works use correct count value ..
for example if you are creating timer for 25μs then

to get 50ms set a flag after 2000 count .....

example count=0;
in the interrupt try 2 increment this count ie
count++
if(count==2000)
{
set a flag=1;// use this flag in the main loop and do the task which u want to after every 50ms ....
count =0;
}


similarly for 100ms 4000
and for 10ms 400
 

Thread Starter

RG23

Joined Dec 6, 2010
304
yeah it works

i am getting the three time intervals of 10 ms, 50 ms , 500 ms by setting corresponding counter variables

but when i tried to check the timer of 25 us,

i am getting 100 us

i have 00 in OPTION_REG
and FB in TMR0 register

It should have given me exactly 25 us timer

If anyone has an idea please let me know

Thanks
 

John P

Joined Oct 14, 2008
2,026
I think your timer rate is approximately correct.

With 0 in the OPTION reg, you get a 2:1 division of the clock rate, so

Assuming a 20MHz crystal, instruction time is 20000000/4, or 5MHz
Divide by 2, so count rate is 2.5MHz
Divide 2.5MHz by 241 (= 0xFB) and you get 10373Hz, or about 100usec, but not exact.

Why not use TMR2? You wouldn't need any action to keep getting the same interval, and you could have it interrupt at an exact 25usec. Use 1:1 prescale and postscale, and count to 125.
 
Top