Timing – Timers

Timer interrupts

In most Microchip PIC microcontrollers, there are more than one hardware timers which have interrupts. The best thing about timer is that they work in the background. The delay loops will pause your program. You have to wait for them to complete. By using timers, you don’t have to wait for them. When they finish work, they will produce an interrupt. It is like an alarm clock.

Timer0

We will examine Timer0. Because, it is the most common timer in Microchip PIC microcontrollers. It is a 8bit timer with prescaler.

Timer0 related registers

OPTION

Option register sets the general features of Timer0 such as prescaler, clock source, edge type, etc.

OPTION_REG

Prescaler PS«2:0», bit 2:0 of Option register

Prescaler determines in how many instruction cycle Timer0 will count one. Let’s say we set prescaler value to 1:8. Then, every 8 instruction cycle, Timer0 will count 1. Prescaler can take below values :

PS«2:0» – prescaler
000 – 1:2
001 – 1:4
010 – 1:8
011 – 1:16
100 – 1:32
101 – 1:64
110 – 1:128
111 – 1:256

Note that 3. bit of Option register (PSA) assigns this prescaler to Timer0 or WDT. Making this bit 0 assigns prescaler to Timer0. If prescaler is assigned to WDT, there is no prescaler for Timer0 (,or vice versa).

Timer0 clock source T0CS, bit 5 of Option register

The clock source of Timer0 can be PORTA.4 (RA4/T0CKI) external clock or internal instruction cycle clock. This bit assigns clock source to Timer0. Making this bit 1 will choose RA4/T0CKI pin as clock source and 0 will choose instruction cycle clock.

If RA4/T0CKI external clock is choosen, T0SE (4.bit of Option register) will assign the edge of the clock. if T0SE is set to 1, high to low transition will increment the clock, otherwise low to high transition will increment the clock.

To use RA4/T0CKI, TRISA.4 must be choosen as input.

INTCON

INTCON

Timer0 interrupt enable T0IE, bit 5 of INTCON

This bit enables the Timer0 interrupt.

Timer0 interrupt flag T0IF, bit 2 of INTCON

When an overflow has occured on Timer0, this flag will be ’1′.

To use Timer0 interrupt, general interrupts must be enabled (set bit 7 of INTCON).

Now, let’s design a 500us timer. We will use internal instruction cycle. We said before Timer0 is a 8bit timer. So, it will count untill 255 and an overflow will be occured. We decided to design a 500us timer. 500/2=250 we are inside the 255 limit (8bit). We can choose 1:2 prescaler. That will count 1 in every two instruction cycle. That makes 256x2us=512us. We can define a starting point for counting. Here, we should start from 6. So that, counter will count 250 and overflow will be occured.

#define <p16f628.inc>
ORG 0×00
GOTO main
ORG 0×04
GOTO interrupt

main:
BSF STATUS,RP0 ;Switch BANK1
CLRF TRISB ;Make all bits of PORTB as output
MOVLW b’00000000′
MOVWF OPTION_REG
;First three bits (bit«2:0») are prescaler value. We set prescaler to 1:2 (PS«2:0»=000)
;bit 3 = 0 assigns prescaler to Timer0
;bit 5 = 0 assigns instruction cycle as clock source
;bit 4 = NA it assigns edge select of external clock, we use internal clock
;bit 6 = NA
;bit 7 = NA
BCF STATUS,RP0 ;Switch to BANK0
MOVLW b’00000100′
MOVWF INTCON ;Enable Timer0 interrupt, Disable all others
BSF INTCON,GIE ;Enable general interrupts
MOVLW d’6′
MOVWF TMR0 ;Timer0 starting point, writing this will start timer after two ins. cyc.
LOOP: ;Infinite LOOP
GOTO LOOP ;We can do other things while timer is counting

interrupt:
BTFSS INTCON,T0IF ;Check if interrupt is caused by Timer0
GOTO exit_interrupt ;If not exit interrupt routine
MOVLW b’00000001′
XORWF PORTB,F ;Blink PORTB.0, but it will be too fast to see on LED, 500us.
BCF INTCON,T0IF ;Clear Timer0 interrupt flag, otherwise interrupt will not be occured again
BSF INTCON,T0IE ;Enable Timer0 interrupt again
MOVLW d’6′
MOVWF TMR0 ;Start Timer0 again from 6
exit_interrupt:
RETFIE ;Enable general interrupts and return

END

1 second Timer0 overflow

If we calculate maximum overflow time, it is 256*256*1us=65536us=65.536ms (First 256 is the maximum prescaler value. Second 256 is the 8bit timer value. And assume that we used 4MHz oscillator which means 1us instruction cycle.) What if we need let’s say 1 second Timer overflow?

In case we need longer overflow, we should use another register for multiplying overflow time. If we need 5 times of overflow time, we should count overflows untill 5.

Let’s calculate one second delay. We will use an overflow counter. We need to choose a prescaler value, TMR0 starting value and a counter value. To do such calculations, i use Open Office Calc (or Microsoft Excel).

CALC-ITERATION

We have Calc to do some iterations for us. The first column is our prescaler value. I choosed 256. If i couldn’t find an integer value, i would replace 256 with 128, and , would do same iterations with it. The second column is how much we count for overflow. Then, we set TMR0 to 256-217=39. TMR0 will start to count from 39 to 256. The third column is the multiplication of prescaler and TMR0. An overflow will take place 256*217*1us=55552us later. The fourth column is 1second/55552=1000000ms/55552=18. This value is for the counter. We will decrease counter from 18 to 0. That means, we will wait for 18 overflows. 55552*18=1000000us=1s

#define <p16f628.inc>

CNT1 EQU h’20′ ;User defined register

ORG 0×00
GOTO main
ORG 0×04
GOTO interrupt

main:
BSF STATUS,RP0 ;Switch BANK1
CLRF TRISB ;Make all bits of PORTB as output
MOVLW b’00000111′
MOVWF OPTION_REG
;First three bits (bit«2:0») are prescaler value. We set prescaler to 1:2 (PS«2:0»=111)
;bit 3 = 0 assigns prescaler to Timer0
;bit 5 = 0 assigns instruction cycle as clock source
;bit 4 = NA it assigns edge select of external clock, we use internal clock
;bit 6 = NA
;bit 7 = NA
BCF STATUS,RP0 ;Switch to BANK0
MOVLW b’00000100′
MOVWF INTCON ;Enable Timer0 interrupt, Disable all others
BSF INTCON,GIE ;Enable general interrupts
MOVLW d’39′
MOVWF TMR0 ;Timer0 starting point, writing this will start timer after two ins. cyc.
MOVLW d’18′ ;Overflow counter for 1 second
MOVWF CNT1

LOOP: ;Infinite LOOP
GOTO LOOP ;We can do other things while timer is counting

interrupt:
BTFSS INTCON,T0IF ;Check if interrupt is caused by Timer0
GOTO exit_interrupt ;If not exit interrupt routine
DECFSZ CNT1,F ;Decrease CNT1. If zero, skip next ins.interrupt will not be occured again
GOTO not_counted_yet ;Not zero goto not counted
MOVLW b’00000001′
XORWF PORTB,F ;Blink PORTB.0
MOVWF CNT1 ;Reload counter
not_counted_yet:
BCF INTCON,T0IF ;Clear Timer0 interrupt flag, otherwise interrupt will not be occured again
BSF INTCON,T0IE ;Enable Timer0 interrupt again
MOVLW d’39′
MOVWF TMR0 ;Reload Timer0
exit_interrupt:
RETFIE ;Enable general interrupts and return

END

Another usage of Timers is overflow (in the exact meaning of overflow). Let’s say you wait for pushing two buttons one after other from user. If you don’t put an overflow between two pushes, user can push one button and 2 hours later push the other button. You can put one minute overflow after first push. Then, user must push second button in one minute. Otherwise, user push first button again.

We discussed Timer0 overflow interrupt and how to use it in timing. There are other special Timers such as match occured interrupt for some PICs. On these timers, we put a match value to a register and wait for the match occurs with Timer (Same as overflow. This time we put the overflow limit.). Once you understand the logic of timer, it is easy and comfortable to use them. Just read data sheets carefully.

Share and Enjoy

  • Facebook
  • Twitter
  • Delicious
  • LinkedIn
  • StumbleUpon
  • Reddit
  • Add to favorites
  • Email
  • RSS

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>