|
|
View previous topic :: View next topic |
Author |
Message |
treitmey
Joined: 23 Jan 2004 Posts: 1094 Location: Appleton,WI USA
|
ds12887 RTC |
Posted: Wed Aug 02, 2006 8:00 am |
|
|
Here is some work I did on ds12887. Not sure how good it is. I switched to the M41T80. If there is errors, give me the changes and I can fix it up.
Code: | ///////////////////////////////////////////////////////////////////////////
// Name : ds12887.c //
// Author : Timothy Reitmeyer //
// Notice:
// : //
// Date : 05-05-2005 //
// Version: 1.00 //
/////////////////////////////////////////////////////////////////////////////
//05/09/2005 07:25AM initial program with driver. This file is the Driver
/* time, date & alarm regs */
#define CLK_SECS 0 //MSbit of secs is read only
#define CLK_SECS_ALM 1 //MSbit of secs is read only
#define CLK_MINS 2
#define CLK_MINS_ALM 3
#define CLK_HRS 4
#define CLK_HRS_ALM 5
#define CLK_DOW 6
#define CLK_DOM 7
#define CLK_MON 8
#define CLK_YR 9
#define REGA 10 //BIT 7 READ-ONLY all others r/w
#define REGB 11 //READ/WRITE REGISTER
#define REGC 12 //READ-ONLY REGISTER
#define REGD 13 //READ-ONLY REGISTER
#define nvram_min 14 //addresses 14-127 available for use as nv ram
#define nvram_max 127
//Comment out the text if your not using it to save on ram
const char dow_text[8][4] =
{
"---",// -0-
"Mon",// -1-
"Tue",// -2-
"Wed",// -3-
"Thr",// -4-
"Fri",// -5-
"Sat",// -6-
"Sun" // -7-
};
//Comment out the text if your not using it to save on ram
const char month_text[13][4] =
{
"---",// -0-
"Jan",// -1-
"Feb",// -2-
"Mar",// -3-
"Apr",// -4-
"May",// -5-
"Jun",// -6-
"Jul",// -7-
"Aug",// -8-
"Sep",// -9-
"Oct",// -10-
"Nov",// -11-
"Dec"// -12-
};
struct rtc_pin_def
{ //Motorola timing/bus (must have mot(pin1) tied to Vdd.
//Read is data from ds12887 to micro. Write is data from micro to ds12887
BOOLEAN cs_bar; // C0 CS must be kept in the active state during DS and AS for mot
BOOLEAN as; // C1 falling edge of AS latches.
// The next rising AS clears address regardless of whether CS is asserted.
BOOLEAN rw_bar; // C2 Read,Write_bar
BOOLEAN ds; // C3 During read cycles, DS signifies the time that the DS12887 is to drive the bidirectional bus.
// In write cycles the trailing edge of DS causes the DS12887 to latch the written data.
BOOLEAN reset_bar; // C4 Reset active low
BOOLEAN irq_bar; // C5 IRQ input active low,read reg C to return irq_bar=1
BOOLEAN rclr_bar; // C6 Unused ..rclr_bar
BOOLEAN swq; // C7 Square Wave out of ds12887
int8 ad; // PortD=Address and Data bus
};
struct rtc_rega_struc
{
BOOLEAN RS0;//RS0-3 //1) Enable the interrupt with the PIE bit;
BOOLEAN RS1; //2) Enable the SQW output pin with the SQWE bit;
BOOLEAN RS2; //3) Enable both at the same time and the same rate; or
BOOLEAN RS3; //4) Enable neither.
BOOLEAN DV0;//DV0-2 A pattern of 010 to turn on RTC first time
BOOLEAN DV1;//DV0-2 A pattern of 11X enables the oscillator but holds the countdown in reset.
BOOLEAN DV2;
BOOLEAN UIP;//UIP The update-in-progress status flag to be monitored
} rega_var;
struct rtc_regb_struc
{
BOOLEAN DSE; //1=Daylight Savings Enable
BOOLEAN MIL; //1=24 hour military clock or 12 standard household clock
BOOLEAN DM; //1=binary data while a 0 =BCD data.
BOOLEAN SQWE;//1=a square-wave signal at the frequency set by bits RS3-RS0
BOOLEAN UIE; //1=IRQ on update-ended.
BOOLEAN AIE; //1=IRQ on alarm flag,when three time bytes equal the three alarm bytes.
BOOLEAN PIE; //1=IRQ at a rate RS3-RS0.0=IRQ blocked,but the periodic flag (PF) bit is still set.
BOOLEAN SET; //1=update transfer is inhibited and the program can initialize the time and calendar bytes without an update occurring,0=normal advancing,
} regb_var;//0b00001100
struct rtc_regc_struc
{
BOOLEAN bit0;
BOOLEAN bit1;
BOOLEAN bit2;
BOOLEAN bit3;
BOOLEAN UF;//bit is set after each update cycle.
BOOLEAN AF;//1=current time has matched the alarm time.
BOOLEAN PF;//periodic-interrupt flag. Read-only bit that is set to a 1 when an edge is detected
BOOLEAN IRQF;
} regc_var; //Read only
struct rtc_regd_struc
{
BOOLEAN bit0;
BOOLEAN bit1;
BOOLEAN bit2;
BOOLEAN bit3;
BOOLEAN bit4;
BOOLEAN bit5;
BOOLEAN bit6;
BOOLEAN VRT;//Valid RAM time. If zero the lithium battery is dead
} regd_var;//Read only
struct rtc_pin_def rtc; //pins for the rtc
struct rtc_pin_def rtc_tris;//tris for the rtc
#byte rtc = 0xF82 //note: no semicolin 0x82=C0 on a 18F452
#byte rtc_tris = 0xF94 //tris location for port C pin 0
#define rtc_tris_r() rtc_tris=0;rtc_tris.ad=0xFF//read data is input
#define rtc_tris_w() rtc_tris=0;rtc_tris.ad=0//write data is output
//============Prototypes=================================//
void init_rtc(void);
//void model_num(void);
char read_rtc(char addr);
void write_rtc(char addr,char data);
void set_time(void);
//============Funtions===================================//
void write_rtc(char addr,char data)
{
//C7=swq,6=rclr_bar,5=irq_bar,4=reset_bar,3=ds,2=rw_bar,1=as,0=cs_bar
rtc_tris_w();
rtc.cs_bar=0;//chip active
rtc.ad=addr; //addr is on bus
rtc.rw_bar=0;//write mode
rtc.ds=0; //data strob idle
rtc.as=1; //addr strob
delay_cycles(1); // pause
rtc.as=0; //latch address
rtc.ds=1; //data strob idle
rtc.ad=data; //data is on bus
delay_cycles(1); // pause
rtc.ds=0; //latch data
rtc_tris_r(); //set the tris of C and D to ALL INPUTS
}
//=======================================================//
char read_rtc(char addr)
{
//C7=swq,6=rclr_bar,5=irq_bar,4=reset_bar,3=ds,2=rw_bar,1=as,0=cs_bar
char data;
rtc_tris=0b11100000;//set the tris of C for setting address
rtc_tris.ad=0x00; //set the tris of D for setting address
rtc =0b00011110;//set C for for setting address
rtc.ad=addr; //put address on bus
#asm nop #endasm //pause
rtc.as=0; //latch
delay_cycles(1); // pause
rtc_tris.ad=0xFF; //set the tris of D for reading data
rtc.ds=0; //release
#asm nop #endasm //pause
data=rtc.ad; //read the data from the bus
rtc_tris_r(); //set the tris of B and D to ALL INPUTS
return(data);
}
//=======================================================//
void init_rtc()
{
rtc_tris.reset_bar=0;//set the tris of C
rtc.reset_bar=0; //reset
delay_ms(200);// delay the required time for reset
rtc.reset_bar=1; //release
rtc_tris_r(); //set the tris of C & D to ALL INPUTS
while(rega_var.UIP);//wait for update to finish
regd_var=read_rtc(REGD);
if(regd_var.VRT) fprintf(DEBUG,"Lithium battery OK\n\r");
else fprintf(DEBUG,"Lithium battery dead\n\r");
rega_var=0;
// //RS3:0 0=None,1=256Hz,2=128Hz,3=8.192kHz,4=4.096kHz,5=2.048kHz,6=1.024kHz
// //7=512Hz,8=256Hz,9=128Hz,A=64Hz,B=32Hz,C=16Hz,D=8Hz,E=4Hz,F=2Hz
// //RS3:0=5 =2kHz sqr wave
// rega_var.RS0=1;//RS0-3 //1) Enable the interrupt with the PIE bit;
// rega_var.RS1=1; //2) Enable the SQW output pin with the SQWE bit;
// rega_var.RS2=1; //3) Enable both at the same time and the same rate; or
// rega_var.RS3=1; //4) Enable neither.
// rega_var.DV0=0;//DV0-2 A pattern of 010 to turn on RTC first time
// rega_var.DV1=1;//DV0-2 A pattern of 11X enables the oscillator but holds the countdown in reset.
// rega_var.DV2=0;
// rega_var.UIP=0;//UIP The update-in-progress status flag to be monitored
// write_rtc(REGA,(int8)rega_var); //set reg A
write_rtc(REGA,0b11110100); //set reg A
// //write_rtc(REGB,0b00001000); //set reg B
// //write_rtc(REGB,0b01000100); //(msb) SET,PIE,AIE,UIE,SQWE,DM,MIL,DSE (lsb)
// regb_var.DSE=0; //1=Daylight Savings Enable
// regb_var.MIL=0; //1=24 hour military clock or 12 standard household clock
// regb_var.DM=1; //1=binary data while a 0 =BCD data.
// regb_var.SQWE=1;//1=a square-wave signal at the frequency set by bits RS3-RS0
// regb_var.UIE=0; //1=IRQ on update-ended.
// regb_var.AIE=1; //1=IRQ on alarm flag,when three time bytes equal the three alarm bytes.
// regb_var.PIE=0; //1=IRQ at a rate RS3-RS0.0=IRQ blocked,but the periodic flag (PF) bit is still set.
// regb_var.SET=0; //1=update transfer is inhibited and the program can initialize the time and calendar bytes without an update occurring,0=normal advancing,
// write_rtc(REGB,(int8)regb_var);
write_rtc(REGB,0b11111100); //(msb) SET,PIE,AIE,UIE,SQWE,DM,MIL,DSE (lsb)
}
//================set the time and date======================//
void set_time()
/* Note: NO error checking is done on the user entries! */
{
char yr, mn, dt, dy, hr, min, sec;
char input[10];
regb_var=read_rtc(REGB);
if(regb_var.DM=1) /* Binary data */
{
fprintf(DEBUG,"\nEnter the year (0-99): ");
fgets(input,DEBUG);//scanf("%bd", &yr);
yr=atoi(input);
fprintf(DEBUG,"\n\rread %u\n\r",yr);
fprintf(DEBUG,"Enter the month (1-12): ");
fgets(input,DEBUG);// scanf("%bd", &mn);
mn=atoi(input);
fprintf(DEBUG,"\n\rread %u\n\r",mn);
fprintf(DEBUG,"Enter the date (1-31): ");
fgets(input,DEBUG);// scanf("%bd", &dt);
dt=atoi(input);
fprintf(DEBUG,"\n\rread %u\n\r",dt);
fprintf(DEBUG,"Enter the day (1-7): ");
fgets(input,DEBUG);// scanf("%bd", &dy);
dy=atoi(input);
fprintf(DEBUG,"\n\rread %u\n\r",dy);
if(regb_var.MIL=1) /* if 24 hour mode */
{
fprintf(DEBUG,"Enter the hour (1-23): ");
fgets(input,DEBUG);//scanf("%bd", &hr);
hr=atoi(input);
fprintf(DEBUG,"\n\rread %u\n\r",hr);
}
else
{
fprintf(DEBUG,"Enter the hour (1-11): ");
fgets(input,DEBUG);//scanf("%bd", &hr);
hr=atoi(input);
fprintf(DEBUG,"\n\rread %u\n\r",hr);
fprintf(DEBUG,"A)M or P)M (A/P) " );
fgets(input,DEBUG);//scanf("%1bs", &min);
if(input == 'P' || input == 'p')
hr |= 0x80; /* add PM indicator */
}
fprintf(DEBUG,"Enter the minute (0-59): ");
fgets(input,DEBUG);//scanf("%bd", &min);
min=atoi(input);
fprintf(DEBUG,"\n\rread %u\n\r",min);
fprintf(DEBUG,"Enter the second (0-59): ");
fgets(input,DEBUG);//scanf("%bd", &sec);
sec=atoi(input);
fprintf(DEBUG,"\n\rread %u\n\r",sec);
}
else /* BCD data mode */
{
// fprintf(DEBUG,"\nEnter the year (0-99): ");
// scanf("%bx", &yr);
// fprintf(DEBUG,"Enter the month (1-12): ");
// scanf("%bx", &mn);
// fprintf(DEBUG,"Enter the date (1-31): ");
// scanf("%bx", &dt);
// fprintf(DEBUG,"Enter the day (1-7): ");
// scanf("%bx", &dy);
// if(REGB & 2) /* if 24 hour mode */
// {
// fprintf(DEBUG,"Enter the hour (1-23: ");
// scanf("%bx", &hr);
// }
// else
// {
// fprintf(DEBUG,"Enter the hour (1-11:) ");
// scanf("%bx", &hr);
// fprintf(DEBUG,"A)M or P)M (A/P) ");
// scanf("%1bs", &min);
// if(min == 'P' || min == 'p')
// hr |= 0x80; /* add PM indicator */
// }
// fprintf(DEBUG,"\nEnter the minute (0-59): ");
// scanf("%bx", &min);
// fprintf(DEBUG,"Enter the second (0-59): ");
// scanf("%bx", &sec);
}
regb_var.SET=1;// REGB |= 0x80; /* inhibit update while writing to clock */
write_rtc(REGB,(int8)regb_var); //set reg B
write_rtc(CLK_SECS,sec);// CLK_SECS = sec;
write_rtc(CLK_MINS,min);// CLK_MINS = min;
write_rtc(CLK_HRS,hr);// CLK_HRS = hr;
write_rtc(CLK_DOW,dy);// CLK_DOW = dy;
write_rtc(CLK_DOM,dt);// CLK_DOM = dt;
write_rtc(CLK_MON,mn);// CLK_MON = mn;
write_rtc(CLK_YR,yr);// CLK_YR = yr;
//irq on alarm, alarm set to don't care in all 3 bytes..ie: irq on each second
write_rtc(CLK_HRS_ALM,0xFF); // CLK_HRS_ALM= 0xFF;//ie:don't care
write_rtc(CLK_MINS_ALM,0xFF);// CLK_MINS = 0xFF;//ie:don't care
write_rtc(CLK_SECS_ALM,0xFF);// CLK_MINS = 0xFF;//ie:don't care
regb_var.SET=0;// REGB &= 0x7f; /* allow update of buffered set of time & date registers */
write_rtc(REGB,(int8)regb_var); //set reg B
}
//=======================================================//
//void model_num(void) /* ------ determine the model number of the RTC ------ */
//{
// REGA |= 0x10; /* select bank 1 */
// XBYTE[0x40] ^= 0xff; /* try to write to compliment data */
// if( (XBYTE[0x40] ^ 0xff) != XBYTE[0x40] ) /* if bits cannot be written, it's
// bank 1 */
// {
// model = XBYTE[0x40];
// }
// else
// {
// XBYTE[0x40] ^= 0xff; /* restore original data */
// model = 0; /* default if device does not support model number */
// }
// REGA &= 0xef; /* select bank 0 */
// printf("\nModel: ");
// switch(model)
// {
// case 0x71: printf("DS1687"); break;
// case 0x72: printf("DS17287"); break;
// case 0x73: printf("DS1691/93"); break;
// case 0x74: printf("DS17487"); break;
// case 0x78: printf("DS17887"); break;
// default: printf("DS12887");
// }
//}
|
Code: | ///////////////////////////////////////////////////////////////////////////
// Name : ds12887_test.c //
// Author : Timothy Reitmeyer //
// Notice : //
// : //
// Date : 01-05-2004 //
// Version: (see VER_MAJOR and VER_MINOR below) //
///////////////////////////////////////////////////////////////////////////
//05/09/2005 07:30AM Initial program and driver. This file is the program//
//05/10/2005 12:54PM
//***********************************************************************//
#include <18F452>
#device adc=8
#CASE
#USE DELAY(CLOCK=16000000)
#FUSES HS,NOWDT,NOPROTECT,NOLVP,NOWDT,WDT128,NOOSCSEN,NOBROWNOUT,NOPUT,NOSTVREN
#DEFINE VER_MAJOR 1
#DEFINE VER_MINOR 01
#USE RS232(BAUD=19200,XMIT=PIN_E0,RCV=PIN_E1,INVERT,STREAM=DEBUG)
#ZERO_RAM
#include <stdio.h>
#include <stdlib.h>
#include "C:\ccs\Projects\Sample code\LCD_PICDEM2.C"
#include "ds12887.c"
int8 old_secs;
//======================= MAIN ============================//
void main(void)
{
char hours,mins,secs;
setup_adc_ports(NO_ANALOGS);
set_tris_a(0);set_tris_b(0);set_tris_c(0x00);set_tris_d(0x00);set_tris_e(0);
fprintf(DEBUG,"\n\r");
fprintf(DEBUG,"STARTING DS12887 Test.\n\r");
fprintf(DEBUG,"FIRMWARE VERSION %u.%02u\n\r",VER_MAJOR,VER_MINOR);
output_a(0);
output_b(0);
output_c(0);
output_d(0);
set_tris_b(0xFF);
port_b_pullups(TRUE);
set_time();
lcd_init();
lcd_clr();
init_rtc();
//RS3:0 0=None,1=256Hz,2=128Hz,3=8.192kHz,4=4.096kHz,5=2.048kHz,6=1.024kHz
//7=512Hz,8=256Hz,9=128Hz,A=64Hz,B=32Hz,C=16Hz,D=8Hz,E=4Hz,F=2Hz
rega_var.RS0=1;
rega_var.RS1=1;
rega_var.RS2=1;
rega_var.RS3=1;
rega_var.DV0=0;//DV0-2 A pattern of 010 to turn on RTC first time
rega_var.DV1=1;//DV0-2 A pattern of 11X enables the oscillator but holds the countdown in reset.
rega_var.DV2=0;
rega_var.UIP=0;//UIP The update-in-progress status flag to be monitored
write_rtc(REGA,(int8)rega_var); //set reg A
//write_rtc(REGB,0b00001000); //set reg B
//write_rtc(REGB,0b01000100); //(msb) SET,PIE,AIE,UIE,SQWE,DM,MIL,DSE (lsb)
regb_var.DSE=0; //1=Daylight Savings Enable
regb_var.MIL=1; //1=24 hour military clock or 12 standard household clock
regb_var.DM =1; //1=binary data while a 0 =BCD data.
regb_var.SQWE=1;//1=a square-wave signal at the frequency set by bits RS3-RS0
regb_var.UIE=1; //1=IRQ on update-ended.
regb_var.AIE=1; //1=IRQ on alarm flag,when three time bytes equal the three alarm bytes.
regb_var.PIE=1; //1=IRQ at a rate RS3-RS0.0=IRQ blocked,but the periodic flag (PF) bit is still set.
regb_var.SET=0; //1=update transfer is inhibited and the program can initialize the time and calendar bytes without an update occurring,0=normal advancing,
write_rtc(REGB,(int8)regb_var);
set_tris_b(0xFF);
port_b_pullups(TRUE);
regc_var=read_rtc(REGC);//clear any outstanding irq's
enable_interrupts(INT_RB);
enable_interrupts(GLOBAL);
fprintf(DEBUG,"In Main loop\n\r");
while (TRUE)
{
}
}
//======================= int_RB ============================//
#int_RB
RB_isr()
{
char day_of_week,day_of_month,month,year,hours,mins,secs;
rtc=input_b(); //clear 18F452 INT
regc_var=read_rtc(REGC);
// if (regc_var.UF)fprintf(DEBUG,"UF ");
// if (regc_var.AF)fprintf(DEBUG,"AF ");
// if (regc_var.PF)fprintf(DEBUG,"PF");
if (regc_var.IRQF)
{
// fprintf(DEBUG,"IRQF ");
secs =read_rtc(CLK_SECS);
if (secs!=old_secs)
{
output_high(PIN_B0);
mins =read_rtc(CLK_MINS);
hours=read_rtc(CLK_HRS);
day_of_week=read_rtc(CLK_DOW);
day_of_month=read_rtc(CLK_DOM);
month=read_rtc(CLK_MON);
year =read_rtc(CLK_YR);
lcd_clr();//will leave the lcd at position 1,1(upper left)
printf(lcd_putc,"%02u/%02u/2%03u\n",month,day_of_month,year);
lcd_gotoxy(1,2);
printf(lcd_putc,"%02u:%02u:%02u\n",hours,mins,secs);
old_secs=secs;
output_low(PIN_B0);
}
}
}
|
|
|
|
faisal
Joined: 20 Apr 2010 Posts: 2 Location: Pakistan
|
|
Posted: Tue Apr 20, 2010 12:54 am |
|
|
hy,
i hve interafcing problem with DS12887 RTC....
whn i write the time on RTC its shows the correct time but after sometime when i again turn it on its shows dummy time......
woud u plz help me out... _________________ DRIVER |
|
|
smanzer
Joined: 14 Sep 2009 Posts: 24 Location: Ontario, Canada
|
RTC Errors |
Posted: Tue Apr 20, 2010 9:05 am |
|
|
Hi, faisal,
I had quite a problem with DS1307 RTC's. Here is what I would check:
- Check crystal solder connections
- Shorten all cables going from the PIC to the RTC I2C ports
- Verify battery voltage is correct
- Verify pullups are present
They were the things I had trouble with. The worst was the length of cable on the I2C lines. If I went to a port breakout board the RTC would stop functioning. I now have very short direct cabling to the RTC module....
Good luck!
Steven _________________ "I am always doing that which I can not do, in order that I may learn how to do it."
- Pablo Picasso |
|
|
faisal
Joined: 20 Apr 2010 Posts: 2 Location: Pakistan
|
DS12877 |
Posted: Fri Apr 23, 2010 1:16 am |
|
|
thnX for ur reply...
I checked everything in my circuit.
At start, when I switched on the circuit the RTC (DS1287) displays the right time.
But when there is an interruption in Power, the time is changed,
and then it displays dead when I read its Register D.
In this I have permanently grounded its CS pin.
Does it cause any problem during Power reset and change the time ?
_________________ DRIVER |
|
|
smanzer
Joined: 14 Sep 2009 Posts: 24 Location: Ontario, Canada
|
Re: RTC |
Posted: Sun Apr 25, 2010 9:41 pm |
|
|
Did you check your battery voltage and make sure it is connected properly?
Sounds silly, but it is usually the most obvious solution we all miss... _________________ "I am always doing that which I can not do, in order that I may learn how to do it."
- Pablo Picasso |
|
|
Gabriel
Joined: 03 Aug 2009 Posts: 1067 Location: Panama
|
|
Posted: Tue Oct 05, 2010 6:59 am |
|
|
i use a DS1305, its SPI but its the same manufacturer and im sure its the same logic.
when there is a power interruption... from vcc1 and backup (both at the same time) the control register bits that control the oscillator are reset and the oscillator is stopped, and the chip goes into a low power state..
your code upon startup(or wake up) should check the control register.
if the oscillator control bit is set, you had a power failure..
thus you should prompt the user for time...
else... continue to display time or what ever normaly..
your chip even on your protoboard should be powerd by 2 sources..
regular VCC from (for example) an 7805 and Vbat from a coin cell..
obviously when you do this... you will not have a power failure for the next 10 years probably.... Vbat will not die any time soon.
to test your code for power failure you will need to cut power from both sources...
hope that helps..
gabriel. _________________ CCS PCM 5.078 & CCS PCH 5.093 |
|
|
|
|
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
|