|
|
View previous topic :: View next topic |
Author |
Message |
emix245
Joined: 06 Apr 2014 Posts: 3
|
RTC Frequency of 1hz |
Posted: Tue Apr 08, 2014 11:46 pm |
|
|
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: 19550
|
|
Posted: Wed Apr 09, 2014 1:08 am |
|
|
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: 9245 Location: Greensville,Ontario
|
|
Posted: Wed Apr 09, 2014 5:16 am |
|
|
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
|
|
Posted: Wed Apr 09, 2014 6:22 am |
|
|
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
|
|
Posted: Wed Apr 09, 2014 10:22 am |
|
|
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: 19550
|
|
Posted: Wed Apr 09, 2014 11:21 am |
|
|
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
|
|
Posted: Wed Apr 09, 2014 11:42 am |
|
|
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: 9245 Location: Greensville,Ontario
|
|
Posted: Thu Apr 10, 2014 5:17 am |
|
|
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
|
|
Posted: Thu Apr 10, 2014 9:58 am |
|
|
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
|
|
Posted: Thu Apr 10, 2014 10:10 am |
|
|
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
|
|
Posted: Thu Apr 10, 2014 10:10 am |
|
|
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
|
|
Posted: Thu Apr 10, 2014 10:17 am |
|
|
Thank you all for your time. |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9245 Location: Greensville,Ontario
|
|
Posted: Thu Apr 10, 2014 2:20 pm |
|
|
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 |
|
|
|
|
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
|