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 support@ccsinfo.com

RTC Frequency of 1hz

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
emix245



Joined: 06 Apr 2014
Posts: 3

View user's profile Send private message

RTC Frequency of 1hz
PostPosted: Tue Apr 08, 2014 11:46 pm     Reply with quote

Hi guys,
I'm programming an RTC and simulating it on isis.
Does someone know how to put the frequency of the RTC to 1Hz using the reg and the loop, because when i want to change the time and date I need to press the button for 1sec for it to change because of the delay_ms(1000) in the while function.

This is my code
Code:

#include "Project.h"
#include "LCD2x16.h"
#use i2c(Master,Slow,sda=PIN_C4,scl=PIN_C3)

#include <ds1307.c>
///////////////////////////////////////////////////////////////////////////////
BOOLEAN Ext_Int_detect = FALSE;
#int_EXT    //interrupt service routine for INT0

void  EXT_isr(void)
{
   Ext_Int_detect = TRUE;
}
///////////////////////////////////////////////////////////////////////////////
unsigned int16 old_CCP1=0, CCP1_diff;
#int_CCP1   //interrupt service routine for Capture 1

void CCP1_isr(void)
{
   CCP1_diff = CCP_1 - old_CCP1;
   
   old_CCP1 = CCP_1; //prepare for next capture
}
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
void main()
{
  BYTE sec;
  BYTE min;
  BYTE hrs;
  BYTE day;
  BYTE month;
  BYTE yr;
  BYTE dow;
  float freq;
   
   setup_timer_3(T3_DISABLED | T3_DIV_BY_1);
   
   setup_timer_1(T1_INTERNAL | T1_DIV_BY_1 );   //prepare timer1 for CCP1
   setup_ccp1(CCP_CAPTURE_FE);   //set up input capture for frequency detect
   
   ext_int_edge(H_TO_L);
   enable_interrupts(INT_EXT);
   enable_interrupts(INT_CCP1); //enable interrupt for input capture
   enable_interrupts(GLOBAL);
   
   set_tris_c(0xBF);
   
   delay_ms(500);    //wait a bit
   
   lcd_init();       //initialize 16x2 LCD
   printf(lcd_putc, "Project Lab\nEmile & Karl"); // print on LCD
   
   delay_ms(1000);   //wait 1 sec
   lcd_putc('\f');   //clear LCD
   
  ds1307_init();
 
  // Set date for -> 15 June 2005 Tuesday
  // Set time for -> 15:20:55
  ds1307_set_date_time(15,6,5,2,15,20,55);
   
   while(TRUE)
   {
    delay_ms(1000);
   
    ds1307_get_date(day,month,yr,dow);
    ds1307_get_time(hrs,min,sec);
     
    printf(lcd_putc,"\f\%02d/\%02d/\%02d\r\n",day,month,yr);
    printf(lcd_putc,"\%02d:\%02d:\%02d", hrs,min,sec);
   
     if (!input(PIN_B0))
      {
         while (!input(PIN_B0));
         day++;
         ds1307_set_date_time(day,month,yr,dow,hrs,min,sec);
      }
      if (!input(PIN_B1))
      {
         while (!input(PIN_B1));
         month++;
         ds1307_set_date_time(day,month,yr,dow,hrs,min,sec);
      }
      if (!input(PIN_B2))
      {
         while (!input(PIN_B2));
         yr++;
         ds1307_set_date_time(day,month,yr,dow,hrs,min,sec); ;
      }
      if (!input(PIN_B3))
      {
         while (!input(PIN_B3));
         sec++;
         ds1307_set_date_time(day,month,yr,dow,hrs,min,sec);
      }
      if (!input(PIN_B4))
      {
         while (!input(PIN_B4));
         min++;
         ds1307_set_date_time(day,month,yr,dow,hrs,min,sec);
      }
      if (!input(PIN_B5))
      {
         while (!input(PIN_B5));
         hrs++;
         ds1307_set_date_time(day,month,yr,dow,hrs,min,sec);
      }

      //display frequency:
      freq = 1/((float)CCP1_diff/1000000);
      lcd_gotoxy(10,1);
      printf(lcd_putc, "F=%.2f", freq);
   }

}

And this is the ds1307.c code
Code:

////////////////////////////////////////////////////////////////////////////////
///                               DS1307.C                                   ///
///                     Driver for Real Time Clock                           ///
///                                                                          ///
/// ds1307_init() - Enable oscillator without clearing the seconds register -///
///                 used when PIC loses power and DS1307 run from 3V BAT     ///
///               - Disable squarewave output                                ///
///                                                                          ///
/// ds1307_set_date_time(day,mth,year,dow,hour,min,sec)  Set the date/time   ///
///                                                                          ///
/// ds1307_get_date(day,mth,year,dow)               Get the date             ///
///                                                                          ///
/// ds1307_get_time(hr,min,sec)                     Get the time             ///
///                                                                          ///
////////////////////////////////////////////////////////////////////////////////

#define RTC_SDA  PIN_C4
#define RTC_SCL  PIN_C3

#use i2c(master, sda=RTC_SDA, scl=RTC_SCL)

BYTE bin2bcd(BYTE binary_value);
BYTE bcd2bin(BYTE bcd_value);

void ds1307_init(void)
{
   BYTE seconds = 0;

   i2c_start();
   i2c_write(0xD0);      // WR to RTC
   i2c_write(0x00);      // REG 0
   i2c_start();
   i2c_write(0xD1);      // RD from RTC
   seconds = bcd2bin(i2c_read(0)); // Read current "seconds" in DS1307
   i2c_stop();
   seconds &= 0x7F;

   delay_us(3);

   i2c_start();
   i2c_write(0xD0);      // WR to RTC
   i2c_write(0x00);      // REG 0
   i2c_write(bin2bcd(seconds));     // Start oscillator with current "seconds value
   i2c_start();
   i2c_write(0xD0);      // WR to RTC
   i2c_write(0x07);      // Control Register
   i2c_write(0x80);     // Disable squarewave output pin
   i2c_stop();
}

void ds1307_set_date_time(BYTE day, BYTE mth, BYTE year, BYTE dow, BYTE hr, BYTE min, BYTE sec)
{
  sec &= 0x7F;
  hr &= 0x3F;

  i2c_start();
  i2c_write(0xD0);            // I2C write address
  i2c_write(0x00);            // Start at REG 0 - Seconds
  i2c_write(bin2bcd(sec));      // REG 0
  i2c_write(bin2bcd(min));      // REG 1
  i2c_write(bin2bcd(hr));      // REG 2
  i2c_write(bin2bcd(dow));      // REG 3
  i2c_write(bin2bcd(day));      // REG 4
  i2c_write(bin2bcd(mth));      // REG 5
  i2c_write(bin2bcd(year));      // REG 6
  i2c_write(0x80);            // REG 7 - Disable squarewave output pin
  i2c_stop();
}

void ds1307_get_date(BYTE &day, BYTE &mth, BYTE &year, BYTE &dow)
{
  i2c_start();
  i2c_write(0xD0);
  i2c_write(0x03);            // Start at REG 3 - Day of week
  i2c_start();
  i2c_write(0xD1);
  dow  = bcd2bin(i2c_read() & 0x7f);   // REG 3
  day  = bcd2bin(i2c_read() & 0x3f);   // REG 4
  mth  = bcd2bin(i2c_read() & 0x1f);   // REG 5
  year = bcd2bin(i2c_read(0));            // REG 6
  i2c_stop();
}

void ds1307_get_time(BYTE &hr, BYTE &min, BYTE &sec)
{
  i2c_start();
  i2c_write(0xD0);
  i2c_write(0x00);            // Start at REG 0 - Seconds
  i2c_start();
  i2c_write(0xD1);
  sec = bcd2bin(i2c_read() & 0x7f);
  min = bcd2bin(i2c_read() & 0x7f);
  hr  = bcd2bin(i2c_read(0) & 0x3f);
  i2c_stop();

}

BYTE bin2bcd(BYTE binary_value)
{
  BYTE temp;
  BYTE retval;

  temp = binary_value;
  retval = 0;

  while(1)
  {
    // Get the tens digit by doing multiple subtraction
    // of 10 from the binary value.
    if(temp >= 10)
    {
      temp -= 10;
      retval += 0x10;
    }
    else // Get the ones digit by adding the remainder.
    {
      retval += temp;
      break;
    }
  }

  return(retval);
}

// Input range - 00 to 99.
BYTE bcd2bin(BYTE bcd_value)
{
  BYTE temp;

  temp = bcd_value;
  // Shifting upper digit right by 1 is same as multiplying by 8.
  temp >>= 1;
  // Isolate the bits for the upper digit.
  temp &= 0x78;

  // Now return: (Tens * 8) + (Tens * 2) + Ones

  return(temp + (temp >> 2) + (bcd_value & 0x0f));
}


Thanks in advance.
Emile
Ttelmah



Joined: 11 Mar 2010
Posts: 19346

View user's profile Send private message

PostPosted: Wed Apr 09, 2014 1:08 am     Reply with quote

You are making no friends by saying you are using Isis. Read the sticky at the top of the forum....
Isis can give you a lot of problems.

However you already 'know' the answer, and the key is to not be delaying in your loop.
Structure needs to be:
Code:

    while (TRUE)
    {
        has a second passed?
           if so, do the printf etc..
        now check the keyboard
    }

Now the point is that instead of using delay_ms(1000), in the main loop, you keep the loop executing as fast as possible, but only do the print when a second has passed. This way your keyboard responds immediately.

How to 'know' a second has passed?. This comes down to a decision you need to make. Several ways:
1)The DS1307, can be programmed to give a pulse every second. This could trigger an interrupt, and then you'd have an accurate 'one second has passed' signal.
2) Have a 'tick' interrupt from one of the timers. Then have this update a counter, and when the counter gets to a particular value you know a second has passed.
3) The compiler has an ability to do this for you with the the #use timer operation. So the test could become:
Code:

#use timer (timer=2,TICK=1ms,BITS=16,NOISR)
//since you are not using timer2.

    while (TRUE)
    {
       if (get_ticks()>=1000)
       {
           set_ticks(0L);
           //Now do your once per second tasks
       }
       //and scan your keys etc..
    }


Structures only - you'll have to work out how you really want to do this, but the key is that the main code loop, does not want to sit delaying. It wants to be getting on and servicing everything else that needs to be done.

Best Wishes
temtronic



Joined: 01 Jul 2010
Posts: 9164
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Wed Apr 09, 2014 5:16 am     Reply with quote

When you get real hardware you can EASILY do it with zero problems...

...simply use the interrupt available from the DS1307, add a very small,simple ISR and a simple 'state machine' in main() based on the ISR data.

I've used the DS1307 for about 5 years on both 4550 and 46k22 projects using this method.

hth
jay
ezflyr



Joined: 25 Oct 2010
Posts: 1019
Location: Tewksbury, MA

View user's profile Send private message

PostPosted: Wed Apr 09, 2014 6:22 am     Reply with quote

Hi,

As a side note, you really should rethink your 'User Interface' (UI) if you actually plan to build some real hardware. Six buttons for the time/date setting functions is a bit much!! When I did a clock project, I defined three buttons for all the time/date and alarm setting functions. One is a Mode/Enter button, and the others are Decrement and Increment buttons. I also designed a simple menu system (on a GLCD display) with a moving cursor, and a highlighted entry field. It actually worked out pretty slick!

John
Mike Walne



Joined: 19 Feb 2004
Posts: 1785
Location: Boston Spa UK

View user's profile Send private message

PostPosted: Wed Apr 09, 2014 10:22 am     Reply with quote

Like ezflyr says, three buttons are enough.

I locate the buttons below the LCD, then use the bottom line of the LCD as labels for the buttons.
Works a treat.
With a bit of thought, you've got a menu driven system.

Mike
Ttelmah



Joined: 11 Mar 2010
Posts: 19346

View user's profile Send private message

PostPosted: Wed Apr 09, 2014 11:21 am     Reply with quote

I agree with Mike, but tend to use four.

One labelled YES/ENTER
One labelled NO

and two below the display.

It's amazing how easy it is to do almost anything with this, and being able to label the two buttons below the display, makes errors much less likely.

Best Wishes
Mike Walne



Joined: 19 Feb 2004
Posts: 1785
Location: Boston Spa UK

View user's profile Send private message

PostPosted: Wed Apr 09, 2014 11:42 am     Reply with quote

Ttelmah wrote:
I agree with Mike, but tend to use four.

One labelled YES/ENTER
One labelled NO

and two below the display.

It's amazing how easy it is to do almost anything with this, and being able to label the two buttons below the display, makes errors much less likely.

Best Wishes
Yes. I'm not going to argue about three/four buttons.

The problem with three and a 2*16 display is you've really only got five characters to play with for each label.
You sometimes have to be a bit creative.
You should still end up with an obvious menu system, which anyone can drive.

Mike
temtronic



Joined: 01 Jul 2010
Posts: 9164
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Thu Apr 10, 2014 5:17 am     Reply with quote

3 or 4 buttons seems to be the 'regular' method though in the 'good old dayze' I used just 1 button. A clever bit of code cutting using timers allowed for 'auto increment', similar to a PC KBD 'auto repeat' feature.
Of course back then LEDs were expensive and my clocks only had 1 digit display, muxing the 10s hrs,hrs,10s min ,min info into a pattern.

fun dayze
jay
emix245



Joined: 06 Apr 2014
Posts: 3

View user's profile Send private message

PostPosted: Thu Apr 10, 2014 9:58 am     Reply with quote

Thank you all for your help i will definitely do these steps.
But in the datasheet of the DS1307 there is the RS0 and RS1 that should be set to 0 so that i can have SQW/OUT output of 1Hz.
Does anyone know how to do this?
ezflyr



Joined: 25 Oct 2010
Posts: 1019
Location: Tewksbury, MA

View user's profile Send private message

PostPosted: Thu Apr 10, 2014 10:10 am     Reply with quote

Hi,

Huh?

You need to write to the Control Register to program the SQW/OUT pin functionality. See page 9 of the datasheet for all the details.

I'm a bit surprised by your question because it seems that if you can read the DS1307, and write to the DS1307, then a simple configuration change to the DS1307 would be trivial. Read the datasheet!!

Am I missing something?

John
Mike Walne



Joined: 19 Feb 2004
Posts: 1785
Location: Boston Spa UK

View user's profile Send private message

PostPosted: Thu Apr 10, 2014 10:10 am     Reply with quote

emix245 wrote:
Thank you all for your help i will definitely do these steps.
But in the datasheet of the DS1307 there is the RS0 and RS1 that should be set to 0 so that i can have SQW/OUT output of 1Hz.
Does anyone know how to do this?

The data sheet tells you everything you need to know about the DS1307.
Register address, and which bit is which.
The CCS driver does the rest.

Mike
emix245



Joined: 06 Apr 2014
Posts: 3

View user's profile Send private message

PostPosted: Thu Apr 10, 2014 10:17 am     Reply with quote

Thank you all for your time.
temtronic



Joined: 01 Jul 2010
Posts: 9164
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Thu Apr 10, 2014 2:20 pm     Reply with quote

OK,it's been like +17*C here, finally..so
here you go....

just edit the RTC driver....
...
i2c_write(0xD0); // WR to RTC
i2c_write(0x07); // point to Control Register
i2c_write(0x10); // Enable squarewave output pin
...

the last line shows what needs to be done....read the datasheet to see why....


cheers

Jay
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion 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