1
votes

Initially I had Timer0 working fine during the run mode. The only problem is when the device goes to sleep mode, Timer0 stops counting up until awaken. In the datasheet it says to use Timer1 to be able to monitor time during sleep mode. I modified timer0 existing code to timer1 new configurations, the other code is pretty much the same. However, there is something I might have missed that is different about timer1 than timer0, since the timer1 is not counting up at all. The PIC I'm using is PIC18F87J11 with MPLAB C18.

I will share the code that seems relevant and upon request I will add more as needed.

Timer0 Snippet Code ( From Header File)

#define TMR_IF          INTCONbits.TMR0IF
#define TMR_IE          INTCONbits.TMR0IE
#define TMR_IP          INTCON2bits.TMR0IP
#define TMR_ON          T0CONbits.TMR0ON
#define TMR_CON         T0CON
#define TMR_L           TMR0L
#define TMR_H           TMR0H 

Timer0 (From C File)

TMR_CON = 0b00000000 | CLOCK_DIVIDER_SETTING;
TMR_IP = 1;
TMR_IF = 0;
TMR_IE = 1;
TMR_ON = 1;

Timer0 (Where I increment the time)

if(TMR_IF)
        {
        printf("\r\n Passed here");
        timer_counter_high++; 
        }

Output: Passed here


Timer1 Snippet Code ( From Header File)

#define TMR_IF          PIR1bits.TMR1IF
#define TMR_IE          PIE1bits.TMR1IE
#define TMR_IP          IPR1bits.TMR1IP
#define TMR_ON          T1CONbits.TMR1ON
#define TMR_CON         T1CON
#define TMR_L           TMR1L
#define TMR_H           TMR1H

Timer1 (From C File)

TMR_CON = 0b11101101 | CLOCK_DIVIDER_SETTING;
TMR_IP = 1;
TMR_IF = 0;
TMR_IE = 1;
TMR_ON = 1;

Timer1 (Where I increment the time)

   if(TMR_IF)
        {
        printf("\r\n Passed here");
        timer_counter_high++; 
        }
        else
        {
        printf("\r\n Did not come through");
        }

Output: Did not come through

Edit:Added the CLOCK_DIVIDER_SETTING code as requested. This is being used for timer0 and timer1

#elif(CLOCK_FREQ <= 8000000)
        #define CLOCK_DIVIDER 32
        #define CLOCK_DIVIDER_SETTING 0x04
        #define SYMBOL_TO_TICK_RATE 8000000

I still did not put the device on sleep mode to test timer1 in that condition, first I have to figure out why timer1 is not counting up during the run mode. I will appreciate any help or ideas related to my problem, Thanks!

Edit 2: Some questions that I like to be answered

Q1: Can Timer1 still be used with the internal oscillator just like timer0?

Q2: How do you calculate the correct CLOCK_DIVIDER_SETTING for T1CON ? (Do I need it if T1SYNC is set and the prescaler?)

1
Do I need external crystal to have timer1 working or what's going on?Ammar
Belongs on electronics.stackexchange.comJason S
What are you using for CLOCK_DIVIDER_SETTING in each case?Simon Jenkins
@SimonJenkins, I updated the thread.Ammar
I still hope I can get some answers, I need to head in the right direction. I'm lost!Ammar

1 Answers

2
votes

According to PIC18F87J11 FAMILY datashet, you need to add external crystal on T1OSO and T1OSI pins if you are setting Timer1 clock derived from Timer1 oscilator (which you do by setting T1RUN bit in T1CON register).

Also note, that although assigning CLOCK_DIVIDER_SETTING to T0CON register correctly sets clock prescaler, it wrong to assign the same CLOCK_DIVIDER_SETTING to T1CON register becouse of different bit locations (in this case you are effectively setting bit T1SYNC, which you already set) and different size of prescaler.

I also hope that you are setting registers TMR1H, TMR1L, TMR0L and TMR0H somewhere in code before enabling timers.

EDIT Added answers to additional questions.

1: Yes, Timer1 have two sources of clock - external oscillator and internal clock (Fosc/4). To enable internal clock you have to clear bit TMR1CS in T1CON register.

Please note, that during sleep all clocks are disabled except Timer1 oscillator and INTRC (31 kHz clock, which cannot be used by Timer1), so you can measure time with Timer1 during sleep only if Timer1 is clocked by external oscillator.

2: T1CKPS bits are bits 4 and 5 in T1CON register, so simply shifting clock divider setting by four bits should be fine. Remember, that Timer1 clock prescaler is only two bits wide, and it can divide clock by maximum factor of 8.

T1SYNC bit is ignored if you use internal clock. If you plan using external oscillator with Timer1 during sleep mode, you should set T1SYNC to disable synchronisation of external clock input (during sleep external clock cannot be synchronised becouse there is no internal clock to be synchronised to and Timer1 will not count).

Configuration of Timer1 should look something like this

#define CLOCK_DIVIDER_SETTING_T1 0x03 // divide clock by 8 (T1_clock/8)

// RD16 cleared
// T1OSCEN set - Timer1 oscillator is enabled
// T1SYNC set - Does not synchronize external clock input
// TMR1CS set - External clock from the RC0/T1OSO/T13CKI pin (on the rising edge)
// TMR1ON cleared - wait with enabling Timer1 until everything is configured
TMR_CON = 0b00001110 | (CLOCK_DIVIDER_SETTING_T1<<4);
TMR_IP = 1;
TMR_IF = 0;
TMR_IE = 1;
TMR_ON = 1;

If you want to use internal clock, then T1_clock = Fosc/4.

If you use internal oscillator as system clock, then you can change postscaler of system clock by writing to IRCF bits in OSCCON register, but this will affect speed of whole microcontroller.

The default setting is 4 MHz, so T1_clock would be 1 MHz, and after T1 prescaler it would be 125 kHz.