|
|
View previous topic :: View next topic |
Author |
Message |
Kasper
Joined: 14 Jan 2004 Posts: 88 Location: Aurora, Ontario, Canada
|
MAX6900 Realtime Clock (RTC) |
Posted: Thu Feb 26, 2004 6:01 pm |
|
|
Hello.
I have a MAX6900 Realtime clock connected to the I2C port of a PIC18F6720. I can now read the time, set the time, but I can only set the time after a power cycle of the MAX6900. This is a tad annoying, and I would like to fix it so I can set the time anytime I want to.
if anyone has any ideas, I would be very greatful
Kasper
PCWH 3.185,MPLAB 6.4, ICD2, WinXP ProSP1, AMD 3200+ 1GB RAM
( the Set_Seconds... Set_Year values contain BCD numbers to set the time with )
Code: |
void Set_Time_MAX6900(void)
{
output_float(eeprom_scl);
output_float(eeprom_sda);
delay_us(4);
i2c_start();
i2c_write(0xA0);
i2c_write(0x8E);// control register
i2c_write(0x00); // clear the write protect bit, bit 7
i2c_stop();
delay_ms(3); // after any read or write operation, do not talk to it for 2.5ms
i2c_start();
i2c_write(0xA0);
i2c_write(0xBE);
i2c_write(Set_Second);
i2c_write(Set_Minute);
i2c_write(Set_Hour);
i2c_write(Set_Date);
i2c_write(Set_Month);
i2c_write(Set_Day);
i2c_write(Set_Year);
i2c_write(0x00);
i2c_stop();
}
|
|
|
|
Kasper
Joined: 14 Jan 2004 Posts: 88 Location: Aurora, Ontario, Canada
|
|
Posted: Fri Mar 19, 2004 4:00 pm |
|
|
*Bump*
I am assuming that I for whatever reason am not succeeding in clearing the write protect bit with my code.
Anyone has any ideas how to clear the write protect on it, if the above code does not appear to do anything?
Perhaps I should just go for another chip.. any suggestions for an I2C realtime clock, which is known and well supported with CCS?
Thanks in advance
Kasper |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Fri Mar 19, 2004 5:48 pm |
|
|
I think you should post the complete driver, and your test program.
(including all #define statements and ALL pre-processor statements).
I don't have enough information from your post to solve the problem. |
|
|
Kasper
Joined: 14 Jan 2004 Posts: 88 Location: Aurora, Ontario, Canada
|
|
Posted: Mon Mar 22, 2004 12:57 pm |
|
|
Sorry.. here is all the code I have. the read time function works fine, and the set time function also works, but ONLY after a powercycle on the MAX6900 :(
as for a test program.. load up the set time variables, and call Set_time_max6900. I have these variables global right now, but once they work that way, I will switch them over to be passed to the function.
Code: |
// Time is in BCD format
Set_Second = 0x00;
Set_Minute = 0x53;
Set_Hour = 0x13;
Set_Date = 0x22;
Set_Month = 0x03;
Set_Day = 0x00;
Set_Year = 0x04;
Set_Century = 0x20;
Set_Time_MAX6900();
|
This works, but only after a powercycle :(
Code: |
#ifndef EEPROM_SDA
#define EEPROM_SDA PIN_C4
#define EEPROM_SCL PIN_C3
#endif
#define MAX6900_ADDRESS 0xA0 // 0b1010000 R/W
#define BURST_WRITE 0xBE
#define BURST_READ 0xBF
#define SECONDS_write 0x80
#define SECONDS_read 0x81
#define Minutes_write 0x82
#define Minutes_read 0x83
#define Hours_write 0x84
#define Hours_read 0x85
#define date_write 0x86
#define date_read 0x87
#define Month_write 0x88
#define Month_read 0x89
#define Day_write 0x8A
#define Day_read 0x8B
#define Year_write 0x8C
#define Year_read 0x8D
#define Control_write 0x8E
#define Control_read 0x8F
#define Century_write 0x92
#define Century_read 0x93
#define RAM0_write 0xC0
#define RAM0_read 0xC1
#define RAM1_write 0xC2
#define RAM1_read 0xC3
#define RAM2_write 0xC4
#define RAM2_read 0xC5
#define RAM3_write 0xC6
#define RAM3_read 0xC7
#define RAM4_write 0xC8
#define RAM4_read 0xC9
#define RAM5_write 0xCA
#define RAM5_read 0xCB
#define RAM6_write 0xCC
#define RAM6_read 0xCD
#define RAM7_write 0xCE
#define RAM7_read 0xCF
// temp variables for the time setting
int Set_Year = 0;
int Set_Month = 0;
int Set_Day = 0;
int Set_Date = 0;
int Set_Hour = 0;
int Set_Minute = 0;
int Set_Second = 0;
int Set_Century = 32;
//for the realtime Clock
int Century= 0;
int Year = 0;
int Month = 0;
int Day = 0;
int Hour = 0;
int Date = 0;
int Minute = 0;
int Second = 0;
int RTCcontrol =0;
// This function writes time and date info to the MAX6900
//
void Set_Time_MAX6900(void)
{
delay_ms(10);
output_float(eeprom_scl);
output_float(eeprom_sda);
delay_us(4);
i2c_start();
i2c_write(MAX6900_ADDRESS);
i2c_write(Control_write);// control register
i2c_write(0x00); // clear the write protect bit, bit 7
i2c_stop();
delay_ms(3); // after any read or write operation, do not talk to it for 2.5ms
i2c_start();
i2c_write(MAX6900_ADDRESS);
i2c_write(BURST_WRITE);
i2c_write(Set_Second);
i2c_write(Set_Minute);
i2c_write(Set_Hour);
i2c_write(Set_Date);
i2c_write(Set_Month);
i2c_write(Set_Day);
i2c_write(Set_Year);
i2c_write(0x00);// Control register
i2c_stop();
delay_ms(3); // after any read or write operation, do not talk to it for 2.5ms
i2c_write(MAX6900_ADDRESS); // burst write does not write century info.
i2c_write(Century_write);
i2c_write(0x20); // year 2000 in BCD :)
delay_ms(3);// after any read or write operation, do not talk to it for 2.5ms
}
//This function loads up the variables, from Second to Year with the current time
// using a burst read, which is the preferred read to make sure none of the registers
// overflowed while reading.
// This function is tested, and works fine.
void Get_Time_MAX6900(void) {
output_float(eeprom_scl);
output_float(eeprom_sda);
delay_us(4);
// in burst mode, the MAX6900 does not read the century byte.
i2c_start();
i2c_write(0xA0);
i2c_write(0xBF);
i2c_start();
i2c_write(0xA1);
Second = i2c_READ();
Minute = i2c_READ();
hour = i2c_READ();
Date = i2c_READ();
Month = i2c_READ();
Day = i2c_READ();
Year = i2c_READ();
RTCcontrol= i2c_READ(1);
i2c_stop();
delay_ms(3); // after any read or write operation, do not talk to it for 2.5ms
Century= 32; ///20Hex .. reading the century seems to be screwy.. so it is not year 2100 compatible :o\
//fprintf(PORT2,"\rControlReg:=[%X]",RTCcontrol);
}
|
Maxim Tech support was kind enough to email me some code, which they claimed worked, unfortunately not in CCS format. As far as I can tell, I am doing exactly the same as they are.
Code: |
Here's the routine I have used to enter the time and date several times, with no power cycling:
void Initialize_MAX6900() /* ----------------------------------------- */
/* Note: NO error checking is done on the user entries! */
{
uchar yr, mn, dt, dy, hr, min, sec, day;
start2w();
writebyte2w(ADD6900); /* slave address + write */
writebyte2w(0x8e); /* control register write address */
writebyte2w(0x00); /* clear write protect */
stop2w();
printf("\nEnter the year (0-99): ");
scanf("%bx", &yr);
printf("Enter the month (1-12): ");
scanf("%bx", &mn);
printf("Enter the date (1-31): ");
scanf("%bx", &dt);
printf("Enter the day (1-7): ");
scanf("%bx", &dy);
printf("Enter the hour (1-23): ");
scanf("%bx", &hr);
hr = hr & 0x3f; /* force clock to 24 hour mode */
printf("Enter the minute (0-59): ");
scanf("%bx", &min);
printf("Enter the second (0-59): ");
scanf("%bx", &sec);
start2w();
writebyte2w(ADD6900); /* slave address + write */
writebyte2w(0xbe); /* clock burst write */
writebyte2w(sec);
writebyte2w(min);
writebyte2w(hr);
writebyte2w(dt);
writebyte2w(mn);
writebyte2w(dy);
writebyte2w(yr);
writebyte2w(0); /* control */
start2w();
writebyte2w(ADD6900); /* slave address + write */
writebyte2w(0x92);
writebyte2w(0x20); /* century data */
stop2w();
}
|
Any help is appreciated |
|
|
Ttelmah Guest
|
|
Posted: Mon Mar 22, 2004 1:07 pm |
|
|
Look carefully at what they do.
They are not sending a 'stop' between the data body, and the 'write' command, instead they send a 'repeated start' operation.
Best Wishes |
|
|
Kasper
Joined: 14 Jan 2004 Posts: 88 Location: Aurora, Ontario, Canada
|
|
Posted: Mon Mar 22, 2004 1:47 pm |
|
|
oops.. yes.. I fixed that. ( slaps myself for not seeing that part) Thanks!
It seems that I can now set the time, without doing a power cycle on the chip, BUT, once I have read from the chip, using the
Get_Time_MAX6900() routine, I cannot set the time anymore, untill the program has been reset..
Maxim gave me this code for reading, whic works ( yes, I double checked it this time ).
My code reads the time fine too, so I have not suspected it to be causing problems, untill now....
Code: |
Here is a code fragment for reading in burst mode that I believe has
worked in our lab:
start2w();
writebyte2w(ADD6900); /* slave address + write */
writebyte2w(0xbf); /* clock burst read */
start2w();
writebyte2w(ADD6900 + 1); /* slave address + read */
Sec = readbyte2w(ACK); /* starts w/last address stored in register
pointer */
Min = readbyte2w(ACK);
Hrs = readbyte2w(ACK);
Dte = readbyte2w(ACK);
Mon = readbyte2w(ACK);
Day = readbyte2w(ACK);
Yr = readbyte2w(ACK);
cy = readbyte2w(NACK);
stop2w();
|
|
|
|
Kasper
Joined: 14 Jan 2004 Posts: 88 Location: Aurora, Ontario, Canada
|
|
Posted: Mon Mar 22, 2004 2:39 pm |
|
|
OK.. I have a solution, though not a pretty one.
It seems that all is well if I call the set_time_MAX6900 function twice in a row, instead of the once I was doing before.. strange chip this MAX6900
This works, now just be sure you send it BCD values, not straignt integers, or it will be displaying the time in strange hex numbers
.. I still wonder why I have to do this though :o\
Code: |
// This function writes time and date info to the MAX6900
//
void Set_Time_MAX6900(void)
{
/////////////////////////////////////////////////////////////////////////////////////
//yes.. it is retarted, but you have to do this twice :o\////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////
int i;
for(i=0;i<2;i++) {
delay_ms(10);
output_float(eeprom_scl);
output_float(eeprom_sda);
delay_us(4);
i2c_start();
i2c_write(MAX6900_ADDRESS);
i2c_write(Control_write);// control register 0x8E
i2c_write(0x00); // clear the write protect bit, bit 7
i2c_stop();
delay_ms(3); // after any read or write operation, do not talk to it for 2.5ms
i2c_start();
i2c_write(MAX6900_ADDRESS);
i2c_write(BURST_WRITE);
i2c_write(Set_Second);
i2c_write(Set_Minute);
i2c_write(Set_Hour);
i2c_write(Set_Date);
i2c_write(Set_Month);
i2c_write(Set_Day);
i2c_write(Set_Year);
i2c_write(0x00);// Control register
//i2c_stop();
i2c_start();
//delay_ms(3); // after any read or write operation, do not talk to it for 2.5ms
i2c_write(MAX6900_ADDRESS); // burst write does not write century info.
i2c_write(Century_write); //0x92
i2c_write(0x20); // year 2000 in BCD :)
i2c_stop();
delay_ms(3);// after any read or write operation, do not talk to it for 2.5ms
}
/////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
Ttelmah Guest
|
|
Posted: Mon Mar 22, 2004 5:04 pm |
|
|
I must admit, it does seem very 'odd'. It makes me glad I have stuck with the DS1307, seems to be a 'doddle' to drive in comparison!..
Best Wishes |
|
|
|
|
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
|