CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to support@ccsinfo.com

I have Problem to use PCF8563 for RTC and need a driver

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
HGHK



Joined: 29 Jun 2010
Posts: 33

View user's profile Send private message Yahoo Messenger

I have Problem to use PCF8563 for RTC and need a driver
PostPosted: Tue Sep 14, 2010 10:44 pm     Reply with quote

I need a driver for PCF8563. I can't read and write in it's register using I2C. I use PIC16F87 for control. Pleas help me in it. thanks.
ckielstra



Joined: 18 Mar 2004
Posts: 3680
Location: The Netherlands

View user's profile Send private message

PostPosted: Wed Sep 15, 2010 12:08 am     Reply with quote

This forum has a search function at the top of the page. Try using it next time.
http://www.ccsinfo.com/forum/viewtopic.php?t=27988
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Wed Sep 15, 2010 9:58 am     Reply with quote

Before asking for a driver, you should look in the CCS drivers directory
on your computer. CCS has a driver for the pcf8563. Here's the file location:
Quote:

c:\program files\picc\drivers\pcf8563.c
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Wed Sep 15, 2010 1:52 pm     Reply with quote

If you don't have the file, then upgrade your compiler.
We are not allowed to post CCS files on the forum.
See this post at the top of the list:
Announcement: CCS Forum Policy and Guidelines


Stop asking me for the driver in PM's.
HGHK



Joined: 29 Jun 2010
Posts: 33

View user's profile Send private message Yahoo Messenger

my driver not work help me!
PostPosted: Tue Oct 05, 2010 1:21 am     Reply with quote

I wrote a driver for PCF8563 and Now It Does not work. Please help me if it have bug.
my driver is it:
PCF8563.c :
Code:

// PCF8563.C
// Command Set:
// PCF8563_init(void)
// PCF8563_write_byte(int8 address, int8 data)
// PCF8563_read_byte(int8 address)
// bin2bcd(int8 value)
// bcd2bin(char bcd_value)
// PCF8563_set_datetime(date_time_t *dt)
// PCF8563_read_datetime(date_time_t *dt)
// Set_Alarm(int8 AMode,PCF8563_Alarm *AT)
// config_CLKOUT(int8 mode)
// config_PCF8563_Timer(int8 mode)
// config_PCF8563_Interrupt(int8 mode,ti_tp)


#ifndef PCF8563_SDA
#define PCF8563_SDA  PIN_C4
#define PCF8563_SCL  PIN_C3
#endif

#use i2c(master, sda=PCF8563_SDA, scl=PCF8563_SCL)

#ifndef PCF8563_WRITE_ADDRESS
#define PCF8563_WRITE_ADDRESS 0xA2
#define PCF8563_READ_ADDRESS  0xA3
#endif

// Register addresses
#define PCF8563_CTRL_STATUS_REG1   0x00
#define PCF8563_CTRL_STATUS_REG2   0x01
#define PCF8563_SECONDS_REG        0x02
#define PCF8563_MINUTES_REG        0x03
#define PCF8563_HOURS_REG          0x04
#define PCF8563_DAY_REG            0x05
#define PCF8563_WEEK_REG           0x06
#define PCF8563_MONTH_REG          0x07
#define PCF8563_YEAR_REG           0x08
#define PCF8563_ALARM_MINS_REG     0x09
#define PCF8563_ALARM_HOURS_REG    0x0A
#define PCF8563_ALARM_DAY_REG      0x0B
#define PCF8563_ALARM_WEEKDAY_REG  0x0C
#define PCF8563_CTRL_CLKOUT_REG    0x0D
#define PCF8563_CTRL_TIMER_REG     0x0E
#define PCF8563_TIMER_REG          0x0F

// Commands for the Control/Status register.
#define PCF8563_START_COUNTING     0x08
#define PCF8563_STOP_COUNTING      0x28


//*************************************  for Set_Alarm()
#define PCF8563_Alarm_off          0x00
#define PCF8563_M_Mode             0x01
#define PCF8563_MH_Mode            0x04
#define PCF8563_MHW_Mode           0x07
#define PCF8563_MHD_Mode           0x0B 

//*************************************  for config_CLKOUT()
#define PCF8563_CLKOUT_off         0x00
#define PCF8563_CLKOUT_32KHz       0x80
#define PCF8563_CLKOUT_1KHz        0x81
#define PCF8563_CLKOUT_32Hz        0x82
#define PCF8563_CLKOUT_1Hz         0x83

//*************************************  for config_PCF8563_Timer()
#define PCF8563_Timer_off          0x00
#define PCF8563_Timer_4KHz         0x80
#define PCF8563_Timer_64Hz         0x81
#define PCF8563_Timer_1Hz          0x82
#define PCF8563_Timer_1_60Hz       0x83

//*************************************  for config_PCF8563_Interrupt()
#define Alarm_Interrupt_Enable     0x01
#define Timer_Interrupt_Enable     0x02
#define A_T_Interrupt_Enable       0x03
#define Timer_INT_Pulse_on         0x10
#define Timer_INT_Pulse_off        0x00

char const weekday_names[7][10] =
{
{"Sunday"},
{"Monday"},
{"Tuesday"},
{"Wednesday"},
{"Thursday"},
{"Friday"},
{"Saturday"}
};   
               
// This structure defines the user's date and time data.
// The values are stored as unsigned integers.  The user
// should declare a structure of this type in the application
// program. Then the address of the structure should be
// passed to the PCF8563 read/write functions in this
// driver, whenever you want to talk to the chip.
typedef struct
{
int8 seconds;    // 0 to 59
int8 minutes;    // 0 to 59
int8 hours;      // 0 to 23  (24-hour time)
int8 day;        // 1 to 31
int8 weekday;    // 0 = Sunday, 1 = Monday, etc.
int8 month;      // 1 to 12
int8 year;       // 00 to 99
}date_time_t;

typedef struct
{
int8 minutes;    // 0 to 59
int8 hours;      // 0 to 23  (24-hour time)
int8 day;        // 1 to 31
int8 weekday;    // 0 = Sunday, 1 = Monday, etc.
}PCF8563_Alarm;

int8 LV_sec,C_Mon;
#bit LowVoltage = LV_sec.7
#bit Century = C_Mon.7


//----------------------------------------------
void PCF8563_write_byte(int8 address, int8 data)
{
disable_interrupts(GLOBAL);
i2c_start();
i2c_write(PCF8563_WRITE_ADDRESS);
i2c_write(address);
i2c_write(data);
i2c_stop();
enable_interrupts(GLOBAL);
}   

//----------------------------------------------
int8 PCF8563_read_byte(int8 address)
{
int8 retval;
disable_interrupts(GLOBAL);
i2c_start();
i2c_write(PCF8563_WRITE_ADDRESS);
i2c_write(address);
i2c_start();
i2c_write(PCF8563_READ_ADDRESS);
retval = i2c_read(0);
i2c_stop();
enable_interrupts(GLOBAL);
return(retval);
}   

//----------------------------------------------
//           PCF8563 Initial             //

void PCF8563_init(void)
{
PCF8563_write_byte(PCF8563_CTRL_STATUS_REG1,PCF8563_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.

int8 bin2bcd(int8 value)
{
char retval;

retval = 0;

while(1)
  {
   // Get the tens digit by doing multiple subtraction
   // of 10 from the binary value.
   if(value >= 10)
     {
      value -= 10;
      retval += 0x10;
     }
   else // Get the ones digit by adding the remainder.
     {
      retval += value;
      break;
     }
   }

return(retval);
}

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

char bcd2bin(char bcd_value)
{
char temp;

temp = bcd_value;

// Shifting the upper digit right by 1 is
// the same as multiplying it 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));

}
//----------------------------------------------
//----------------------------------------------

void PCF8563_set_datetime(date_time_t *dt)
{
int8 bcd_sec;
int8 bcd_min;
int8 bcd_hrs;
int8 bcd_day;
int8 bcd_mon;
int8 bcd_yer;
int8 wek;
// Convert the input date/time into BCD values
// that are formatted for the PCF8563 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);
bcd_yer = bin2bcd(dt->year);
wek     = dt->weekday;
// Stop the RTC from counting, before we write to
// the date and time registers.
PCF8563_write_byte(PCF8563_CTRL_STATUS_REG1,PCF8563_STOP_COUNTING);

// Write to the date and time registers.  Disable interrupts
// so they can't disrupt the i2c operations.
disable_interrupts(GLOBAL);
i2c_start();
i2c_write(PCF8563_WRITE_ADDRESS);
i2c_write(PCF8563_SECONDS_REG);   // Start at seconds reg.   
i2c_write(bcd_sec);
i2c_write(bcd_min);
i2c_write(bcd_hrs);   
i2c_write(bcd_day);
i2c_write(wek);
i2c_write(bcd_mon);
i2c_write(bcd_yer);
i2c_stop();
enable_interrupts(GLOBAL);

// Now allow the PCF8563 to start counting again.

PCF8563_write_byte(PCF8563_CTRL_STATUS_REG1,PCF8563_START_COUNTING);

}
//----------------------------------------------

//----------------------------------------------
// Read the Date and Time from the hardware registers
// in the PCF8563.   We don't have to disable counting
// during read operations, because according to the data
// sheet, if any of the lower registers (1 to 7) is read,
// all of them are loaded into "capture" registers.
// All further reading within that cycle is done from
// those registers.

void PCF8563_read_datetime(date_time_t *dt)
{
int8 bcd_sec;
int8 bcd_min;
int8 bcd_hrs;
int8 bcd_day;
int8 wek;
int8 bcd_mon;
int8 bcd_yer;

//  LowVoltage = VL_sec.7
//  Century    = C_Mon.7

// Disable interrupts so the i2c process is not disrupted.
disable_interrupts(GLOBAL);

// Read the date/time registers inside the PCF8563.
i2c_start();
i2c_write(PCF8563_WRITE_ADDRESS);
i2c_write(PCF8563_SECONDS_REG);   // Start at seconds reg.
i2c_start();
i2c_write(PCF8563_READ_ADDRESS);

LV_sec  = i2c_read();     
bcd_min = i2c_read();     
bcd_hrs = i2c_read();
bcd_day = i2c_read();
wek     = i2c_read();
C_Mon   = i2c_read();
bcd_yer = i2c_read(0);

i2c_stop();

enable_interrupts(GLOBAL);

// Convert the date/time values from BCD to
// unsigned 8-bit integers.  Unpack the bits
// in the PCF8563 registers where required.
bcd_sec     = LV_sec & 0x7F;
bcd_mon     = C_Mon  & 0x7F;
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 =    wek & 0x07;
dt->year    = bcd2bin(bcd_yer);   

}
//----------------------------------------------
void Set_Alarm(int8 AMode)
{
if (AMode == 0x00)
   {
    disable_interrupts(GLOBAL);
    i2c_start();
    i2c_write(PCF8563_WRITE_ADDRESS);
    i2c_write(PCF8563_ALARM_MINS_REG);   // Start at alarm min reg.   
    i2c_write(0x80);
    i2c_write(0x80);
    i2c_write(0x80);   
    i2c_write(0x80);
    i2c_stop();
    enable_interrupts(GLOBAL);
   }
}
void Set_Alarm(int8 AMode,PCF8563_Alarm *AT)
{
int8 min = 0x80;
int8 hrs = 0x80;
int8 day = 0x80;
int8 wek = 0x80;
 
switch (AMode){
          case 0x01: min = AT->minutes;
                     break;
          case 0x04: min = AT->minutes;
                     hrs = AT->hours;
                     break;
          case 0x07: min = AT->minutes;
                     hrs = AT->hours;
                     wek = AT->weekday;
                     break;
          case 0x0B: min = AT->minutes;
                     hrs = AT->hours;
                     day = AT->day;
                     break;
               }

disable_interrupts(GLOBAL);
i2c_start();
i2c_write(PCF8563_WRITE_ADDRESS);
i2c_write(PCF8563_ALARM_MINS_REG);   // Start at alarm min reg.   
i2c_write(min);
i2c_write(hrs);
i2c_write(day);   
i2c_write(wek);
i2c_stop();
enable_interrupts(GLOBAL);

}

//----------------------------------------------

void config_CLKOUT(int8 mode)
{
PCF8563_write_byte(PCF8563_CTRL_CLKOUT_REG, mode);
}

//----------------------------------------------

void config_PCF8563_Timer(int8 mode)
{
PCF8563_write_byte(PCF8563_CTRL_TIMER_REG, mode);
}

//----------------------------------------------

void config_PCF8563_Interrupt(int8 mode,ti_tp)
{
mode = mode | ti_tp;
PCF8563_write_byte(PCF8563_CTRL_STATUS_REG2, mode);
}

//----------------------------------------------


Help me Please, Thanks a lot.
asdf85



Joined: 03 Jan 2011
Posts: 34

View user's profile Send private message

PostPosted: Wed Dec 28, 2011 1:44 am     Reply with quote

Hi,

How do I use the provided driver?

I do a #include "pcf8563.c" . But when I call this function "rtc_get_datetime();", it says 'A numeric expression must appear here'.

If I simply put a random number or variable in the brackets, then it compiles, but I see no data.

I think I'm calling it wrongly? Basically I just need to know how to use the write and read functions of this driver. I'm not familiar with structures, and I've never included other files in my project before, so I'm kinda clueless on this.

Thanks for the help.
Ttelmah



Joined: 11 Mar 2010
Posts: 19346

View user's profile Send private message

PostPosted: Wed Dec 28, 2011 2:59 am     Reply with quote

Try reading the text at the top of the driver.
All CCS drivers have a set of comments at the top describing the functions and variables involved (worthwhile practice to follow in general....).

Both rtc_get_datetime, and rtc_set_datetime, need to be called with the _address_ of a TIME_STRUCT structure. The functions then put/get the time into/out of this structure.
Putting a number in here instead of the address means the data will be written to a point in the RAM, defined by the number, and _will_ result in RAM being corrupted.
So you need to declare a TIME_STRUCT variable, and pass it's address to the function.

Best Wishes
temtronic



Joined: 01 Jul 2010
Posts: 9164
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Wed Dec 28, 2011 7:03 am     Reply with quote

Also be sure to use the correct value pullup resistors on the I2C bus lines !
If running 5V VDD, I use 3k3 resistors.
asdf85



Joined: 03 Jan 2011
Posts: 34

View user's profile Send private message

PostPosted: Wed Dec 28, 2011 7:38 pm     Reply with quote

I still dont get it and can't get it working. How do i call it with the '_address_ of a TIME_STRUCT structure' ? I tried creating an INT variable and pointing it to that adress, but that doesnt work.

This part is confusing too
Code:

void rtc_get_datetime(TIME_STRUCT *pTs)


How come there's no need for a comma after the 'TIME_STRUCT'? I also dont see the pointer '*pTs' being initialized anywhere.

Could you give an example of how to call this function, with whatever nescessary initialized variable/pointers/address/structure?

And how do i receive the response?
I really am quite blur when it comes to structures.

Thanks alot
dyeatman



Joined: 06 Sep 2003
Posts: 1924
Location: Norman, OK

View user's profile Send private message

PostPosted: Wed Dec 28, 2011 8:26 pm     Reply with quote

Take a look at the example file ex_rtctimer.c in the examples directory
and the time.h file in the drivers directory for some info.

Also try here:
http://pdfserv.maxim-ic.com/en/an/AN517.pdf

The struct is called tm_struct. examine all the code to see how it is used further down.
_________________
Google and Forum Search are some of your best tools!!!!
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group