Problems using timer2 to measure and reproduce delay...

Have you got the greatest 48 bit multiplier ever conceived? Prove it - post your code here.

Moderator: phalanx

Post Reply
nio101
Posts: 16
Joined: Sat Aug 18, 2007 2:36 am

Problems using timer2 to measure and reproduce delay...

Post by nio101 » Wed Jan 12, 2011 10:41 pm

Hello,

I'm seeking some help in undestanding the origin of the problem I'm facing in my current project.
I'm using a PIC16F1823 to read the output of a TSIC506F temperature sensor, which uses a custom ZACWIRE protocol.

Here's an example showing what's coming out of the TSIC506F (A5) and a PIC output DEBUG signal:

Image

What I want to do is measure the delay between T1 and T2 using timer2 and then on every up->down transition of A5, repeat (wait) this very same delay before reading the A5 value...

Here's the code I use:

Code: Select all

 #include <htc.h>
 #include "main.h"
 
 // configuration words
 __CONFIG(FCMEN_OFF & IESO_OFF & CLKOUTEN_OFF & BOREN_OFF & CPD_OFF & CP_OFF \
                     & MCLRE_OFF & PWRTE_OFF & WDTE_OFF & FOSC_INTOSC);
 __CONFIG(LVP_OFF & STVREN_ON & PLLEN_ON & WRT_OFF);                    
 
 enum tState
 {
     waitTStrobe,
     readTStrobe,
     readBits,
     done,
     error,
     debug
 }
 
 volatile enum tState state;
 
 void interrupt myInterrupt()
 {    
     if (DEBUG==1)
             DEBUG = 0;
         else
             DEBUG = 1;
     if (TMR2IF)    // timer2 reaches PR2 => we're at TStrobe => read bit
     {            
         TMR2ON=0;    // stop timer2
         TMR2IE=0;
         TMR2IF=0;    // clear flag        
     }
     else
     if (IOCAF)    // IOC on A5/TProbe
     {
         if (state == waitTStrobe)    // first IOC interrupt up->low - T1 mark
         {
             // start timer2 to measure T1-T2 (should be around 62usec)
             TMR2=0;
             PR2=0xFF;
             TMR2ON=1;
             state=readTStrobe;
         }
         else
         if (state == readTStrobe)    // second IOC interrupt low->up : T2 mark => PR2 gives TStrobe
         {
             TMR2ON=0;    // stop timer2
             PR2=TMR2;
             //PR2=60;
             IOCAP5 = 0;    // stop interrupting on rising edge
             state=readBits;
         }
         else
         if (state == readBits)    // falling edge => wait for TStrobe (PR2)
         {
             TMR2=0;
             TMR2IE=1;
             TMR2ON=1;
         }
         IOCAF5=0;    //clear flag
     }
 }
 
 void main(void)
 {
     OSCCON = 0b01110011;    // 8MHZ
     
     // I/O config
     TRISA = 0b00100000;    // A5 as INPUT
     TRISC = 0;    
     ANSELA = 0b00000000;    // all digital
     ANSELC = 0;
     
     TSupply = 1;
     
     __delay_ms(30);
     
     DEBUG = 0;
     
     state = waitTStrobe;
     
     // setup IOC 
     IOCAP=0;    // for up/down interrupts on A5/TProbe
     IOCAN=0;
     IOCAP5=1;
     IOCAN5=1;
     IOCIE=1;    // IOC interrupt enable
     
     TMR2IE=0;    // default values ? could be omitted ?
     TMR2ON=0;
     
     GIE=1;        // enable all interrupts
     PEIE=1;    // enable all peripheral interrupts
     
     while(1) {}; // run infinitely
 }
When I run this code, the PR2 value read is 128, which seems correct since T1-2 is about 64us. But the delay I got using this PR2 value is far from 64us, and is about 86us (T4-T5 on the graph).

I understand that the delay won't be exactly the same, but @8MHz, the difference is very important, and represent more than 40 instructions cycles! When I'm having a look at the disassembly view in MPLAB, I can't find any 40 instruction cycle anywhere involved...

I also checked that timer2 was working well all alone (giving it a 128 value produced a 64us cycle)...

I made a second test giving manually to PR2 a value of 60, which should give a 30us delay:

Image

This time I got a 54us delay, instead of the 30usec delay I'd wanted. So there seems to be a +20usec extra delay, whatever the PR2 value I give...

Can somebody help me to understand where this +20usec delay comes from and where the instructions cycles are spent ?
Did I miss something ? Is there a major flaw in my code ?

Thanks!

Regards.

Nicolas.

Post Reply