Pic18f45k20 Timer0 help

Thread Starter

alexm1992

Joined Dec 19, 2013
7
Hi, I have an external 32khz crystal hooked up to my pic18f45k20. I am trying to get this timer to toggle an output once per day (see code annotations). Currently it is not working and im struggling. The code toggles correctly but only once when the switch is first pressed. From then on the timer is having no effect?

The code:

//******************************************************************************
//Software License Agreement
//
//The software supplied herewith by Microchip Technology
//Incorporated (the "Company") is intended and supplied to you, the
//Company’s customer, for use solely and exclusively on Microchip
//products. The software is owned by the Company and/or its supplier,
//and is protected under applicable copyright laws. All rights are
//reserved. Any use in violation of the foregoing restrictions may
//subject the user to criminal sanctions under applicable laws, as
//well as to civil liability for the breach of the terms and
//conditions of this license.
//
//THIS SOFTWARE IS PROVIDED IN AN "AS IS" CONDITION. NO WARRANTIES,
//WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT NOT LIMITED
//TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
//PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. THE COMPANY SHALL NOT,
//IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL OR
//CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
// *******************************************************************
// PIC18F46K20 Starter Kit Lesson 1 - Hello LED
//
// This lesson turns on LED 7 on the demo board.
//
// *******************************************************************
// * See included documentation for Lesson instructions *
// *******************************************************************

/** C O N F I G U R A T I O N B I T S ******************************/

#pragma config FOSC = LP, FCMEN = OFF, IESO = OFF // CONFIG1H
#pragma config PWRT = OFF, BOREN = SBORDIS, BORV = 30 // CONFIG2L
#pragma config WDTEN = OFF, WDTPS = 32768 // CONFIG2H
#pragma config MCLRE = OFF, LPT1OSC = OFF, PBADEN = ON, CCP2MX = PORTC // CONFIG3H
#pragma config STVREN = ON, LVP = OFF, XINST = OFF // CONFIG4L
#pragma config CP0 = OFF, CP1 = OFF, CP2 = OFF, CP3 = OFF // CONFIG5L
#pragma config CPB = OFF, CPD = OFF // CONFIG5H
#pragma config WRT0 = OFF, WRT1 = OFF, WRT2 = OFF, WRT3 = OFF // CONFIG6L
#pragma config WRTB = OFF, WRTC = OFF, WRTD = OFF // CONFIG6H
#pragma config EBTR0 = OFF, EBTR1 = OFF, EBTR2 = OFF, EBTR3 = OFF // CONFIG7L
#pragma config EBTRB = OFF // CONFIG7H


/** I N C L U D E S **************************************************/
#include "p18f45k20.h"
#include "delay.h"
#include "delays.h"
#include "switch header.h"

/** D E C L A R A T I O N S ******************************************/



void Timer0_Init(void) //Timer is initiated

{
T0CONbits.T0CS = 0; // internal instruction cycle clock set
T0CONbits.T08BIT = 0; // 16bit operation - reduces the need to use prescale
INTCONbits.TMR0IF = 0; // clear roll-over interrupt flag
TMR0H = 0xE0; // set to 57535 dec see calculation below
TMR0L = 0xBF;
/*
Fosc = 32KHz
Fcycle = Fosc/4 = 32KHz/4 = 8KHz
Tcycle = 1/Fcycle = 125us
Cycle count (no prescaler) for one second = 1s/125us = 8000
16bit overflow value = 0xFFFF (65535 in dec)

Calculate TMR0 (H&L) values:

65535-8000 = 57535 (0xE0BF)

*/
T0CONbits.TMR0ON = 1; // start timer


}



void main (void)
{

int Day =0; // number of days
int Counter =0; // counter
int Sec = 0; // seconds passed


PORTA = 0x03; //Preset RA1,RA0 to 1
TRISA = 0x00;



INTCON2bits.RBPU = 0; // enable PORTB internal pullups
WPUBbits.WPUB0 = 1; // enable pull up on RB0
ANSELH = 0x00; // AN8-12 are digital inputs (AN12 on RB0)
TRISBbits.TRISB0 = 1; // PORTB bit 0 (connected to switch) is input (1)

// Init Timer0
Timer0_Init();



while (1)
{


if(INTCONbits.TMR0IF ==1) // when overflow occurs increment sec integer
{
Sec ++;
INTCONbits.TMR0IF = 0; // clear roll-over interrupt flag
TMR0H = 0xE0; //reset back to seed value
TMR0L = 0xBF;

}

if (Sec==1) // use 30 sec to represent 1 day for now! change after
{
Day ++;
Sec = 0;
}




while (Switch_Pin == 0) // Weak pull up used so switch is high when not pushed!

{



while (Counter<=Day) // This only executes once per
{
LATAbits.LATA0 = 0; //right LED
LATAbits.LATA1 = 1; //left LED

delay100us(); // this is dependent on the clock cycle not actully 100us but it works ok for now!!!!



LATAbits.LATA0 = 0;
LATAbits.LATA1 = 0;

Counter++;

}

}

}
}
 

spinnaker

Joined Oct 29, 2009
7,830
Why are you testing and clearing the interrupt flag in the main loop? That should be done in the interrupt routine.

What have you done to debug your code?

Pleasee post code inside code tags.

This belongs in the embedded forum.
 

THE_RB

Joined Feb 11, 2008
5,438
That is some nasty code to make seconds from a 32 kHz xtal!

A 32768 Hz xtal is binary divisible, so you just free-run the 16bit timer and bit 15 of the timer will be set (will toggle) exactly every second. That is how you detect seconds, not by loading the timer with some value every time. :)
 

Thread Starter

alexm1992

Joined Dec 19, 2013
7
Thanks for the reply. I was told to clear and reset the interrupt flag in the main loop by a guy I know! This is all self taught for me, and my first project so sorry if it is ugly code :)

This may be a simple question but what do you mean by 'free-run' the 16bit timer. Does this mean to pre load a value but never reset? In other words do I just let the timer keep overflowing and simply track its overflow (intern counting seconds)?


Thank you both!
 

Thread Starter

alexm1992

Joined Dec 19, 2013
7
Thanks, I am using the PIC18f45k20 t06afre, I think this is for the PIC16C924?

I have read through the data sheet for the PIC18F and tried to understand it the best I can (not very well!) ;)
 

t06afre

Joined May 11, 2009
5,934
Thanks, I am using the PIC18f45k20 t06afre, I think this is for the PIC16C924?

I have read through the data sheet for the PIC18F and tried to understand it the best I can (not very well!) ;)
Even if it is for 16F or 16C chip the method in the big lines is the same for a 18F series chip. So the documents I posted is still valid for your chip. It may be some minor differences on register level. Like how to enable interrupt and so on
 

ErnieM

Joined Apr 24, 2011
8,377
After spending 30 secs of research (meaning I am taking comments by other posters at face value) you can set up the prescaler on Timer 0 so it has a roll over at exact 1 second intervals.

Also, there is simply no compelling reason to check the flag inside an interrupt routine. Polling that flag (reading the bit in a loop as you do) is another way to do it, has the advantage of NOT needing an interrupt routine. It has the disadvantage of not being as precise at the interrupt routine, but here you're talking about microseconds in an entire day (so it is insignificant).

Sure you can have a variable count 2 second intervals so it increments minutes after 30, but I prefer to count seconds... just simpler, expected, and less prone to errors, and don't forget you just may come back to this projects 2 weeks or 2 years from now and forget your counting 2 second chunks not one second chunks... make it easy for your future self to follow.
 
Top