0
\$\begingroup\$

I'm attempting to blink an LED with the Timer1 overflow interrupt on a PIC12F629, but all I get is a constant LOW value on the GPIO pin. I'm using a 32.768kHz crystal oscillator with 82pF load caps and a 0.1uF filter cap across Vdd and Vss. The GPIO pin for the LED is set to sink (anode tied high, cathode to GPIO through resistor).

I had it all working when using the internal oscillator (4MHz) but haven't had any luck while using the LP crystal. I'm pretty sure it's not a hardware issue since I was able to get it to work (with the LP crystal setup) using MPLAB's built-in __delay_ms() function. I also checked the LED GPIO pin with a logic analyzer to make sure the LED wasn't just blinking faster than I could perceive. Here are my code snippets from several .h and .c files:

#include <xc.h>

// CONFIG register
#pragma config WDTE = OFF     // turn off WDT
#pragma config FOSC = 0b000   // LP crystal

// Set up LP crystal GPIO
TRISIObits.TRISIO4 = 1;
TRISIObits.TRISIO5 = 1;
WPUbits.WPU4 = 0;
WPUbits.WPU5 = 0;

// Set up interrupts
TMR1H = 0;
TMR1L = 0;
PIR1bits.TMR1IF = 0;
PIE1bits.TMR1IE = 1;
INTCONbits.PEIE = 1;
INTCONbits.GIE = 1;

// Set up Timer1
T1CONbits.TMR1GE = 0;
T1CONbits.T1CKPS = 0b00;   // prescaler = 1
T1CONbits.T1OSCEN = 0;
T1CONbits.nT1SYNC = 0;
T1CONbits.TMR1CS = 1;
T1CONbits.TMR1ON = 1;

// Set up GP2 (LED)
TRISIObits.TRISIO2 = 0;
WPUbits.WPU2 = 0;
GPIObits.GP2 = 0;

// Interrupt service routine
void interrupt isr(void)
{
    if(PIR1bits.TMR1IF)
    {
        PIR1bits.TMR1IF = 0;
        GPIObits.GP2 ^= 1;
    }
}

From the datasheet, here's Timer1's signal flow:

Timer1 signal flow

From my calculations, with prescaler set to 1, using a 16-bit timer and a 32.768kHz crystal the timer should overflow every 2 seconds. Any ideas where I'm going wrong?

EDIT: Uh oh, there's an errata for Timer1 :(

EDIT2: Fixed the math in the above paragraph (forgot to invert the 0.5Hz to get 2 seconds).

\$\endgroup\$
  • \$\begingroup\$ 99% of my PIC problems come from choice of oscillator capacitors. I suggest getting a selection ranging from 3.3pf to 33pf. 82pf sounds way too high. Also you might not need any - the leads and tracks can be enough by themselves. Also, be sure to have a fast capacitor on the supply rails close to the PIC. 32khz crystals with PICs can be fussy, even program changes can affect signals. BTW Your program is incomplete AFAIK - I suggest a condensed program to focus solving this issue \$\endgroup\$ – CL22 Apr 20 '17 at 1:21
  • \$\begingroup\$ @Jodes yeah I've tried no caps, 10pF, and 22pF to no avail. I'll keep trying other combinations, though, and maybe a new crystal. Code-wise these are just snippets -- MPLAB templates fragment the heck out of things. I can put more lines up there if they're relevant. \$\endgroup\$ – calcium3000 Apr 20 '17 at 1:25
1
\$\begingroup\$

Figured it out! I used the system clock (F_osc/4 in the block diagram) instead of the LP oscillator itself since I set the system frequency to 32.768kHz:

T1CONbits.TMR1CS = 0;   // clock source = F_osc/4

I'm not sure if it's a noob mistake to use the LP oscillator for Timer1 when the system clock is also using it, or if I made some other incorrect code/assumption. I didn't get the fix in the errata (EXAMPLE 1) to work, either, so I'm not claiming complete victory. But it works!

EDIT: and to quell some anxiety I used 22pF caps on the crystal, too.

\$\endgroup\$
0
\$\begingroup\$

82 pF on a 33 kHz crystal is waaaay too much. Read the datasheet of the crystal.

\$\endgroup\$
  • \$\begingroup\$ I figured -- I just wanted to make sure the crystal would stabilize. Like I told Jodes, I tried with none, 10pF, and 22pF as well. It's just odd to me that it would work using MPLAB's built-in functions, but not Timer1. \$\endgroup\$ – calcium3000 Apr 20 '17 at 18:43

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.