Timer 2
Timer 2
Timer 2
Timer2 Module
The Timer2 module can be modeled by a configurable counter and a flag. The processor (your program) configures the Timer2 for a desired amount of time. When the counter rolls over, the roll-over bit changes from 0 to 1, and sets a flag The counter is then reset and resumes to count. The processor can poll the flag, or, optionally, when the flag is set, an interrupt can be signaled to the processor.
Timer2 Module
The number of clock (CLK) edges required to make the counter roll over is configurable, and is given by the product of 3 individual counters: NumClockEdges = Pre-scalar * PR2 * Post-scalar
The time at which the counter rolls over is given by (Period of CLK) * NumClockEdges (Period of CLK) * Pre-scalar * PR2 * Post-scalar
3
Pre-scalar Counter 1, 4, 16
Timer2 Counter
EX
Comparator
PR2 Register
Interrupt Logic
FOSC is the frequency of the chip oscillator. We use ~4 MHz. FOSC is divided by 4, and the result clocks the Timer2 module: CLK FREQUENCY = FOSC/4 Time to execute one instruction: TCYC = (FOSC/4)-1
4
Pre-scalar Counter 1, 4, 16
Timer2 Counter
EX
Comparator
PR2 Register
Interrupt Logic
The Pre-scalar is configurable to rollover at either 1, 4, or 16 cycles of the CLK (FOSC/4) Configuration of the Pre-scalar counter is done by writing to bits T2CKPS1:T2CKPS0 of the TMR2 control register (T2CON).
Pre-scalar Counter 1, 4, 16
Timer2 Counter
EX
Comparator
PR2 Register
Interrupt Logic
Each time the Pre-scalar counter rolls-over, this increments the Timer2 Counter. When (and each time) the Timer2 Counter exceeds (EX) (one more than) the PR2 register, the Post-scalar Counter is incremented, and Timer2 Counter is reset. The PR2 register is an 8-bit register, which is writable. NOTE: PR2=0 means 1, PR2=1 means 2, , PR2=255 means 256
6
Pre-scalar Counter 1, 4, 16
Timer2 Counter
EX
Comparator
PR2 Register
Interrupt Logic
Pre-scalar Counter 1, 4, 16
Timer2 Counter
EX
Comparator
PR2 Register
Interrupt Logic
When the Post-scalar counter rolls over, the TMR2IF is set. Optionally, if the TiMeR2 Interrupt Enable (TMR2IE) bit is set, the TMR2IF may be relayed to the interrupt logic of the processor.
Testing Timer2
Testing Various Time Intervals Using Polling
Enter main() Function
PIC Processor Oscilloscope
1ms
PIR Register
RE2
Probe (+ve)
1ms
TMR2IF
Timer2 Counter Visualization Pin is Bit-2 of PortE (RE2) Timer2 module sets the TMR2IF flag at various intervals
Start Timer2
TMR2IF=1 ? Y TMR2IF=0
40 39 38 37 36 35 34 33 32 31 30 29 28 27 26 25 24 23 22 21
RJ-12
PIC16F877A
1 Master Clear 10 k 3.3 k 33 pF 2 3 4 5 6 7 8 RE2 9 10 11 12 13 14 15 16 17 18 19 20
To Oscilloscope
10
Testing Timer2
Testing Various Time Intervals Using Polling Desired Period 890 ns 40 s 80 s 500 s 1 ms 58 ms TCYC 890 ns 890 ns 890 ns 890 ns 890 ns 890 ns PreScalar 1 1 1 1 1 16 PR2 1 3 6 51 75 256 PostScalar 1 15 15 11 15 16 Calculated Period .89 s 40.05 s 80.1 s 499.29 s 1,001.25 s 58,327.04 s
Desired Period = (Period of FOSC/4) x Pre-scalar x PR2 x Post-scalar For 40 s: = 890 x 10-9 = 40.05 x 10-6 x 1 x 3 x 15
Inconvenient to hand calculate the best combination of Pre-scalar, PR2, and Postscalar for a desired period that yields the least error. Solve the problem programmatically
11
12
V1: POLLING
Complete Project Source Code (Unit Testing)
Main.c #include <xc.h> // pic16f877a.h #include "ProcessorConfiguration.h" #include "functionPrototypes.h" void main(void) { portInit(); timer2Init(); while(1) { while(TMR2IF == 0){} TMR2IF = 0; RE2 = !RE2; } } Timer2Initialization.c #include <xc.h> void timer2Init(void) { INTCON = 0; // Disable all interrupts. T2CON = 0b01110000; PR2 = 2; // 1 s * 1 * 3* 15 = 40 ms TMR2ON = 1; // Switch Timer 2 on // can also do T2CON = 0b01110100 TMR2IF = 0; // Clear Timer2 flag } PortInitialization.c #include <xc.h> // pic16f877a.h
void portInit(void) { PCFG3 = 0; // Configure PORTE as digital I/O PCFG2 = 1; PCFG1 = 1; TRISE2 = 0; // Configure PORTE-2 as output } FunctionPrototypes.h void main(void); void timer2Init(void); void portInit(void); ProcessorConfiguration.h #pragma config BOREN = OFF, CPD = OFF, DEBUG = ON, WRT = OFF, FOSC = EXTRC, WDTE = OFF, CP = OFF, LVP = OFF, PWRTE = OFF // Set configuration bits (See pic16f877a.h)
13
PROBLEMS
When viewing the visualization pin on the oscilloscope we observed some unequal periods and erratic behavior For very small periods, the waveform was not a perfect square wave, as expected To discover the problem, we analyzed the code and implemented a more accurate clock Using a 4MHz crystal, we obtained an instruction period of exactly 1 s.
14
40 39 38 37 36 35 34 33 32 31 30 29 28 27 26 25 24 23 22 21
RJ-12
PIC16F877A
1 Master Clear 10 k 2 3 4 5 6 7 8 RE2 9 10 11 12 13 14 15 16 17 18 19 20
4MHz
22 pF 22 pF
To Oscilloscope
15
ANALYSIS OF CODE
DISSASEMBLED VERSION OF while(1) LOOP
! while(1) { 0x7FC: GOTO 0x7F2 ! while(TMR2IF == 0); 0x7F1: GOTO 0x7F2 0x7F2: BCF STATUS, 0x5 0x7F3: BCF STATUS, 0x6 0x7F4: BTFSS PIR1, 0x1 0x7F5: GOTO 0x7F7 0x7F6: GOTO 0x7F8 0x7F7: GOTO 0x7F2 ! TMR2IF = 0; 0x7F8: BCF PIR1, 0x1 ! RE2 = !RE2; 0x7F9: MOVLW 0x4 0x7FA: XORWF PORTE, F 0x7FB: GOTO 0x7F2 ! } while(1) { while(TMR2IF==0); TMR2IF = 0; RE2 = !RE2; } Compiler inefficiencies:
GOTO 0x7F2 ? BCF STATUS, 0x5 BCF STATUS, 0x6 ? GOTO 0x7F7 GOTO 0x7F2 ? GOTO 0x7F8 ? MOVLW 0x4 ?
16
BestcasewhenTMR2IFissetat thebeginningofBTFSSPIR1,0x1 11InstructionCycles: 1:BTFSSPIR1,0x1 1:NOP 2:GOTO0x7F8 1:BCFPIR1,0x1 1:MOVLW0x4 1:XORWFPORTE,F 2:GOTO0x7F2 1:BCFSTATUS,0x5 1:BCFSTATUS,0x6
17
WorstcasewhenTMR2IFisset whenBTFSSPIR1,0x1completes
18InstructionCycles: 1:BTFSSPIR1,0x1 2:GOTO0x7F7 2:GOTO0x7F2 1:BCFSTATUS,0x5 1:BCFSTATUS,0x6 1:BTFSSPIR1,0x1 1:NOP 2:GOTO0x7F8 1:BCFPIR1,0x1 1:MOVLW0x4 1:XORWFPORTE,F 2:GOTO0x7F2 1:BCFSTATUS,0x5 1:BCFSTATUS,0x6
18
btfss is FALSE
PIR1,
0x1;
btfss is TRUE
22
btfss is FALSE
PIR1,
0x1;
btfss is TRUE
23
btfss is FALSE
PIR1,
0x1;
btfss is TRUE
24
INTERRUPT METHOD
Interrupt method would produce a better waveform, because the system will be synchronized with each TMR2IF becoming set Disadvantage of the interrupt method is the interrupt latency cause by saving the status of the machine upon an interrupt
25
INTERRUPT LOGIC
INTERRUPT FUNCTION
Main.c ... REQUIRED SYNTAX GOOD PROGRAMMING PRACTISE
void interrupt TMR2InterruptFunction(void) { if(TMR2IF==1) //Check if this is a TMR2 interrupt { TMR2IF = 0; //Clear TMR2IF RE2 = !RE2; //Toggle visualization bit } return; //Return from interrupt }
28
V1: INTERRUPTS
Complete Project Source Code (Unit Testing)
Main.c #include <xc.h> // pic16f877a.h #include "ProcessorConfiguration.h" #include "functionPrototypes.h" unsigned char timeOut = 0; void main(void) { portInit(); timer2Init(); while(1) { } } void interrupt TMR2InterruptFunction(void) { if(TMR2IF==1) { TMR2IF = 0; RE2 = !RE2; } return; } Timer2Initialization.c #include <xc.h> void timer2Init(void) { INTCON = 0; // Disable all interrupts. T2CON = 0b01110100; PR2 = 2; // 1 s * 1 * 3* 15 = 40 ms TMR2IE = 1; // Enable TMR2 interrupts PEIE = 1; // Enable peripheral interrupts GIE = 1; // global interrupt enable TMR2IF = 0; // Clear Timer2 flag } PortInitialization.c (same as for polling) FunctionPrototypes.h (same as for polling) ProcessorConfiguration.h (same as for polling)
29