Clock project with PIC16F873

Discussion in 'Embedded Systems and Microcontrollers' started by ecka333, Sep 19, 2010.

  1. ecka333

    Thread Starter Active Member

    Oct 1, 2009
    76
    0
    I am doing dual channel timer with pic16f873 microcontroller. Compiler - mikroc from Mikroelektronika. Timer schematic and pcb is ready, now i am programming microcontroller. Now clock programming is made, but code is not working. Microcontroller now must count minutes and hours and display time in four seven segments displays. But all, that these displays shows, is lighting three segments: a, d and g. Three buttons is not programmed yet. Mybe someone could help me with the code? Schematics is in .doc file. Part I of the code:


    Code ( (Unknown Language)):
    1.  
    2. //Quartz crystal=2.097152Mhz, ucontroller - PIC16F873
    3. /*Configuration:
    4. oscilator XT; code protection off; WDT disabled; power-up timer enabled;
    5. brown-out reset enabled; low voltage programming disabled;
    6. code protection data disabled; flash program memory write enabled;
    7. debugger mode disabled.
    8. */
    9. //variable declaration
    10. unsigned int Clock, T1on, T1off, T2on, T2off, Display;
    11. unsigned short int Hours, Minutes, Seconds,
    12. Segment1, Segment2, Segment3, Segment4, WhatShow;
    13. bit SA1Press, SA2Press, SA3Press, SA2SA3Press, HG2DpToggle, EditMode, Blackout;
    14. void zero(){PORTC=0b00111111;}         //show number 0 in display
    15. void one(){PORTC=0b00000110;}          //show number 1 in display
    16. void two(){PORTC=0b01011011;}          //show number 2 in display
    17. void three (){PORTC=0b01001111;}       //show number 3 in display
    18. void four (){PORTC=0b01100110;}        //show number 4 in display
    19. void five (){PORTC=0b01101101;}        //show number 5 in display
    20. void six (){PORTC=0b01111101;}         //show number 8 in display
    21. void seven (){PORTC=0b00000111;}       //show number 7 in display
    22. void eight (){PORTC=0b01111111;}       //show number 8 in display
    23. void nine (){PORTC=0b01101111;}        //show number 9 in display
    24. void blank (){PORTC=0b00000000;}        //show nothing in display
    25. void Delay(){Delay_ms(5);}             //delay
    26. void InitTimer0 ()
    27.     {
    28.     // Timer0 initialisation (led blinker in Edit mode) Period = 0.125 sec (8Hz)
    29.     TMR0 = 0;                // preset for timer register
    30.     OPTION_REG.PSA = 0;      // prescaler is assigned to the Timer0
    31.     OPTION_REG.PS2 = 1;      // Prescaler= 256
    32.     OPTION_REG.PS1 = 1;
    33.     OPTION_REG.PS0 = 1;
    34.     OPTION_REG.T0CS = 0;     // TMR0 Clock Source Select bit - Internal Clock
    35.     INTCON.T0IF=0;              //clear TMR0 interrupt flag
    36.     INTCON.T0IE=0;           //TMR0 interrupt enable
    37.     }
    38.     void InitTimer1 ()
    39.     {
    40.     // Timer1 initialisation (Seconds counter) Period = 1 sec
    41.     T1CON.T1CKPS1 = 1;       // Prescaler= 8
    42.     T1CON.T1CKPS0 = 1;
    43.     T1CON.T1OSCEN = 0;       // Timer1 Oscillator disable
    44.     T1CON.TMR1CS = 0;        // Timer1 Clock Source Select bit - internal clock
    45.     T1CON.TMR1ON = 1;        // enable timer
    46.     TMR1H = 0;               // preset for timer1 MSB register
    47.     TMR1L = 0;               // preset for timer1 LSB register
    48.     PIR1.TMR1IF = 0;         //clear TMR1 interrupt flag
    49.     PIE1.TMR1IE=1;           //TMR1 interrupt enable
    50.     }
    51. void InitTimer2 ()
    52.     {
    53.     //Timer2 initialisation (Display multiplexing) Period = 0.00341797 seconds
    54.     PR2 = 7;                 // PR2 (Timer2 Match value)
    55.     T2CON = 120;             // Postscaler=16
    56.     T2CON.T2CKPS1 = 1;      // Prescaler=16
    57.     T2CON.T2CKPS0 = 0;
    58.     T2CON.TMR2ON = 1;       // turn timer2 on;
    59.     PIR1.TMR2IF = 0;        // clear timer2 interupt flag
    60.     PIE1.TMR2IE = 1;        // enable Timer2 interrupts
    61.     }
    62.  
    63.  
    64.  
     
    Last edited: Oct 9, 2010
  2. ecka333

    Thread Starter Active Member

    Oct 1, 2009
    76
    0
    Now my project is near the end, all programming work is done. But now i noticed, that microcontrollers clock is running too fast. The innacurracy is different: one day it reaches 1 minute in every 10 minutes, the other day it is 4 seconds in 10 hours. I can't understant, why the difference is so big. I am using pic16f873 microcontroller, 2,097152MHz crystal oscilator (XTAL configuration) with 15pF ceramic capacitors. Maybe inacurracy comes from environment temperature? And how i can correct this clock inacurracy?
    PART II of the code:
    Code ( (Unknown Language)):
    1.  
    2.  
    3. void interrupt ()
    4.     {
    5.      if(PORTB.B7==0){Blackout=0;} else {Blackout=1;}
    6.      if(Blackout==1)
    7.          {PORTC=0b00000000;//turn off HG1-HG4 indicators on blackout
    8.          PORTA.B3=0; PORTB.B3=0; PORTA.B4=1; TRISA.B5=1; //turn off all five diode indicators on blackout
    9.          PORTA.B1=0; PORTA.B2=0;//turn off outputs of timers on Blackout
    10.          EditMode=0;
    11.         }
    12.     //interrupt from Timer0 -  0.125sec(led blinker in Edit mode)
    13.     if(INTCON.T0IF==1&&INTCON.T0IE==1&&Blackout==0)
    14.         {if(WhatShow==0){PORTA.B3=~PORTA.B3;}
    15.         if(WhatShow==1){PORTB.B3=~PORTB.B3;}
    16.         if(WhatShow==2){PORTA.B4=~PORTA.B4;}
    17.         if(WhatShow==3){PORTA.B5=0; TRISA.B5=~TRISA.B5;}
    18.         if(WhatShow==4){PORTA.B5=1; TRISA.B5=~TRISA.B5;}
    19.         INTCON.T0IF=0;
    20.         }
    21.      //interrupt from Timer1 - 1 sec (Seconds counter)
    22.      if(PIR1.TMR1IF==1&&PIE1.TMR1IE==1){
    23.      HG2DpToggle=~HG2DpToggle;//togle auxiliary HG2 decimal point's bit
    24.      if (Seconds<=58) {Seconds=Seconds+1;}
    25.      else if (Seconds==59&&Clock<=1438) {Seconds=0; Clock=Clock+1;}
    26.      else if (Seconds==59&&Clock==1439) {Seconds=0; Clock=0;};
    27.      PIR1.TMR1IF=0;}                    //clear TMR1 flag
    28.      //interrupt from Timer2 - 0.00341797 sec (Display multiplexing)
    29.      if(Blackout==0&&PIR1.TMR2IF==1){
    30.          if (PORTB.B2==1) {PORTB.B2=0;
    31.          switch (Segment2){
    32.          case 0: zero(); break;
    33.          case 1: one (); break;
    34.          case 2: two(); break;
    35.          case 3: three (); break;
    36.          case 4: four(); break;
    37.          case 5: five (); break;
    38.          case 6: six(); break;
    39.          case 7: seven (); break;
    40.          case 8: eight(); break;
    41.          case 9: nine (); break;};
    42.          PORTB.B1=1; PORTB.B0=0; PORTA.B0=0;
    43.          PORTC.B7=HG2DpToggle;               //blink indicator's HG2 decimal point
    44.                            }
    45.  
    46.          else if (PORTA.B0==1) {PORTA.B0=0;
    47.          switch (Segment1){
    48.          case 0: blank(); break;
    49.          case 1: one (); break;
    50.          case 2: two(); break;
    51.                         };
    52.          PORTB.B2=1; PORTB.B1=0; PORTB.B0=0; PORTC.B7=0;
    53.                                }
    54.  
    55.          else if (PORTB.B0==1) {PORTB.B0=0;
    56.          switch (Segment4){
    57.          case 0: zero(); break;
    58.          case 1: one (); break;
    59.          case 2: two(); break;
    60.          case 3: three (); break;
    61.          case 4: four(); break;
    62.          case 5: five (); break;
    63.          case 6: six(); break;
    64.          case 7: seven (); break;
    65.          case 8: eight(); break;
    66.          case 9: nine (); break;};
    67.          PORTA.B0=1; PORTB.B1=0; PORTB.B2=0; PORTC.B7=0;
    68.                           }
    69.          else if (PORTB.B1==1) {PORTB.B1=0;
    70.          switch (Segment3){
    71.          case 0: zero(); break;
    72.          case 1: one (); break;
    73.          case 2: two(); break;
    74.          case 3: three (); break;
    75.          case 4: four(); break;
    76.          case 5: five (); break;
    77.          case 6: six(); break;
    78.          case 7: seven (); break;
    79.          case 8: eight(); break;
    80.          case 9: nine (); break;};
    81.          PORTB.B0=1; PORTA.B0=0; PORTB.B2=0; PORTC.B7=0;
    82.                         }
    83.      PIR1.TMR2IF=0;}     //clear TMR2 flag
    84.      }
    85. void main()
    86.      {
    87.      /*SFR's and variables initialisation*/
    88.      ADCON1=0b00000110;        //make PORTA pins digital
    89.      TRISA=0b00100000;         //configure input/output pins, turn on Clock indication
    90.      TRISB=0b11110000;
    91.      TRISC=0b00000000;
    92.      PORTA=0b00011000;         //clear data latches
    93.      PORTB=0b11110100;
    94.      PORTC=0b00000000;
    95.      OPTION_REG.B7=0;          //turn on pullups for B port
    96.      Seconds=0; Clock=0; T1on=0; T1off=0; T2on=0, T2off=0; //Set all variables to zero
    97.      SA1Press=0; SA2Press=0; SA3Press=0; SA2SA3Press=0;
    98.      WhatShow=0; EditMode=0;              //on turn-on show Clock time in display
    99.      InitTimer0 ();
    100.      InitTimer1 ();
    101.      InitTimer2 ();
    102.      INTCON.PEIE = 1;        //Peripheral Interrupt Enable
    103.      INTCON.GIE = 1;         // global interrupt enable
    104.  
    105.       for (;;)
    106.       {
    107.       //turn timers on and off
    108.       if(Blackout==0)
    109.           {if(Clock>=T1on&&Clock<T1off){PORTA.B2=1;}
    110.           else if(Clock>=T1off&&Clock<T1on){PORTA.B2=1;}
    111.           else{PORTA.B2=0;};
    112.           if(Clock>=T2on&&Clock<T2off){PORTA.B1=1;}
    113.           else if(Clock>=T2off&&Clock<T2on){PORTA.B1=1;}
    114.           else{PORTA.B1=0;}
    115.           }
    116.       //display modes initialization
    117.       if (WhatShow==0){Display=Clock;}
    118.       else if(WhatShow==1){Display=T1on;}
    119.       else if(WhatShow==2){Display=T1off;}
    120.       else if(WhatShow==3){Display=T2on;}
    121.       else if(WhatShow==4){Display=T2off;}
    122.       //display modes indication
    123.       if(EditMode==0&&PORTB.B7==0)
    124.           {if (WhatShow==0){PORTA.B3=1; PORTB.B3=0; PORTA.B4=1; TRISA.B5=1;}
    125.           else if(WhatShow==1){PORTA.B3=0; PORTB.B3=1; PORTA.B4=1; TRISA.B5=1;}
    126.           else if(WhatShow==2){PORTA.B3=0; PORTB.B3=0; PORTA.B4=0; TRISA.B5=1;}
    127.           else if(WhatShow==3){PORTA.B3=0; PORTB.B3=0; PORTA.B4=1; TRISA.B5=0; PORTA.B5=0;}
    128.           else if(WhatShow==4){PORTA.B3=0; PORTB.B3=0; PORTB.B4=1; TRISA.B5=0; PORTA.B5=1;}
    129.           }
    130.           //Time calculation
    131.           Hours=Display/60;
    132.           Segment1=Hours/10;         //calculate tens of hours
    133.           Segment2=Hours%10;         //calculate ones of hours
    134.           Minutes=Display%60;
    135.           Segment3=Minutes/10;         //calculate tens of minutes
    136.           Segment4=Minutes%10;         //calculate ones of minutes
    137.  
    138.          //check if button SA1 is pressed
    139.          if(PORTB.B4==0&&SA1Press==0&&EditMode==0){SA1Press=1; Delay();};
    140.          if(PORTB.B4==1&&SA1Press==1&&EditMode==0)
    141.              {SA1Press=0; Delay();
    142.              //button SA1 was pressed and released, so switch mode:
    143.              if(Whatshow<4){Whatshow++;}else{Whatshow=0;}
    144.              };
    145.          //Check if SA2 & SA3 simultaneously pressed, if pressed, enter edit mode
    146.          if(EditMode==0&&PORTB.B5==0&&PORTB.B6==0&&SA2SA3Press==0){SA2SA3Press=1; Delay();}
    147.          if(PORTB.B5==1&&PORTB.B6==1&&SA2SA3Press==1){SA2SA3Press=0; Delay(); EditMode=1;}
    148.          //Check if SA2 pressed, if pressed, edit hours
    149.          if(EditMode==1&&PORTB.B5==0&&SA2Press==0){SA2Press=1; Delay();};
    150.          if(EditMode==1&&PORTB.B5==1&&SA2Press==1)
    151.              {SA2Press=0; Delay();
    152.              if(WhatShow==0){if(Clock<1380){Clock=Clock+60;}else{Clock=Clock-1380;};}
    153.              else if(WhatShow==1){if(T1on<1380){T1on=T1on+60;}else{T1on=T1on-1380;};}
    154.              else if(WhatShow==2){if(T1off<1380){T1off=T1off+60;}else{T1off=T1off-1380;};}
    155.              else if(WhatShow==3){if(T2on<1380){T2on=T2on+60;}else{T2on=T2on-1380;};}
    156.              else if(WhatShow==4){if(T2off<1380){T2off=T2off+60;}else{T2off=T2off-1380;};}
    157.              }
    158.          //Check if SA3 pressed, if pressed, edit minutes
    159.          if(EditMode==1&&PORTB.B6==0&&SA3Press==0){SA3Press=1; Delay();};
    160.          if(EditMode==1&&PORTB.B6==1&&SA3Press==1)
    161.              {SA3Press=0; Delay();
    162.              if(WhatShow==0){if(Clock%60<59){Clock=Clock+1;}else{Clock=Clock-59;};}
    163.              else if(WhatShow==1){if(T1on%60<59){T1on=T1on+1;}else{T1on=T1on-59;};}
    164.              else if(WhatShow==2){if(T1off%60<59){T1off=T1off+1;}else{T1off=T1off-59;};}
    165.              else if(WhatShow==3){if(T2on%60<59){T2on=T2on+1;}else{T2on=T2on-59;};}
    166.              else if(WhatShow==4){if(T2off%60<59){T2off=T2off+1;}else{T2off=T2off-59;};}
    167.              }
    168.  
    169.          //Check if SA1 pressed, if pressed, escape edit mode
    170.          if(EditMode==1&&PORTB.B4==0&&SA1Press==0){SA1Press=1; Delay();};
    171.          if(PORTB.B4==1&&SA1Press==1){SA1Press=0; Delay(); EditMode=0;}
    172.  
    173.          //enable edit mode
    174.          if(EditMode==1){INTCON.T0IE=1;if(Whatshow==0){PIE1.TMR1IE=0;HG2DpToggle=1;}}
    175.          //disable edit mode
    176.          if(EditMode==0){PIE1.TMR1IE=1; INTCON.T0IE=0;}
    177.         }
    178.       }
     
    Last edited: Oct 12, 2010
  3. Markd77

    Senior Member

    Sep 7, 2009
    2,803
    594
    Is it on breadboard? There are lots of stray capacitances and inductances which can wreck crystal accuaracy.
    It's quite likely it will work properly when on a proper PCB.
     
  4. ecka333

    Thread Starter Active Member

    Oct 1, 2009
    76
    0
    No, all parts is on pcb, which i designed myself.
     
  5. ecka333

    Thread Starter Active Member

    Oct 1, 2009
    76
    0
    Now i think that problem is with part of the code, which is incrementing seconds and minutes.
     
  6. Markd77

    Senior Member

    Sep 7, 2009
    2,803
    594
    Something to try would be to reduce the amount of code inside the interrupt. Unless C does something clever it can be possible to miss interrupts if you spend too much time in there.
    However I would have guessed that would make the clock run slow not fast.......
     
  7. ecka333

    Thread Starter Active Member

    Oct 1, 2009
    76
    0
    One interesting thing: clock is going normally until one minute. After one minute it starts run very fast, clock counts 60 seconds through 40-50 seconds interval of time, according good clock. Seems like Timer1 interrupt occurs not always exactly 1 second, sometimes less, sometimes exactly. Or interrupt flag is not cleared always after Timer1 interrupt. But when i look at the code, everything seems ok. Maybe this is problem with compiler?
     
  8. t06afre

    AAC Fanatic!

    May 11, 2009
    5,939
    1,222
    Read the datasheet with care. It may be as you say. Some flag need to be cleared. If you have a free pin on the cpu, and a scope. Toggle this pin each time you enter and leave the Timer1 ISR(If this is used as second counter). That will give you some clues. You must use a scope as the pin may switch to fast to be seen on a LED
     
  9. Markd77

    Senior Member

    Sep 7, 2009
    2,803
    594
    I don't know much about C (I should put that in my signature) so I can't really check the code well.
    It's possible that both interrupt flags are set, as they become set when the condition is true, regardless of if you are already in the interrupt.
    I find it's best to check for one type of interrupt, service it as quickly as possible, then exit the ISR. If the other interrupt is set then the ISR will immediately be triggered again. Checking for both kinds of interrupts can lead to ruin because you are servicing the event that caused the interrupt and also another one.
     
  10. Potato Pudding

    Well-Known Member

    Jun 11, 2010
    684
    92
    What you want to do is let it run as a counter and just keep reading the timer as often as possible and decoding the timer counts into a real time value. Interrupts shouldn't be required but they are normally used.

    I would suggest that you let a prescaler work for you and make the numbers smaller and easier to divide into seconds - and prevent the timer from overflowing more than you need to.

    You only need one timer. For other timezone clocks you are just going to change their base.

    Your clocks are normally all going to be running from a 32kilohertz crystal and that makes them theoretically accurate to less than a millisecond.

    You don't need that for only counting seconds. As long as you aren't going to introduce timing errors, slowing down the counter you actually read and convert to RTC so that it is closer to 1 Hz is a good start. Even better might have been to pick a device with native RTC hardware but if this is the learning exercise that it seems to be then that would be cheating. Using a Real Time Clock equipped device would make this much simpler.

    For now have you looked at Microchips application note AN1303? Even Microchip suggests just having an outside device send a Real time clock signal to their PIC over I2C so don't feel bad about having so much trouble.
    It could even be another PIC.

    Also look at this Video which might help.

    This can be done but it takes some work.
     
    Last edited: Oct 13, 2010
    ecka333 likes this.
  11. AlexR

    Well-Known Member

    Jan 16, 2008
    735
    54
    Your clock problems are obviously software related, crystals are simply not that erratic. The most probable cause would be a failure to clear one of the interrupt flags resulting in multiple interrupts for the same event but where the problem lies I've no idea. To put it brutally your code is very difficult to read, it has no structure, you need to make more use of functions and less use of nested "if" statements.
    The ISR is particularly bad. The whole idea of servicing an interrupt is to do it as fast as you can then get out so the next interrupt can occur. If an event triggers an interrupt that requires extensive processing then set a flag in the ISR, exit the ISR and do the processing in the main loop.
    Also when you are looking for the interrupt source don't over-specify. For example, in your ISR code you have statements such as
    Code ( (Unknown Language)):
    1. //interrupt from Timer1 - 1 sec (Seconds counter)
    2.       if(PIR1.TMR1IF==1&&PIE1.TMR1IE==1){.......
    In other words is timer1 overflow interrupt flag is set and TMR1 interrupts are enabled do something. But why are you worried about TMR1 interrupts are enabled? If the an interrupt has occurred and the TMR1F flag is set then TMR1F flag must be cleared regardless of anything else.

    The whole ISR could be re-written as
    Code ( (Unknown Language)):
    1. void interrupt()
    2. {
    3.     //interrupt from Timer0 -  0.125sec(led blinker in Edit mode)
    4.     if(INTCON.T0IF)
    5.     {
    6.         t0_isr();
    7.         INTCON.T0IF=0;
    8.     }
    9.    
    10.     //interrupt from Timer1 - 1 sec (Seconds counter)
    11.      else if(PIR1.TMR1IF)
    12.     {
    13.         t1_isr();
    14.         PIR1.TMR1IF=0;
    15.     }
    16.        
    17.      //interrupt from Timer2 - 0.00341797 sec (Display multiplexing)
    18.     else if(TMR2IF)
    19.     {
    20.         t2_isr();
    21.         PIR1.TMR2IF=0;    
    22.      }
    23. }    
    24.  
    Which is much easier to read and less likely to result in errors through failure to clear interrupt flags. All the real work will be done in the new functions t?_isr().

    Your display routines are very cumbersome and needlessly complicated. Also none of the display work should be done inside the ISR. All that the ISR should do update time and display counters and set flags to tell the main loop that it's time for a display update. The actual selection of LED segments would be better done using an array rather than 10 functions all performing the same task (ie writing a byte to a portB). eg.
    Code ( (Unknown Language)):
    1. char led_segment[] = {0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F};
    2.  
    3. //Then for example to bring up the pattern for Segment2 all you need write is
    4.  
    5. portB = led_segment[Segment2];
     
  12. Markd77

    Senior Member

    Sep 7, 2009
    2,803
    594
    A possibly useful thing would be to turn timer1 off, rather than just disabing the interrupt. That way, any time TMR1IF is set you know it's needed. I don't think you can turn timer0 off unfortunately.
     
  13. ecka333

    Thread Starter Active Member

    Oct 1, 2009
    76
    0
    Thank you all for answers. I found a clock inacurracy problem after some searching. My routine in the main function constantly was enabling TMR1 timer i.e. TMR1 enable bit was set to 1 time after time, even if this bit was set to 1 already. As i puzzled out, TMR1 enable bit setting to 1, if timer is already running, causes timer to restart at zero or similarly.
     
  14. Potato Pudding

    Well-Known Member

    Jun 11, 2010
    684
    92
    Simple enough to put a config inside the main loop and cause resets like that. Amazing how often those types of things can pop up.

    Let us know if you have any other problems - and how accurate your clock is. Your display is working now?

    So many people are convinced that the interrupts need to shrink, but when you have put that much work into your code I would want you to test it and see if there are any more problems with the code as it is.

    I expect there will be but they will probably be about 1% or less. So you might miss 15 minutes a day which is not bad for your first clock attempt.
     
  15. ecka333

    Thread Starter Active Member

    Oct 1, 2009
    76
    0
    Now i connected 32,768kHz crystal to Timer1 module T1OSO and T1OSI pins. I tried to configure timer to get 1 sec interrupts, but insted o that i get exactly 2 sec interrupts. I suspect, that compiler cant write TMR1H and TMR1L registers. I tried to change these registers values, but interrupt occured exactly after 2 sec, regardless TMR1H and TMR1L values. Maybe something is wrong with the code? Microcontroller - PIC16F873.
    Code ( (Unknown Language)):
    1. // Timer1 initialisation (Seconds counter) Period = 2 sec, Quartz 32768Hz
    2.         T1CON.T1OSCEN = 1;       // Timer1 Oscillator enable
    3.         T1CON.TMR1CS = 1;        // Timer1 Clock Source Select bit - external clock
    4.         T1CON.T1SYNC = 1;        // Do not synchronize external clock input
    5.         TMR1H = 0;               // preset for timer1 MSB register
    6.         TMR1L = 0;               // preset for timer1 LSB register
    7.         T1CON.T1CKPS1 = 0;       // Prescaler= 1
    8.         T1CON.T1CKPS0 = 0;
    9.         PIR1.TMR1IF = 0;         //clear TMR1 interrupt flag
    10.         PIE1.TMR1IE=1;           //TMR1 interrupt enable
    11.         T1CON.TMR1ON = 1;        // enable timer
     
  16. t06afre

    AAC Fanatic!

    May 11, 2009
    5,939
    1,222
    TMR1 with external osc. at 32.768KHz generates overflow interrupt every 2 seconds. If we set TMR1 to start at 0x8000 (32768), the TMR1 will overflow every 1 second. Setting TMR1 to 0x8000 requires only 0x80 to be written to TMR1H in your ISR. This Does not affect the clock accuracy. Given that TMR1H is set in about 7.7 msesond after TMR1 interrupt. 7.7 msecond is rough calculated about 7700 machine code instructions with a 4 MHz clock frequency. Any setting of TMR1L will affect the accuracy, as it will be updated during your time in the ISR. Also include this as it is good reference but perhaps not in this project
    http://ww1.microchip.com/downloads/en/DeviceDoc/01146B.pdf
     
    Last edited: Oct 27, 2010
  17. ecka333

    Thread Starter Active Member

    Oct 1, 2009
    76
    0
    Ok, i understand what you say, t06afre. But i said, that if write to TMR1h register any value 0 or 255 gives absolutely no result. So, if i write
    Code ( (Unknown Language)):
    1. // Timer1 initialisation (Seconds counter) Period = 2 sec, Quartz 32768Hz
    2.         T1CON.T1OSCEN = 1;       // Timer1 Oscillator enable
    3.         T1CON.TMR1CS = 1;        // Timer1 Clock Source Select bit - external clock
    4.         T1CON.T1SYNC = 1;        // Do not synchronize external clock input
    5.         TMR1H = 0b10000000;               // preset for timer1 MSB register
    6.         TMR1L = 0;               // preset for timer1 LSB register
    7.         T1CON.T1CKPS1 = 0;       // Prescaler= 1
    8.         T1CON.T1CKPS0 = 0;
    9.         PIR1.TMR1IF = 0;         //clear TMR1 interrupt flag
    10.         PIE1.TMR1IE=1;           //TMR1 interrupt enable
    11.         T1CON.TMR1ON = 1;        // enable timer
    i will get interrupt every second, am i right?
     
    Last edited: Oct 27, 2010
  18. t06afre

    AAC Fanatic!

    May 11, 2009
    5,939
    1,222
    Timer1 do not have any preset value. The TMR1 Register pair (TMR1H:TMR1L) increments from 0000h to FFFFh and rolls over to 0000h. So whatever you write to the TMR1 Register pair in the Timer1 initialisation function will only have effect once. But if you update TMR1H in your ISR it should work.
     
  19. ecka333

    Thread Starter Active Member

    Oct 1, 2009
    76
    0
    I dont understand: if i wrote something to TMR1H register, will this register resets on interrupt to 0b00000000? I thought, that if i once wrote particulal value to register, this value stays there till the POR or BOR?
     
  20. Markd77

    Senior Member

    Sep 7, 2009
    2,803
    594
    Because it is a timer it is being incremented all the time. When it rolls over to zero that causes the interrupt, not the other way round.
     
Loading...