View previous topic :: View next topic |
Author |
Message |
magic_mauve
Joined: 05 Apr 2011 Posts: 12
|
i2c problem with M41T81S and oscillator fail bit |
Posted: Tue May 10, 2011 2:49 pm |
|
|
Hi, I am using the i2C functions for the first time and am having a problem clearing the OF bit of the M41T81S rtc when the module is first booted up and it is set. Does anyone have experience of this, who might be able to spot an error? I am using the PIC 18LF46J11. Here is my test code:
Code: |
#include <18LF46J11.h>
#include <string.h>
#include <stdlib.h>
#fuses HS,NOWDT
#use DELAY(crystal=4000000)
#PIN_SELECT U2TX=PIN_B4
#PIN_SELECT U2RX=PIN_B5
#use rs232(UART2, baud=9600, ERRORS, STREAM=PC)
#define TRISA_VAL 0x02
#define TRISB_VAL 0x2F
#define TRISD_VAL 0x20
#define TRISE_VAL 0x00
#define I2C_SCL PIN_C3
#define I2C_SDA PIN_C4
#define RTC_DEVICE_READ 0xD0
#define RTC_DEVICE_WRITE 0xD1
#define RTC_STOP_BIT_REG 0x01
#define RTC_SEC_REG 0x01
#define RTC_MIN_REG 0x02
#define RTC_HOUR_REG 0x03
#define RTC_DOW_REG 0x04
#define RTC_DAY_REG 0x05
#define RTC_MONTH_REG 0x06
#define RTC_YEAR_REG 0x07
#define RTC_HALT_BIT_REG 0x0c
#define RTC_FLAGS_REG 0x0F
#define BOOL short // 'short' is very short (1 bit) in this compiler
#use I2C(MASTER, SDA=PIN_C4, SCL=PIN_C3, restart_wdt)
void rtc_init();
bool rtc_check_osc_failure();
void rtc_start_osc_restart();
void rtc_finish_osc_restart();
byte read_ext_rtc(byte address);
void write_ext_rtc(byte address, byte data);
void main(void)
{
fprintf(PC,"Hello World: Booting Up\r\n");
delay_ms(1000);
rtc_init();
while (1)
{
if (rtc_check_osc_failure() == true)
{
fprintf(PC,"RTCLOCK: Oscillator fail flag set - clearing\r\n");
rtc_start_osc_restart();
delay_ms(4000);
rtc_finish_osc_restart();
// now check again
if (rtc_check_osc_failure() == true)
{
fprintf(PC,"RTCLOCK: Oscillator FAILED to restart\r\n");
}
else
{
fprintf(PC,"RTCLOCK: Oscillator fail flag ok\r\n");
}
}
else
{
fprintf(PC,"RTCLOCK: Oscillator fail flag ok\r\n");
}
}
}
void rtc_init() {
output_float(I2C_SCL);
output_float(I2C_SDA);
}
bool rtc_check_osc_failure()
{
byte flags;
byte oscill_fail_flag;
flags = read_ext_rtc(RTC_FLAGS_REG); // flags including Oscillator Fail bit
oscill_fail_flag = (flags&0x04);
if (oscill_fail_flag > 0)
{
return true;
}
else
{
return false;
}
}
void rtc_start_osc_restart()
{
byte temp_data;
// the oscillator has failed, so go to restart sequence which is
// Write '1' to Stop bit, then write '0' to stop bit, then wait 4 secs, then set OF (oscillator fail) bit to 0
temp_data = read_ext_rtc(RTC_STOP_BIT_REG); // Read the byte at the address for the stop bit
temp_data = temp_data|0x80; // Set bit 7 (the stop bit) to 0
write_ext_rtc(RTC_STOP_BIT_REG,temp_data);
// now set the stop bit to 1
temp_data = temp_data&0x7F; // Set bit 7 (the stop bit) to 1
write_ext_rtc(RTC_STOP_BIT_REG,temp_data);
}
void rtc_finish_osc_restart()
{
byte flags;
// Set the OF flag to 0
// first read flags
flags = read_ext_rtc(RTC_FLAGS_REG);
// now set OF bit to 0
flags = flags&0xFB;
// now write flags to rtc
write_ext_rtc(RTC_FLAGS_REG,flags);
}
bool ext_rtc_ready()
{
int1 ack;
i2c_start(); // If the write command is acknowledged,
ack = i2c_write(RTC_DEVICE_READ); // then the device is ready.
i2c_stop();
return !ack;
}
byte read_ext_rtc(byte address)
{
byte data;
while(!ext_rtc_ready());
i2c_start();
i2c_write(RTC_DEVICE_READ); // D is device address
i2c_write(address);
i2c_start();
i2c_write(RTC_DEVICE_WRITE); // set device to read
data=i2c_read(0);
i2c_stop();
return (data);
}
void write_ext_rtc(byte address, byte data)
{
while(!ext_rtc_ready());
i2c_start();
i2c_write(RTC_DEVICE_READ);
i2c_write(address);
i2c_write(data);
i2c_stop();
} |
I get the following output:
Hello World: Booting Up
RTCLOCK: Oscillator fail flag set - clearing
RTCLOCK: Oscillator FAILED to restart
RTCLOCK: Oscillator fail flag set - clearing
RTCLOCK: Oscillator FAILED to restart
RTCLOCK: Oscillator fail flag set - clearing
RTCLOCK: Oscillator FAILED to restart
RTCLOCK: Oscillator fail flag set - clearing
RTCLOCK: Oscillator FAILED to restart etc.
Thanks |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Tue May 10, 2011 7:54 pm |
|
|
The M41T81S data sheet says this:
Quote: |
Oscillator fail detection
If the oscillator fail bit (OF) is internally set to '1,' this indicates that the
oscillator has either stopped, or was stopped for some period of time and
can be used to judge the validity of the clock and date data.
In the event the OF bit is found to be set to '1' at any time other than the
initial power-up, the STOP bit (ST) should be written to a '1,' then
immediately reset to '0.' This will restart the oscillator.
The following conditions can cause the OF bit to be set:
● The first time power is applied (defaults to a '1' on power-up).
● The voltage present on V CC is insufficient to support oscillation.
● The ST bit is set to '1.'
● External interference of the crystal.
The OF bit will remain set to '1' until written to logic '0'. The oscillator
must start and have run for at least 4 seconds before attempting
to reset the OF bit to '0.' |
|
|
|
magic_mauve
Joined: 05 Apr 2011 Posts: 12
|
|
Posted: Wed May 11, 2011 1:50 am |
|
|
Thank you for your reply. I see you have highlighted the note that you need to wait 4 secs and then set the OF to '0'. I believe I have done this with:
delay_ms(4000);
rtc_finish_osc_restart();
The rtc_finish_osc_restart() function sets the OF to 0.
Are you saying that this is not correct? |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Wed May 11, 2011 12:55 pm |
|
|
You're right. I skimmed your program too quickly and I missed that part.
I'll look more closely at it.
Describe the external hardware connections to the RTC chip. Do you
have the external 32.768 KHz watch crystal, and the backup battery ?
What is the Vdd voltage of the PIC and the RTC chip ? What is the size
of the pullup resistors on the i2c bus ? |
|
|
magic_mauve
Joined: 05 Apr 2011 Posts: 12
|
|
Posted: Fri May 13, 2011 3:07 am |
|
|
Just to let you know, I discovered the crystal had been been positioned the wrong way around which explains a lot! All is working now. Many thanks |
|
|
Sinalux
Joined: 17 May 2011 Posts: 2
|
|
Posted: Tue May 17, 2011 5:12 pm |
|
|
Hello,
I'm having the same problem. Can you tell me if you're using a 32.767 kHz crystal? What do you mean with "crystal had been positioned the wrong way around"? _________________ Tks
Sinalux |
|
|
magic_mauve
Joined: 05 Apr 2011 Posts: 12
|
Crystal |
Posted: Wed May 18, 2011 1:40 am |
|
|
There is a 32.768Khz crystal connected, it is an ABS13. I'm not the hardware engineer, but the crystal has a slight slope at one end and it had been positioned on the board around the wrong way, i.e. with the slope at the wrong end. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19515
|
|
Posted: Wed May 18, 2011 5:01 am |
|
|
In your case the way round matters.
A crystal is a 2pin component.
The ABS13 version comes in a SMD package, with four pins. The actual crystal being across pins 1 and 4. Put it in the wrong way round, and you will be connecting your circuit to pins 2 and 3, and no actual connection will be made to the internal crystal!.....
So in this package 'direction matters'. For 99.9% of crystals, it doesn't.
Best Wishes |
|
|
Sinalux
Joined: 17 May 2011 Posts: 2
|
|
Posted: Wed May 18, 2011 3:45 pm |
|
|
Hi!
I just found that my problem is on i2c bus, not the crystal!! My uC always detect i2c bus collision. Anyone experienced something like this? _________________ Tks
Sinalux |
|
|
|