1 second delay using TIMER1 of PIC16f877a

Discussion in 'Embedded Systems and Microcontrollers' started by bobparihar, Oct 28, 2014.

  1. bobparihar

    Thread Starter Member

    Jul 31, 2014
    93
    0
    i am doing a simple project of generating 1 second time delay and i choose timer1 of pic micro controller (PIC16f877a)
    the formula i have chosen to compute the time delay is like
    [​IMG]

    so for 1 sec the count value comes out to be 15

    register bit selection is as follows

    [​IMG]


    1. TMR1ON=1; // the timer is enable
    2. TMR1CS=0; // internal clock source
    3. T1CKPS0=0; // Prescaler value set to “00”
    4. T1CKPS1=0; // which means 1:1 (no division)

    and according to the calculation above my code is for 1 sec as follows( iam using mikroc compiler and proteus for simulation) :


    int count=0;
    void main() {

    TRISC=0; // configuring output port
    PORTC.F0=1; // led connected to 1st pin of portC
    TMR1H=0x00; // initial count values in timer1 register
    TMR1L=0x00;
    T1CON=0x01; // explained above in the discription
    while(1)
    {
    while(TMR1IF==0); // monitor the timer1 flag for overflow
    count=count+1;

    if(count==15)
    {
    PORTC.F0=~PORTC.F0;
    count=0;
    }
    PIR1.F0=0; //contaning Timer flag register at bit 0

    }
    }


    i think iam doing right but the code does not work
    anyone please tell me what wrong with it
     
    Last edited: Oct 28, 2014
  2. ericgibbs

    AAC Fanatic!

    Jan 29, 2010
    2,501
    380
    hi bob,
    If you can buy a 4.194MHz xtal, its a simple binary division down to 0.5Sec or 1Sec.
    E
     
  3. bobparihar

    Thread Starter Member

    Jul 31, 2014
    93
    0
    could'nt got u
     
  4. MaxHeadRoom

    Expert

    Jul 18, 2013
    10,511
    2,369
    A 32.768khz watch Xstal on T1CK T1 automatically rolls over in 1 sec.
    Max.
     
  5. BobTPH

    Active Member

    Jun 5, 2013
    782
    114
    The timer is incrementing on every instruction cycle, so you cannot expect TMR1 == 0 to succeed every time the timer goes to zero, since it will stay that way for only 1 instruction, and it will most likely happen on an instruction other than the compare. Actually it is worse than that, since TMR1 is 2 bytes it might never compare equal to 0, depending on the order they are compared.

    Use the interrupt flag instead. It will be set each time the timer overflows and you can clear after you see it set, guaranteeing that you catch all of them.

    Bob
     
  6. MaxHeadRoom

    Expert

    Jul 18, 2013
    10,511
    2,369
    With the 32khz xtal, if the T1 MSB is set, after the timer counts up the other 15 bits it generates a precise interupt at exactly 1 second.
    Max.
     
  7. Art

    Distinguished Member

    Sep 10, 2007
    785
    61
    If you use a timer on interrupt you also have to take into account the time it takes to save and resotre registers,
    and load a new value into the timer (depending on your osc value).
    If you used a second watch xtal o/c, you would have the slight resolution issue of waiting for
    the primary osc next cycle to do anything, and if it's the primary osc, the problem of speed (if that is an issue).
     
  8. BobTPH

    Active Member

    Jun 5, 2013
    782
    114
    You do not need to enable interrupts to use the timer interrupt flag. You can check it in a loop just like the OP was trying to check for TMR1 == 0.

    Bob
     
  9. jjw

    Member

    Dec 24, 2013
    173
    31
    He is checking the Timer1 interrupt flag in while( TMR1IF==0) ;
    The code looks OK.
    The problem might be in the Proteus simulator or in it's settings.
     
  10. John P

    AAC Fanatic!

    Oct 14, 2008
    1,632
    224
    Please read "Use of CODE tags". And what is wrong with computer keyboards in Asia? It seems as if nobody there can find the Shift keys.
    I wonder if the line
    Code (Text):
    1.  
    2.     while(TMR1IF==0);
    3.  
    is going to work properly. It may depend on the compiler. I've seen the reference to a flag in that way get turned into a reference to a memory register instead--maybe you could check the List file? It might be necessary to use something like
    Code (Text):
    1.  
    2.     while (!bit_test(PIR1, TMR1IF)) ;
    3.  
    or maybe
    Code (Text):
    1.  
    2.     while (!bit_test(PIR1, 0)) ;
    3.  
     
  11. BobTPH

    Active Member

    Jun 5, 2013
    782
    114
    Whoops, I misread the original code.

    Bob
     
  12. joeyd999

    AAC Fanatic!

    Jun 6, 2011
    2,675
    2,723
    BUT, TMR1IF doesn't reset itself. It must be cleared manually in software:

    Code (Text):
    1.  
    2. ...
    3.  
    4. while(TMR1IF==0); // monitor the timer1 flag for overflow
    5. TMR1IF=0; // clear the flag
    6. count=count+1;
    7.  
    8. ...
    9.  
    EDIT: Ooops...I guess this line:

    Code (Text):
    1.  
    2. PIR1.F0=0; //contaning Timer flag register at bit 0
    3.  
    presumably does that.
     
  13. John P

    AAC Fanatic!

    Oct 14, 2008
    1,632
    224
    Oh yes, of course. You must clear the flag, or it's going to stay set forever.
     
  14. bobparihar

    Thread Starter Member

    Jul 31, 2014
    93
    0
    guys it was all due to compiler.. instead of just writing the name of the flag TMR1IF=0 or PIR.F0=0 TMRIF_bit=0 should be used.. now the code working fine
     
  15. ErnieM

    AAC Fanatic!

    Apr 24, 2011
    7,386
    1,605
    That's not a compiler issue. The compiler gets those symbols from the include file for the PIC device you use.

    You as the programmer should use the exact same symbols as in that file.
     
    bobparihar likes this.
Loading...