Simple PIC help!!! - Page 1
Forum section: electronics / beginners

author: Christopher
author_rank: Frequent Contributor
timestamp: March 20, 2013, 05:04:36 pm
content: Hi All,trying to get Timer1 working with a 32.678kHz crystal. Using a PIC16LF1937 on a board which one of my co workers has used before.Crystal is on the T1OSCIN and OUT pins.What happens: RE2 goes high for 0.5sec and goes low again as expected in a loop. RD1 goes high and stays high....Code:Code:#include <pic.h>#include <xc.h>#include <stdio.h>#include <stdlib.h>//#define _XTAL_FREQ 4000000UL#define _XTAL_FREQ 32000000UL//#define _XTAL_FREQ 4000000#pragma config CPD=OFF, BOREN=OFF, IESO=OFF, FOSC=INTOSC, FCMEN=OFF, MCLRE=OFF, WDTE=OFF, CP=OFF, PWRTE=ON, CLKOUTEN=OFF, LVP=ON, PLLEN=ONunsigned int wat = 0;int main(void) {TRISD1 = 0;TRISE2 = 0;//internal 32kHz clockOSCCONbits.SCS = 0b00;OSCCONbits.IRCF = 0b1110;OSCCONbits.SPLLEN = 1;// configure Timer1T1CONbits.TMR1CS = 2; //clock source as 10, external crystalT1CONbits.T1OSCEN = 1; // enable external oscillatorT1CONbits.nT1SYNC = 0; // sync external clock with system clockT1CONbits.TMR1ON = 1; // enable Timer1// setup Timer1 interrupt flags to defaultPIR1bits.TMR1IF = 0; //Timer1 Overflow Interrupt not pendingPIE1bits.TMR1IE = 1; //Timer1 Overflow interrupt enableINTCONbits.PEIE = 1; // peripheral interrupt enableei();// main loopwhile (1) {PORTEbits.RE2 = 0;__delay_ms(500);PORTEbits.RE2 = 1;__delay_ms(500);}return 0;}void interrupt isr(){if (TMR1IF && TMR1IE) {TMR1IF = 0; // clear flagINTCONbits.GIE = 1;wat++;if (wat > 1) {PORTDbits.RD1 = ~PORTDbits.RD1;wat = 0;}return;}}Any help would be appreciated, Ive been trying to get this going all day with help from the datasheet...

author: Rufus
author_rank: Super Contributor
timestamp: March 20, 2013, 05:51:03 pm
content: You haven't configured the ANSEL registers so neither pin should do anything.Also you should write/modify port LAT registers to avoid read/modify/write issues (probably doesn't matter here).You could check the 32kHz crystal is actually oscillating.

author: Christopher
author_rank: Frequent Contributor
timestamp: March 20, 2013, 06:05:27 pm
content: Quote from: Rufus on March 20, 2013, 05:51:03 pmSet the ANSEL regs to 0x00 and now works!!! Thanks!But the LED i have connected to RD1 oscillates about 0.25 Hz, shouldnt it be oscillating at 32kHz?

author: Rufus
author_rank: Super Contributor
timestamp: March 20, 2013, 06:14:51 pm
content: Quote from: Christopher on March 20, 2013, 06:05:27 pmTimer 1 is a 16 bit up counter which interrupts on overflow so it will interrupt every 2 seconds and you toggle the LED every other interrupt.The timer 1 hardware isn't very friendly for doing anything faster than 0.5Hz if you want to maintain an accurate total count of 32kHz cycles.

author: Christopher
author_rank: Frequent Contributor
timestamp: March 20, 2013, 06:26:42 pm
content: Ah right, I wanted to use this timer for a second timer. Not handy if its running at 0.5 Hz? I now have a 2 second timer.EDIT: Had a brainwave and used the prescaler (T1CKPS) to do this, but unfortunately only makes it slower and not speeds up like I thought it would. Haha.

author: Rufus
author_rank: Super Contributor
timestamp: March 20, 2013, 06:54:38 pm
content: Quote from: Christopher on March 20, 2013, 06:26:42 pmIf you preset the timer registers to -32k in the interrupt handler it will overflow 1 second later.However, if you can't afford to miss a clock cycle you need to take the interrupt and preset the timer before the next 32kHz clock. Being able to do that depends on how fast the PIC is running and what else it is doing. Using the prescaler could give you more time or you could spin and wait for a clock in the interrupt handler to give you enough time for the timer register loading. Presetting the timer with its current value -32k would mean you have relatively ages to get round to servicing the interrupt.