Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

[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(y);
}

// 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.

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top