Sunteți pe pagina 1din 12

Introduction to PIC Microcontroller Programming & Interfacing

August 19-21, 2010


Franz Duran

20-Aug-2010

Paranz

Timers
DAY 2 Afternoon Session August 20, 2010
20-Aug-2010 Paranz 2

PIC16F877A Timer Modules


Timer 0 (TMR0)
Simple architecture

Timer 1 (TMR1)
Can be used with the CCP module to perform capture or compare operations

Timer 2 (TMR2)
Can be used with the CCP module to perform PWM operations
20-Aug-2010 Paranz 3

TMR0 MODULE
8-bit timer/counter module
count up from 0x00 (0) 0xFF (255) overflow back to 0x00, can generate an interrupt

Used for timing-related applications

20-Aug-2010

Paranz

OVERVIEW
TMR0 architecture
SFRs

TMR0 Timer Mode Operation


Interrupt, Prescaler, Skip Timer technique, Presets

TMR0 Counter Mode Operation


20-Aug-2010 Paranz 5

TMR0 MODULE: Block Diagram

TMR0 module
20-Aug-2010 Paranz 6

TMR0 MODULE
Operating Mode:
Timer mode Counter mode

Associated SFRs
TMR0 OPTION INTCON
20-Aug-2010 Paranz 7

TMR0 MODULE: SFRs

20-Aug-2010

Paranz

TMR0: Timer Mode


Example TMR0 operation:
TMR0 in Timer mode (TOCS=0)
TMR0 is driven by the instruction clock

FOSC = 20 MHz FOSC/4 = 5MHz

(system frequency) (instruction cycle)

0.2 s instruction period

TMR0 increment from 0x00 0xFF every 51.2 s


256 x 0.2 s = 51.2 us or 19531.25 Hz

20-Aug-2010

Paranz

TMR0

0xFF 0 0xFE 0x03 0x02 0x01 0x00 1 0


TMR0 in Timer Mode
20-Aug-2010

1
No prescaler

Paranz

10

TMR0
#include <pic.h> void main() { TRISB0 = 0; RB0 = 0; T0CS = 0; PSA = 1; T0IE = 0; GIE = 0; while(1) { while(!T0IF); T0IF = 0; RB0 ^= 1; } }
20-Aug-2010 Paranz

Ex am ple
//RB0 pin is output, LED off //TMR0 uses the internal clock, Fosc/4 //No prescaler //Disable TMR0 interrupt

#1

//poll the T0IF bit, loop while bit is clear

//RB0 signal = 9765.6 Hz


11

TMR0: Interrupt
0 1 1

ISR is executed

20-Aug-2010

Paranz

12

TMR0: Interrupt
#include <pic.h>

void interrupt isr(void) { RB0 ^= 1; //toggle RB0 T0IF = 0; //clear TMR0 interrupt flag } void main() { .. .. .. }
20-Aug-2010 Paranz

Ex am ple

#2

13

TMR0: Interrupt
void main() { TRISB0 = 0; RB0 = 0; T0CS = 0; PSA = 1; T0IF = 0; T0IE = 1; GIE = 1; while(1); }
20-Aug-2010 Paranz

//RB0 pin is output. //LED is off.

Ex am ple

#2

//Timer mode. //No prescaler //Clear TMR0 interrupt flag. //Enable TMR0 interrupt. //Enable all interrupts. //Infinite loop, do nothing. //Wait for ISR to be executed.

14

TMR0: Prescaler
Why use prescaler?
to slow down the TMR0

0
20-Aug-2010 Paranz 15

TMR0: Prescaler
with no prescaler (PSA=1)
TMR0 register increment every instruction clock TMR0 overflows period = 51.2 s

with prescaler = 2 (PSA=0)


TMR0 register increment every 2 instruction clock TMR0 overflows period = 102.4 s
20-Aug-2010 Paranz 16

TMR0: Prescaler
with prescaler = 8
TMR0 register increment every 8 instruction clock TMR0 overflows period = 409.6 s

with prescaler = 256


TMR0 register increment every 256 instruction clock TMR0 overflows period = 13.1072 ms
20-Aug-2010 Paranz 17

TMR0: Prescaler

20-Aug-2010

Paranz

18

TMR0: Example #3
#include <pic.h>

void interrupt isr(void) { RB0 ^= 1; //Toggle RB0 T0IF = 0; //Clear TMR0 interrupt flag } void main() { .. .. .. }
20-Aug-2010 Paranz

Ex am ple

#3

19

TMR0
void main() { TRISB0 = 0; RB0 = 0; T0CS = 0; PSA = 0; PS2 = 1; PS1 = 1; PS0 = 1; TMR0IF = 0; TMR0IE = 1; GIE = 1; while(1); }
20-Aug-2010 Paranz

Ex am ple
//RB0 pin is output //LED is off

#3

//TMR0 uses the instruction clock, Fosc/4 //prescaler is assigned to TMR0 //prescaler = 256

//clear TMR0 interrupt flag bit //enable TMR0 as an interrupt source //enable all interrupts //infinite loop, do nothing //but wait for ISR to be executed
20

TMR0: Prescaler

1 1 1

0 TMR0 increment every 256 x FOSC/4


21

Prescaler = 256
20-Aug-2010 Paranz

TMR0: Skip Timer


Why use skip timer?
A software technique for slowing down the TMR0 derive a time delay that is multiples of the TMR0 overflow period

Prescaler hardware technique Skip Timer software technique


20-Aug-2010 Paranz 22

TMR0: Skip Timer


#include <pic.h> volatile unsigned int skptmr1;

Ex am ple
//skip timer variable

#4

void interrupt isr(void) { if(skptmr1) //If skip timer variable is not yet 0, --skptmr1; // decrement it. T0IF = 0; //Clear TMR0 interrupt flag. } void main() { .. .. .. }
20-Aug-2010 Paranz 23

TMR0: Skip Timer


void main() { TRISB0 = 0; RB0 = 0; //RB0 pin is output //LED is off //Timer mode. //Prescaler is assigned to TMR0. //Prescaler = 32. T0CS = 0; PSA = 0; PS2 = 1; PS1 = 0; PS0 = 0; T0IF = 0; T0IE = 1; GIE = 1; skptmr1 = 610;

Ex am ple

#4

//Clear TMR0 interrupt flag. //Enable TMR0 interrupt. //Enable all interrupts. //Approximately 1 second time delay.

while(1) { if(skptmr1==0) { skptmr1 = 610; RB0 ^= 1; } } 20-Aug-2010 }

//if skip timer variable is 0 //reset skip timer variable //toggle RB0 Paranz 24

TMR0: Skip Timer


skptmr1 = 610

Ex am ple

#4

Skptmr1 is decremented each time ISR is executed If skptmr1==0, ISR has execute 610x already
TMR0 overflow period

Why 610?
(4/20Mhz)x256x32 = 1.6384x10-3 or 610.35 Hz (rounded off to 610)
20-Aug-2010 Paranz 25

TMR0: Preset
To generate an accurate time delay using TMR0, use a preset value
TMR0 starts incrementing not from 0x00
Preset Value range from (0x00-0xFF) If Preset Value = 100, TMR0 increment 156x only before TMR0IF is set (overflow)
100 101 102 .. 254 255 0 (overflow)

With a preset, TMR0 doesnt increment the full 256 steps


20-Aug-2010 Paranz 26

TMR0: Preset
TMR0 Preset Value = 256 Period FOSC 4 Prescaler

Example:
TMR0 interrupt frequency = 5000 Hz
Period = 0.2 s

FOSC = 20MHz Prescaler = 4 TMR0 Preset Value = 6


20-Aug-2010 Paranz 27

TMR0: Preset
TMR0 Period

FOS C

Prescaler

Calculated Preset

Actual Preset

Adjusted Preset (+2)

Actual overflow period

200 s

20 Mhz

2 4 8 16 32 64 128 256

- 244 6 131 193.5 224.75 240.375 248.188 252.094


Paranz

N/A 6 131 194 225 240 248 252

N/A 8 133 196 227 242 250 254

N/A 200 s 200 s 198.4 s 198.4 s 204.8 s 204.8 s 204.8 s


28

20-Aug-2010

TMR0: Preset
Calculated Preset should be adjust (TMR0 Preset + 2) as advised in the device datasheet

20-Aug-2010

Paranz

29

TMR0: Preset
#include <pic.h> volatile unsigned int skptmr1 = 0;

//skip timer variable

Ex am ple

#5

void interrupt isr(void) { TMR0 = 0x08; //Write preset value to TMR0 if(skptmr1) //If skip timer variable is not yet 0, --skptmr1; // decrement it. T0IF = 0; //Clear TMR0 interrupt flag } void main() { .. .. .. }
20-Aug-2010 Paranz 30

10

TMR0: Preset
void main() { TRISB0 = 0; RB0 = 0; T0CS = 0; PSA = 0; PS2 = 0; PS1 = 0; PS0 = 1; TMR0IF = 0; TMR0IE = 1; GIE = 1; while(1) { ..... } 20-Aug-2010
Paranz

Ex am ple

//RB0 pin is output //LED is off //TMR0 timer mode //Prescaler is assigned to TMR0 //Prescaler = 4

#5

//Clear TMR0 interrupt flag bit //Enable TMR0 as an interrupt source //Enable all interrupts

31

TMR0: Preset
void main() { //Initializations //... while(1) { if(skptmr1==0) { skptmr1 = 5000; RB0 ^= 1; } } }
20-Aug-2010 Paranz

Ex am ple

#5

//Toggle every second

32

Using TMR0 Module


tmro.h and tmro.c
Copy the two files to the project folder In main.c, add the preprocessor directive
#include tmr0.h

20-Aug-2010

Paranz

33

11

Other Timer Modules: TMR1


TMR1
16-bit (0-65535)

Timer mode or Counter mode SFRs: T1CON, INTCON, PIR1, PIE1 Prescalers: 8,4,2,1 Use Preset to generate accurate time
Period FOSC TMR1 Preset Value = 65536 - 4 Prescaler
20-Aug-2010 Paranz 34

12