[SOLVED] Help with RTC(PCF8583) using PIC18F4550

Status
Not open for further replies.

mariuszoll

Member level 5
Joined
Aug 28, 2012
Messages
82
Helped
1
Reputation
2
Reaction score
0
Trophy points
1,286
Activity points
2,147
Hi,

I am working on a calendar/clock application that uses PCF8583 RTC and PIC18F4550.The pull-up resistors on SCL and SDA are both of 4k7. I use serial communication (USART) and Hyperterminal to display the information. I display the date on dd/mm/yy format and the time on hh/mm/ss format. It does not work properly as expected. It displays:

Date: 45/25/12
Time: 45:165:1

As far the seconds are concerned, they are incrementing correctly from 1 to 59.

Could you help me please to fix this problem?

Attached you can find my code:

#include <p18f4550.h>
#include <delays.h>
#include <sw_uart.h>
#include <i2c.h>

// Pragma, internal register configuration

#pragma config FOSC = INTOSCIO_EC //Internal oscillator, port function on RA6, EC used by USB
#pragma config WDT = OFF // watch dog disabled
#pragma config IESO = OFF //Oscillator Switchover mode disabled
//#pragma config PWRT = OFF //PWRT disabled
#pragma config BORV = 2 // output voltage test 2V
#pragma config PBADEN=OFF //PORTB<4:0> pins are configured as digital I/O on Reset
#pragma config STVREN=OFF //Stack full/underflow will not cause Reset
#pragma config LVP=OFF //Single-Supply ICSP disabled
#pragma config XINST=OFF //Instruction set extension and Indexed Addressing mode disabled (Legacy mode)


// definitions

#define PCF8583_WRITE_ADDRESS 0xA0
#define PCF8583_READ_ADDRESS 0xA1

// Register addresses
#define PCF8583_CTRL_STATUS_REG 0x00
#define PCF8583_100S_REG 0x01
#define PCF8583_SECONDS_REG 0x02
#define PCF8583_MINUTES_REG 0x03
#define PCF8583_HOURS_REG 0x04
#define PCF8583_DATE_REG 0x05
#define PCF8583_MONTHS_REG 0x06
#define PCF8583_TIMER_REG 0x07

#define PCF8583_ALARM_CONTROL_REG 0x08
#define PCF8583_ALARM_100S_REG 0x09
#define PCF8583_ALARM_SECS_REG 0x0A
#define PCF8583_ALARM_MINS_REG 0x0B
#define PCF8583_ALARM_HOURS_REG 0x0C
#define PCF8583_ALARM_DATE_REG 0x0D
#define PCF8583_ALARM_MONTHS_REG 0x0E
#define PCF8583_ALARM_TIMER_REG 0x0F

// Use the first NVRAM address for the year byte.
#define PCF8583_YEAR_REG 0x10


// Commands for the Control/Status register.
#define PCF8583_START_COUNTING 0x00
#define PCF8583_STOP_COUNTING 0x80

// Structure defines the user's date and time data.
typedef struct{
unsigned char seconds; // 0 to 59
unsigned char minutes; // 0 to 59
unsigned char hours; // 0 to 23
unsigned char day; // 1 to 31
unsigned char month; // 1 to 12
unsigned char year; // 0 to 99
unsigned char weekday; // 0=Sunday, 1=Monday, etc
} date_time_t;

// Variables

/** L O C A L F U N C T I O N S *******************************************/

void init_UART(void)
{
TXSTAbits.TX9=0;
TXSTAbits.TXEN=1;
TXSTAbits.SYNC=0;
TXSTAbits.BRGH=1;
TXSTAbits.TX9D=0;
RCSTAbits.SPEN=1;
BAUDCONbits.BRG16=0;
SPBRG=25; // 9600KBaud
}

void PCF8583_write_byte(char address, char data)
{
IdleI2C();
StartI2C(); //start
while(SSPCON2bits.SEN);
Delay1TCY(); // delay 5us (see datasheet pg20)
Delay1TCY();
Delay1TCY();
Delay1TCY();

WriteI2C(PCF8583_WRITE_ADDRESS); // address and write flag
IdleI2C();
WriteI2C(address);
IdleI2C();
WriteI2C(data);
IdleI2C();
StopI2C();
while(SSPCON2bits.PEN); // stop
Delay1TCY(); // delay 4us (see datasheet pg20)
Delay1TCY();
Delay1TCY();
Delay1TCY();
}

char PCF8583_read_byte(char address)
{
char retval;

IdleI2C();
StartI2C(); //start
while(SSPCON2bits.SEN);

Delay1TCY(); // delay 5us (see datasheet pg20)
Delay1TCY();
Delay1TCY();
Delay1TCY();

WriteI2C(PCF8583_WRITE_ADDRESS); // address and write flag
IdleI2C();
WriteI2C(address);
IdleI2C();

RestartI2C(); //restart
while(SSPCON2bits.RSEN);

Delay1TCY(); // delay 5us (see datasheet pg20)
Delay1TCY();
Delay1TCY();
Delay1TCY();

WriteI2C(PCF8583_READ_ADDRESS); //address and read flag
IdleI2C();
retval=ReadI2C();
IdleI2C();

StopI2C();
while(SSPCON2bits.PEN); // stop
Delay1TCY(); // delay 4us (see datasheet pg20)
Delay1TCY();
Delay1TCY();
Delay1TCY();

return(retval);
}

void PCF8583_init(void)
{
PCF8583_write_byte(PCF8583_CTRL_STATUS_REG,PCF8583_START_COUNTING);
}

// This function converts an 8 bit binary value
// to an 8 bit BCD value.
// The input range must be from 0 to 99

unsigned char bin2bcd(unsigned char x)
{
unsigned char y;

y=(x / 10) << 4;
y= y | (x % 10);
return;
}

// This function converts an 8 bit BCD value to
// an 8 bit binary value.
// The input range must be from 00 to 99.

unsigned char bcd2bin(unsigned char x)
{
unsigned char binary;
binary = ((x & 0xF0 )>>4 ) * 10 + (x & 0x0F);
return (binary);
}

void PCF8583_set_datetime( date_time_t *dt)
{
unsigned char bcd_sec;
unsigned char bcd_min;
unsigned char bcd_hrs;
unsigned char bcd_day;
unsigned char bcd_mon;

// Convert the input date/time into BCD values
// that are formatted for the PCF8583 registers
bcd_sec=bin2bcd(dt->seconds);
bcd_min=bin2bcd(dt->minutes);
bcd_hrs=bin2bcd(dt->hours);
bcd_day=bin2bcd(dt->day) | (dt->year <<6);
bcd_mon=bin2bcd(dt->month) |(dt->weekday << 5);

// Stop the RTC from counting, before we write to the date and time registers
PCF8583_write_byte(PCF8583_CTRL_STATUS_REG,PCF8583_STOP_COUNTING);

// Write to the date and time registers
IdleI2C();
StartI2C(); //start
while(SSPCON2bits.SEN);
Delay1TCY(); // delay 5us (see datasheet pg20)
Delay1TCY();
Delay1TCY();
Delay1TCY();

WriteI2C(PCF8583_WRITE_ADDRESS); // address and write flag
IdleI2C();
WriteI2C(PCF8583_100S_REG); // Start at 100's reg
IdleI2C();
WriteI2C(0x00); // Set 100's reg=0
IdleI2C();
WriteI2C(bcd_sec);
IdleI2C();
WriteI2C(bcd_min);
IdleI2C();
WriteI2C(bcd_hrs);
IdleI2C();
WriteI2C(bcd_day);
IdleI2C();
WriteI2C(bcd_mon);
IdleI2C();

StopI2C();
while(SSPCON2bits.PEN); // stop
Delay1TCY(); // delay 4us (see datasheet pg20)
Delay1TCY();
Delay1TCY();
Delay1TCY();

// Write the year to the first NVRAM location. Live it in binary format.
PCF8583_write_byte(PCF8583_YEAR_REG,dt->year);

// Now allow the RTC to start counting again
PCF8583_write_byte(PCF8583_CTRL_STATUS_REG,PCF8583_START_COUNTING);
}


//Read the Date and Time from the hardware registers in the PCF8583
void PCF8583_read_datetime(date_time_t *dt)
{
unsigned char year_bits;
unsigned char year;

unsigned char bcd_sec;
unsigned char bcd_min;
unsigned char bcd_hrs;
unsigned char bcd_day;
unsigned char bcd_mon;

// Read the date/time registers inside the PCF8583
IdleI2C();
StartI2C(); //start
while(SSPCON2bits.SEN);
Delay1TCY(); // delay 5us (see datasheet pg20)
Delay1TCY();
Delay1TCY();
Delay1TCY();

WriteI2C(PCF8583_WRITE_ADDRESS); // address and write flag
IdleI2C();
WriteI2C(PCF8583_SECONDS_REG); // Start at secods reg
IdleI2C();

RestartI2C(); //start
while(SSPCON2bits.RSEN);
Delay1TCY(); // delay 5us (see datasheet pg20)
Delay1TCY();
Delay1TCY();
Delay1TCY();
WriteI2C(PCF8583_READ_ADDRESS); // address and write flag
IdleI2C();

bcd_sec=ReadI2C();
IdleI2C();
bcd_min=ReadI2C();
IdleI2C();
bcd_hrs=ReadI2C();
IdleI2C();
bcd_day=ReadI2C();
IdleI2C();
bcd_mon=ReadI2C();
IdleI2C();

StopI2C();
while(SSPCON2bits.PEN); // stop
Delay1TCY(); // delay 4us (see datasheet pg20)
Delay1TCY();
Delay1TCY();
Delay1TCY();

// Convert the date/time values from BCD to
// unsigned 8-bit integers. Unpack the bits
// in the PCF8583 registers where required.
dt->seconds = bcd2bin(bcd_sec);
dt->minutes = bcd2bin(bcd_min);
dt->hours = bcd2bin(bcd_hrs & 0x3F);
dt->day = bcd2bin(bcd_day & 0x3F);
dt->month = bcd2bin(bcd_mon & 0x1F);
dt->weekday=bcd_mon >> 5;
year_bits=bcd_day >> 6 ;

// Read the year byte from NVRAM.
// This is an added feature of this driver.
year = PCF8583_read_byte(PCF8583_YEAR_REG);

/* //Check if the two " year bits " were incremented by the PCF8583.
while(year_bits!= (year & 3)) year++;

dt->year=year;

// Now update the year byte in the NVRAM inside the PCF8583
PCF8583_write_byte(PCF8583_YEAR_REG, year); */

}

void print_date_time(char t)
{
int k,n,j,m,c;
unsigned char data;
char string[5];

data=t;
n=data;
j=0;

while(n!=0)
{
c=n%10;
n=n/10;
string[j]=c+48;
j++;
}

m=j-1;

while(m>=0)
{
WriteUSART(string[m]);
while(!TXSTAbits.TRMT);
m--;
}
}

///////////////////functia main///////////////////////////////////////////

void main(void)
{

date_time_t dt;

//Outputs:

TRISCbits.TRISC6=0; // UART__TX

//Inputs:

TRISBbits.TRISB0=1; // I2C_SDA
TRISBbits.TRISB1=1; // I2C_SCL
TRISCbits.TRISC7=1; // UART__RX

// Oscillator frequency

OSCCON=0b01100110; // 4MHz

// the configuration of the functions of port pins

ADCON1=0b00001111; // digital port configured

// Initializations

init_UART();
TXREG=12; // new page

// I2C settings

SSPSTAT=0x80; // SLEW RATE CONTROL DISABLED FOR std mode (100khz)
SSPCON1=0x28; // i2c master mode, serial synch enable
SSPCON2=0x00;
SSPADD=0x09; // for 100Khz

PCF8583_init();

dt.seconds=0; // 0 seconds
dt.minutes=25; // 25 minutes
dt.hours=10; // 10am - 24-hour format
dt.day=27; // 27
dt.month=8; // August
dt.weekday=1; // Monday
dt.year=12; // 2012

PCF8583_set_datetime(&dt);

while(1)
{
// Read the date and time from the PCF8583 and dispaly it once per second
Delay10KTCYx(100);

PCF8583_read_datetime(&dt);

print_date_time(dt.weekday);
TXREG=32; // space
TXREG=32; // space
print_date_time(dt.day);
TXREG=47; // /
print_date_time(dt.month);
TXREG=47;
print_date_time(dt.year);
TXREG=32; // space
TXREG=32; // space

print_date_time(dt.hours);
TXREG=58; // :
print_date_time(dt.minutes);
TXREG=58;
print_date_time(dt.seconds);
TXREG=10; // new line
TXREG=13; //carriage return

}
} // main



Thank you in advance.
 

Status
Not open for further replies.
Cookies are required to use this site. You must accept them to continue using the site. Learn more…