CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

TIMER1 1sec int external 32.768 Real-Time Clock

 
Post new topic   Reply to topic    CCS Forum Index -> Code Library
View previous topic :: View next topic  
Author Message
E_KARVELAs



Joined: 14 Feb 2007
Posts: 46
Location: Greece & Cyprus

View user's profile Send private message

TIMER1 1sec int external 32.768 Real-Time Clock
PostPosted: Wed Apr 16, 2008 10:12 am     Reply with quote

HI
I'm posting this code as help for people who need some help starting with Real-Time Clock. Counts seconds, minutes using interrupt TIMER1 with External asynchronous crystal 32.768Khz and 33pF caps on Pins between pins T1OSI (input) and T1OSO (amplifier output). (Look at data sheets).

I had an issue of myself with this code, I couldn't have exactly 1sec interrupt. I was always 1-2 sec forward with my (casio) watch. Searching the forum didn't find exactly where was the issue, until I looked at the datasheet picture and found that the oscillator circuit, shown in Figure 12-3, should be
located as close as possible to the microcontroller, grounded with Vss <<LOOK AT THE PICTURE>> so i give a try and finallly noticed that there was "NO MORE ERROR". Cool
This code uses internal 8MHZ crystal with 32.768 KHz crystal for RTC, flexy_lcd.c driver for 2x16 LCD can be found in the forum.




Code:

#include <18F2550.h>
#device ICD=TRUE

#FUSES NOWDT                    //No Watch Dog Timer
#FUSES WDT128                   //Watch Dog Timer uses 1:128 Postscale
#FUSES INTRC_IO                 //Internal RC Osc, no CLKOUT
#FUSES NOPROTECT                //Code not protected from reading
#FUSES NOBROWNOUT               //No brownout reset
#FUSES BORV20                   //Brownout reset at 2.0V
#FUSES PUT                      //Power Up Timer
#FUSES NOCPD                    //No EE protection
#FUSES STVREN                   //Stack full/underflow will cause reset
#FUSES NODEBUG                  //No Debug mode for ICD
#FUSES NOLVP                    //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOWRT                    //Program memory not write protected
#FUSES NOWRTD                   //Data EEPROM not write protected
#FUSES NOIESO                     //NO Internal External Switch Over mode enabled
#FUSES FCMEN                    //Fail-safe clock monitor enabled
#FUSES NOPBADEN                 //NO PORTB pins are configured as digital I/O on RESET
#FUSES NOWRTC                   //configuration not registers write protected
#FUSES NOWRTB                   //Boot block not write protected
#FUSES NOEBTR                   //Memory not protected from table reads
#FUSES NOEBTRB                  //Boot block not protected from table reads
#FUSES NOCPB                    //No Boot Block code protection
#FUSES MCLR                     //Master Clear pin enabled
#FUSES NOLPT1OSC                //Timer1 configured for higher power operation
#FUSES NOXINST                  //Extended set extension and Indexed Addressing mode disabled (Legacy mode)
#FUSES PLL12                    //Divide By 12(48MHz oscillator input)
#FUSES CPUDIV1 
#FUSES NOUSBDIV                 //NO USB clock source comes from primary oscillator
#FUSES NOVREGEN                 //NO USB voltage regulator disabled


#use delay(clock=8000000)
#include <flexy_lcd.c>

int sec=0;
int min=0;
int hour=0;
int1 flg=false;


void main(){   
   enable_interrupts(INT_TIMER1);
   setup_timer_1(T1_EXTERNAL|T1_DIV_BY_1|T1_CLK_OUT);
   enable_interrupts(GLOBAL);
   lcd_init();
   setup_oscillator(OSC_8MHZ|OSC_INTRC|OSC_PLL_ON); //<-- internal 8MHZ crystal with PLL ON 8X4=32MHZ                     
 
 for(;;){
 
 if(flg==true){
 
   set_timer1(32768);                //2^16=  65536/2 = 32768 * 1/32.768Hz <--- (1sec)                                           
   setup_timer_1(T1_EXTERNAL|T1_CLK_OUT);       //    external TIMER1 with
                                               //    32.768Khz ,clock out for oscillator,asynchronus mode
   
       if (++sec>59){
                       sec=0;
         if(++min>59){
                       min=0;
                       hour++;
        if(++hour>23){
                             
                     hour=0;
                             }
                     }
         }
                     
                     
    lcd_gotoxy(1,1);
 printf(lcd_putc"%02u:%02u:%02u  "hour,min,sec);
 flg=false;
 }
   
         }
           }
                   
#int_TIMER1
void  TIMER1_isr(void)
 {

   flg=true;

    }


_________________
---- GREECE ----
Neutone



Joined: 08 Sep 2003
Posts: 839
Location: Houston

View user's profile Send private message

PostPosted: Wed Apr 16, 2008 5:41 pm     Reply with quote

Use this as the interrupt. This uses 3 instructions that do the following.
1) Enable access to the individual bytes of the timer register
2) Add 32768 to timer1 by setting high bit or timer register
3) Disable access to the individual bytes of the timer register
Code:

#Byte TMR1H = 0xFCF
#Byte T1CON = 0xFCD
#int_TIMER1
void TIMER1_isr()
{  bit_clear(T1CON,7);
   Bit_Set(TMR1H,7);     
   Bit_Set(T1CON,7);     
   flg=true;
}

and remove this
Code:
set_timer1(32768);

This will have improved performance and accuracy. There will be no error introduced by setting the timer to 32768 after the timer has incremented to 3 or 4.
E_KARVELAs



Joined: 14 Feb 2007
Posts: 46
Location: Greece & Cyprus

View user's profile Send private message

Thanks goes to Neutone.
PostPosted: Thu Apr 17, 2008 8:48 am     Reply with quote

Code Now improved for more performance and accuracy Thanks to Neutone Smile


Code:

#include <18F2550.h>
#device ICD=TRUE

#FUSES NOWDT                    //No Watch Dog Timer
#FUSES WDT128                   //Watch Dog Timer uses 1:128 Postscale
#FUSES INTRC_IO                 //Internal RC Osc, no CLKOUT
#FUSES NOPROTECT                //Code not protected from reading
#FUSES NOBROWNOUT               //No brownout reset
#FUSES BORV20                   //Brownout reset at 2.0V
#FUSES PUT                      //Power Up Timer
#FUSES NOCPD                    //No EE protection
#FUSES STVREN                   //Stack full/underflow will cause reset
#FUSES NODEBUG                  //No Debug mode for ICD
#FUSES NOLVP                    //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOWRT                    //Program memory not write protected
#FUSES NOWRTD                   //Data EEPROM not write protected
#FUSES NOIESO                     //NO Internal External Switch Over mode enabled
#FUSES FCMEN                    //Fail-safe clock monitor enabled
#FUSES NOPBADEN                 //NO PORTB pins are configured as digital I/O on RESET
#FUSES NOWRTC                   //configuration not registers write protected
#FUSES NOWRTB                   //Boot block not write protected
#FUSES NOEBTR                   //Memory not protected from table reads
#FUSES NOEBTRB                  //Boot block not protected from table reads
#FUSES NOCPB                    //No Boot Block code protection
#FUSES MCLR                     //Master Clear pin enabled
#FUSES NOLPT1OSC                //Timer1 configured for higher power operation
#FUSES NOXINST                  //Extended set extension and Indexed Addressing mode disabled (Legacy mode)
#FUSES PLL12                    //Divide By 12(48MHz oscillator input)
#FUSES CPUDIV1 
#FUSES NOUSBDIV                 //NO USB clock source comes from primary oscillator
#FUSES NOVREGEN                 //NO USB voltage regulator disabled


#use delay(clock=8000000)
#include <flexy_lcd.c>

#Byte TMR1H = 0xFCF   // TIMER1 HIGH BYTE LOOK DATASHEET
#Byte T1CON = 0xFCD  //TIMER1 CONFIG REGISTER LOOK DATASHEET

int sec=0;
int min=0;
int hour=0;
int1 flg=false;


void main(){   
   enable_interrupts(INT_TIMER1);
   setup_timer_1(T1_EXTERNAL|T1_DIV_BY_1|T1_CLK_OUT);
   enable_interrupts(GLOBAL);
   lcd_init();
   setup_oscillator(OSC_8MHZ|OSC_INTRC|OSC_PLL_ON);
                                                  //<-- internal 8MHZ crystal with PLL ON 8X4=32MHZ                     
 
 for(;;){
 
 if(flg==true){                     
   setup_timer_1(T1_EXTERNAL|T1_CLK_OUT);       //    external TIMER1 with
                                               //    32.768Khz ,clock out for oscillator,asynchronus mode
   
       if (++sec>59){
                       sec=0;
         if(++min>59){
                       min=0;
                       hour++;
        if(++hour>23){
                             
                     hour=0;
                             }
                     }
         }
                     
                     
    lcd_gotoxy(1,1);
 printf(lcd_putc"%02u:%02u:%02u  "hour,min,sec);
 flg=false;
 }
   
         }
           }
                   
#int_TIMER1
void TIMER1_isr()    // 2^16=  65536/2 = 32768 * 1/32.768Hz <--- (1sec)                     
{

   bit_clear(T1CON,7);  //Enable access to the individual bytes of the timer register
   Bit_Set(TMR1H,7);   //Add 32768 to timer1 by setting high bit or timer register       
   Bit_Set(T1CON,7);   //Disable access to the individual bytes of the timer register
   
   flg=true;
}


_________________
---- GREECE ----
monkeyman



Joined: 05 Jun 2008
Posts: 18

View user's profile Send private message

PostPosted: Mon Sep 28, 2009 9:56 am     Reply with quote

good
but i think there is a problem with hours...
Code:

      if (++sec>59){
                       sec=0;
         if(++min>59){
                       min=0;
                       hour++;
        if(++hour>23){
                             
                     hour=0;
                             }
                     }
         }

the hours increment two time for one!
omarsito12



Joined: 02 Oct 2009
Posts: 6

View user's profile Send private message

Re: Thanks goes to Neutone.
PostPosted: Tue Dec 01, 2009 7:57 pm     Reply with quote

E_KARVELAs wrote:
Code Now improved for more performance and accuracy Thanks to Neutone Smile
Code:

#include <18F2550.h>
#device ICD=TRUE

#FUSES NOWDT                    //No Watch Dog Timer
#FUSES WDT128                   //Watch Dog Timer uses 1:128 Postscale
#FUSES INTRC_IO                 //Internal RC Osc, no CLKOUT
#FUSES NOPROTECT                //Code not protected from reading
#FUSES NOBROWNOUT               //No brownout reset
#FUSES BORV20                   //Brownout reset at 2.0V
#FUSES PUT                      //Power Up Timer
#FUSES NOCPD                    //No EE protection
#FUSES STVREN                   //Stack full/underflow will cause reset
#FUSES NODEBUG                  //No Debug mode for ICD
#FUSES NOLVP                    //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOWRT                    //Program memory not write protected
#FUSES NOWRTD                   //Data EEPROM not write protected
#FUSES NOIESO                     //NO Internal External Switch Over mode enabled
#FUSES FCMEN                    //Fail-safe clock monitor enabled
#FUSES NOPBADEN                 //NO PORTB pins are configured as digital I/O on RESET
#FUSES NOWRTC                   //configuration not registers write protected
#FUSES NOWRTB                   //Boot block not write protected
#FUSES NOEBTR                   //Memory not protected from table reads
#FUSES NOEBTRB                  //Boot block not protected from table reads
#FUSES NOCPB                    //No Boot Block code protection
#FUSES MCLR                     //Master Clear pin enabled
#FUSES NOLPT1OSC                //Timer1 configured for higher power operation
#FUSES NOXINST                  //Extended set extension and Indexed Addressing mode disabled (Legacy mode)
#FUSES PLL12                    //Divide By 12(48MHz oscillator input)
#FUSES CPUDIV1 
#FUSES NOUSBDIV                 //NO USB clock source comes from primary oscillator
#FUSES NOVREGEN                 //NO USB voltage regulator disabled

#use delay(clock=8000000)
#include <flexy_lcd.c>

#Byte TMR1H = 0xFCF   // TIMER1 HIGH BYTE LOOK DATASHEET
#Byte T1CON = 0xFCD  //TIMER1 CONFIG REGISTER LOOK DATASHEET

int sec=0;
int min=0;
int hour=0;
int1 flg=false;


void main(){   
   enable_interrupts(INT_TIMER1);
   setup_timer_1(T1_EXTERNAL|T1_DIV_BY_1|T1_CLK_OUT);
   enable_interrupts(GLOBAL);
   lcd_init();
   setup_oscillator(OSC_8MHZ|OSC_INTRC|OSC_PLL_ON);
                                                  //<-- internal 8MHZ crystal with PLL ON 8X4=32MHZ                     
 
 for(;;){
 
 if(flg==true){                     
   setup_timer_1(T1_EXTERNAL|T1_CLK_OUT);       //    external TIMER1 with
                                               //    32.768Khz ,clock out for oscillator,asynchronus mode
   
       if (++sec>59){
                       sec=0;
         if(++min>59){
                       min=0;
                       hour++;
        if(++hour>23){
                             
                     hour=0;
                             }
                     }
         }
                     
                     
    lcd_gotoxy(1,1);
 printf(lcd_putc"%02u:%02u:%02u  "hour,min,sec);
 flg=false;
 }
   
         }
           }
                   
#int_TIMER1
void TIMER1_isr()    // 2^16=  65536/2 = 32768 * 1/32.768Hz <--- (1sec)                     
{

   bit_clear(T1CON,7);  //Enable access to the individual bytes of the timer register
   Bit_Set(TMR1H,7);   //Add 32768 to timer1 by setting high bit or timer register       
   Bit_Set(T1CON,7);   //Disable access to the individual bytes of the timer register
   
   flg=true;
}



Listen, Hi, I tested this code with Proteus with the pic18f8720 and it doesn't work. What can I do? Please help me.
theLion



Joined: 11 Dec 2009
Posts: 1

View user's profile Send private message

Re: Thanks goes to Neutone.
PostPosted: Fri Dec 11, 2009 4:30 pm     Reply with quote

omarsito12 wrote:
Listen, Hi, I tested this code with Proteus with the pic18f8720 and it doesn't work. What can I do? Please help me.


I have tested this on Proteus and "no" it doesn't work.. when you simulate the external crystal. The code works - the problem is with Proteus.

You can get around this just by providing a 32768hz clock straight into T1OSI.
abbas14



Joined: 05 Sep 2015
Posts: 7

View user's profile Send private message

PostPosted: Wed Jun 15, 2016 4:34 am     Reply with quote

Neutone wrote:
Use this as the interrupt. This uses 3 instructions that do the following.
1) Enable access to the individual bytes of the timer register
2) Add 32768 to timer1 by setting high bit or timer register
3) Disable access to the individual bytes of the timer register
Code:

#Byte TMR1H = 0xFCF
#Byte T1CON = 0xFCD
#int_TIMER1
void TIMER1_isr()
{  bit_clear(T1CON,7);
   Bit_Set(TMR1H,7);     
   Bit_Set(T1CON,7);     
   flg=true;
}

and remove this
Code:
set_timer1(32768);

This will have improved performance and accuracy. There will be no error introduced by setting the timer to 32768 after the timer has incremented to 3 or 4.



Hello Neutone!


Why did you disable and enable the 7th bit of T1CON only to set the 7th bit of TMR1H?

I don't understand that.

Doing so will, as per the datasheet, shift the timer clock source to instruction clock (Fosc/4).

TMR1CS<1:0>: Timer1/3/5 Clock Source Select bits
00 = Timer1/3/5 clock source is instruction clock (FOSC/4)


?????
_________________
Long Live My Master.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Wed Jun 15, 2016 9:24 am     Reply with quote

Quote:
Why did you disable and enable the 7th bit of T1CON only to set the 7th bit of TMR1H?

I don't understand that.

Doing so will, as per the datasheet, shift the timer clock source to instruction clock (Fosc/4).

TMR1CS<1:0>: Timer1/3/5 Clock Source Select bits
00 = Timer1/3/5 clock source is instruction clock (FOSC/4)

<1:0> does not mean bit 7. It means bits 0 and 1.

Look in the PIC data sheet at the T1CON register. You'll see that
bit 7 is the RD16 bit in T1CON.
abbas14



Joined: 05 Sep 2015
Posts: 7

View user's profile Send private message

PostPosted: Wed Jun 15, 2016 10:34 pm     Reply with quote

PCM programmer wrote:
Quote:
Why did you disable and enable the 7th bit of T1CON only to set the 7th bit of TMR1H?

I don't understand that.

Doing so will, as per the datasheet, shift the timer clock source to instruction clock (Fosc/4).

TMR1CS<1:0>: Timer1/3/5 Clock Source Select bits
00 = Timer1/3/5 clock source is instruction clock (FOSC/4)

<1:0> does not mean bit 7. It means bits 0 and 1.

Look in the PIC data sheet at the T1CON register. You'll see that
bit 7 is the RD16 bit in T1CON.



RD16 is bit1.
Or maybe it differs for different uCs.
I am talking about PIC18(L)F2X/4XK22

Look at page number 172 of the datasheet.

By the way, i understand it now. thank you.
One more question: why are you clearing it before setting the 7th bit of TMR1H and then setting it afterwards. the default value of the bit is 0, as per the datasheet. Can't it be left unaltered? because we are not doing any 16-bit read/write operation in this program?

Also, my compiler is showing TMR1H and T1_CLK_OUT as undefined identifier.
I have tried uninstalling and then reinstalling the compiler, but no progress. Can anyone help me out with this? my compiler version is the latest 5.56.

Thanks a lot.
_________________
Long Live My Master.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Thu Jun 16, 2016 1:21 am     Reply with quote

My advice is, open a new thread in the main forum. You have a different,
much newer technology PIC (K22 series). A real-time clock with an
external 32.768KHz crystal is setup differently with your PIC. This thread
is about the older 18F2550 series.
abbas14



Joined: 05 Sep 2015
Posts: 7

View user's profile Send private message

PostPosted: Thu Jun 16, 2016 2:19 am     Reply with quote

abbas14 wrote:
PCM programmer wrote:
Quote:
Why did you disable and enable the 7th bit of T1CON only to set the 7th bit of TMR1H?

I don't understand that.

Doing so will, as per the datasheet, shift the timer clock source to instruction clock (Fosc/4).

TMR1CS<1:0>: Timer1/3/5 Clock Source Select bits
00 = Timer1/3/5 clock source is instruction clock (FOSC/4)

<1:0> does not mean bit 7. It means bits 0 and 1.

Look in the PIC data sheet at the T1CON register. You'll see that
bit 7 is the RD16 bit in T1CON.



RD16 is bit1.
Or maybe it differs for different uCs.
I am talking about PIC18(L)F2X/4XK22

Look at page number 172 of the datasheet.

By the way, i understand it now. thank you.
One more question: why are you clearing it before setting the 7th bit of TMR1H and then setting it afterwards. the default value of the bit is 0, as per the datasheet. Can't it be left unaltered? because we are not doing any 16-bit read/write operation in this program?

Also, my compiler is showing TMR1H and T1_CLK_OUT as undefined identifier.
I have tried uninstalling and then reinstalling the compiler, but no progress. Can anyone help me out with this? my compiler version is the latest 5.56.

Thanks a lot.



I found the solution.

Instead of T1_CLK_OUT parameter in setup_timer1(), my device header file define T1_ENABLE_SOSC, so i am using that.

and my compiler version does not allows access to individual registers, so i am using set_timer1() instead of bit_set() and bit_clear() functions, as in the original program posted by E_KARVELAs.

Either way, can anyone suggest any way i could use the bit_set() and bit_clear() functions as suggested by Neutone???

Thanks a lot.
_________________
Long Live My Master.
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> Code Library All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group