mariuszoll
Member level 5
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.
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.