I2C not working on 18F25K20
Posted: Wed Jul 23, 2014 2:05 pm
Hi,
I'm new to this forum, and any help would be appreciated.
I have I2C code for a DS3232 clock that was compiled with the XC8 compiler and runs fine on a 18F2520. However I can get it to work on a 18F25K20. I think I am missing something re the I/O setup. Is there anything special necessary to enable the C3 and C4 pins to use the MSSP in I2C mode?
ds3232.c
I'm new to this forum, and any help would be appreciated.
I have I2C code for a DS3232 clock that was compiled with the XC8 compiler and runs fine on a 18F2520. However I can get it to work on a 18F25K20. I think I am missing something re the I/O setup. Is there anything special necessary to enable the C3 and C4 pins to use the MSSP in I2C mode?
ds3232.c
- Code: Select all
////////////////////////////////////////////////////////////////////////////////
/// DS3232.C ///
/// Driver for Real Time Clock ///
/// ///
/// ds3232_init() - Enable oscillator without clearing the seconds register -///
/// used when PIC loses power and DS1307 run from 3V BAT ///
/// - Disable squarewave output ///
/// ///
/// ds3232_set_date_time(day,mth,year,dow,hour,min,sec) Set the date/time ///
/// ///
/// ds3232_get_date(day,mth,year,dow) Get the date ///
/// ///
/// ds3232_get_time(hr,min,sec) Get the time ///
/// ///
////////////////////////////////////////////////////////////////////////////////
#include "device.h"
#include <plib\i2c.h>
#define RTC_SDA PIN_C4
#define RTC_SCL PIN_C3
int bin2bcd(int binary_value);
int bcd2bin(int bcd_value);
void ds3232_init(void)
{
BYTE seconds = 0;
OpenI2C(MASTER, SLEW_OFF);
StartI2C();
WriteI2C(0xD0); // WR to RTC
WriteI2C(0x00); // REG 0
RestartI2C();
WriteI2C(0xD1); // RD from RTC
seconds = bcd2bin(ReadI2C()); // Read current "seconds" in DS1307
// NotAckI2C();
StopI2C();
seconds &= 0x7F;
delay_us(3);
StartI2C();
WriteI2C(0xD0); // WR to RTC
WriteI2C(0x00); // REG 0
WriteI2C(bin2bcd(seconds)); // Start oscillator with current "seconds value
RestartI2C();
WriteI2C(0xD0); // WR to RTC
WriteI2C(0x0E); // Control Register
WriteI2C(0x00); // Set to 0x00
NotAckI2C();
StopI2C();
}
void ds3232_set_date_time(BYTE day, BYTE mth, BYTE year, BYTE dow, BYTE hr, BYTE min, BYTE sec)
{
sec &= 0x7F;
hr &= 0x3F;
StartI2C();
WriteI2C(0xD0); // I2C write address
WriteI2C(0x00); // Start at REG 0 - Seconds
WriteI2C(sec); // REG 0 ** Modified
WriteI2C(min); // REG 1 ** Modified
WriteI2C(hr); // REG 2 ** Modified
WriteI2C(bin2bcd(dow)); // REG 3
WriteI2C(day); // REG 4 ** Modified
WriteI2C(mth); // REG 5 ** Modified
WriteI2C(year); // REG 6 ** Modified
// i2c_write(0x80); // REG 7 - Disable squarewave output pin
StopI2C();
}
void ds3232_get_date(int *day, int *mth, int *year, int *dow)
{
StartI2C();
WriteI2C(0xD0);
WriteI2C(0x02); // Start at REG - Day of week
RestartI2C();
WriteI2C(0xD1);
*dow = bcd2bin(ReadI2C() & 0x7f); // REG 3
AckI2C();
*day = bcd2bin(ReadI2C() & 0x3f); // REG 4
AckI2C();
*mth = bcd2bin(ReadI2C() & 0x1f); // REG 5
AckI2C();
*year = bcd2bin(ReadI2C()); // REG 6
NotAckI2C();
StopI2C();
}
void ds3232_get_time(int *hr, int *min, int *sec)
{
StartI2C();
WriteI2C(0xD0);
WriteI2C(0x00); // Start at REG 0 - Seconds
RestartI2C();
WriteI2C(0xD1);
*sec = bcd2bin(ReadI2C() & 0x7f);
AckI2C();
*min = bcd2bin(ReadI2C() & 0x7f);
AckI2C();
*hr = bcd2bin(ReadI2C() & 0x3f);
NotAckI2C();
StopI2C();
}
int bin2bcd(int binary_value)
{
int temp;
int 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.
int bcd2bin(int bcd_value)
{
int 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));
}