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

Problem with the real time clock PCF8563

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



Joined: 20 Jul 2006
Posts: 29

View user's profile Send private message Send e-mail MSN Messenger

Problem with the real time clock PCF8563
PostPosted: Sun Jul 22, 2007 7:33 pm     Reply with quote

Hi. I am trying to built a system with the PCF8563 chip. But I got into troubles when trying to make it work. I can't set the time correctly. I program it to be set at 10:5:0 (time) and 15/7/7 (date day/month/year). In the display I get 45:15:0 (time) and the correct date. What happens is thar the seconds count correctly from 0 to 59. The minutes, moreover, are counting wrongly, i.e., when the seconds go from 59 to 0, the minutes don't go from 15 to 16, they go from 15 to 40 and worst, not when the seconds go from 59 to 0, but when they go from 39 to 40. The date is shown correctly but I don't know if it is counting correctly.

I tried to built the driver by myself. I used the functions to manipulate BCD from the driver for PCF8583 posted in this forum. I tried to search the internet for drivers for the PCF8563, but I wasn't successful.

Here goes the program I've written. The lines that configure the display are not shown.

Code:

int8 dia, mes, ano, hor, min, seg, bdia, bmes, bano, bhor, bmin, bseg;

int8 bcd2bin(int8 bcd)
{
int8 temp;
temp = bcd;
temp >>= 1;
temp &= 0x78;
return(temp + (temp >> 2) + (bcd & 0x0f));

}
int8 bin2bcd(int8 value)
{
int8 retval;
retval = 0;
while(1)
  {
   if(value >= 10)
     {
      value -= 10;
      retval += 0x10;
     }
   else // Get the ones digit by adding the remainder.
     {
      retval += value;
      break;
     }
   }
return(retval);
}

void inicia_RTC(){   //initiates the RTC
   //configurar o RTC.
   i2c_start();
   i2c_write(0xa2); //write address of the RTC.
   i2c_write(0x00); //control status 1.
   i2c_write(0);    //normal operation mode.
   i2c_stop();
   i2c_start();
   i2c_write(0xa2);
   i2c_write(0x01); //control status 2.
   i2c_write(0);    //disables the timer and alarm functions.
   i2c_stop();
   i2c_start();
   i2c_write(0xa2);
   i2c_write(0x0D); //address of the clock frequency.
   i2c_write(0);    //sets it to 32768Hz.
   i2c_stop();
   i2c_start();
   i2c_write(0xa2);
   i2c_write(0x0E); //address of the alarms.
   i2c_write(0);    //disable them
   i2c_stop();
}

//read time and date.
void le_horas (){
   output_high(PIN_C0);          //these are the SCL and the SDA lines.
   output_high(PIN_C1);
   //read seconds.
   i2c_start();
   i2c_write(0xa2);
   i2c_write(0x02); //address of the seconds.
   i2c_start();
   i2c_write(0xa3); //read address of the RTC.
   bseg = i2c_read();
   i2c_stop();
   //read minutes.
   i2c_start();
   i2c_write(0xa2);
   i2c_write(0x03); //address of the minutes.
   i2c_start();
   i2c_write(0xa3);
   bmin = i2c_read();
   i2c_stop();
   //read hours.
   i2c_start();
   i2c_write(0xa2);
   i2c_write(0x04); //address of the hours.
   i2c_start();
   i2c_write(0xa3);
   bhor = i2c_read();
   i2c_stop();
   //read day.
   i2c_start();
   i2c_write(0xa2);
   i2c_write(0x05); //address of the day.
   i2c_start();
   i2c_write(0xa3);
   bdia = i2c_read();
   i2c_stop();
   //read month.
   i2c_start();
   i2c_write(0xa2);
   i2c_write(0x07); //address of the month.
   i2c_start();
   i2c_write(0xa3);
   bmes = i2c_read();
   i2c_stop();
   //ler ano.
   i2c_start();
   i2c_write(0xa2);
   i2c_write(0x08); //address of the years.
   i2c_start();
   i2c_write(0xa3);
   bano = i2c_read();
   i2c_stop();
seg = bcd2bin(bseg & 0x7F);
min = bcd2bin(bmin & 0x7F);
hor = bcd2bin(bhor & 0x3F);
dia = bcd2bin(bdia & 0x3F);
mes = bcd2bin(bmes & 0x1F);
ano = bcd2bin(bano);
}

//set the time and date.
void acertar_horas(){
   output_high(PIN_C0); //SDA and SCL lines.
   output_high(PIN_C1);
bmin = bin2bcd(min);
bhor = bin2bcd(hor);
bdia = bin2bcd(dia);
bmes = bin2bcd(mes);
bano = bin2bcd(ano);
   i2c_start();
   i2c_write(0xa2);
   i2c_write(0x00);
   i2c_write(0x20); //the RTC stops counting.
   i2c_stop();
   //set the second.
   i2c_start();
   i2c_write(0xa2);
   i2c_write(0x02); //write the seconds.
   i2c_write(0);
   i2c_stop();
   //set the minute.
   i2c_start();
   i2c_write(0xa2);
   i2c_write(0x03); //write the minutes.
   i2c_write(min);
   i2c_stop();
   //set the hour.
   i2c_start();
   i2c_write(0xa2);
   i2c_write(0x04); //write the hours.
   i2c_write(hor);
   i2c_stop();
   //set the day.
   i2c_start();
   i2c_write(0xa2);
   i2c_write(0x05); //write the days.
   i2c_write(dia);
   i2c_stop();
   //set the month.
   i2c_start();
   i2c_write(0xa2);
   i2c_write(0x07); //write the months.
   i2c_write(mes);
   i2c_stop();
   //set the year.
   i2c_start();
   i2c_write(0xa2);
   i2c_write(0x08); //write the years.
   i2c_write(ano);
   i2c_stop();
   i2c_start();
   inicia_RTC();
}

void main()
{
inicia_RTC();
while (true){

le_teclado(); //here, it gets the number pressed in a keypad, stores it in the variable "tec" and verifies the instruction.
if (tec==5){
  min = 0x05;
  hor = 0x10;
  dia = 0x15;
  mes = 0x07;
  ano = 0x07;
  acertar_horas(); //sets the time and date.
}
if (tec==6){
  min = 0;
  hor = 0;
  dia = 0;
  mes = 0;
  ano = 0;
  acertar_horas(); //sets the time and date.
}

le_horas(); //read the time and date and shows it in the display.
   lcd_gotoxy(9,1);
   printf(lcd_putc,"%u:%u:%u", hor, min, seg);
   lcd_gotoxy(9,2);
   printf(lcd_putc,"%u/%u/%u", dia, mes, ano);

output_high(PIN_B0); //this is a led pin.
delay_ms(50);
output_low(PIN_B0);
delay_ms(50);
}}


The configuration of the PIC18F2455 that I am using is the following:
Code:
#FUSES NOWDT, WDT128, XT, NOPROTECT, NOBROWNOUT, BORV20, NOPUT, NOCPD, NOSTVREN, NODEBUG, NOLVP, NOWRT, NOWRTD, NOIESO, NOFCMEN, NOPBADEN, NOWRTC, NOWRTB, NOEBTR, NOEBTRB, NOCPB, NOLPT1OSC, NOMCLR, NOXINST, PLL1
#use delay(clock=4000000)
#use i2c(Master,sda=PIN_C1,scl=PIN_C0)
   setup_adc_ports(NO_ANALOGS|VSS_VDD);
   setup_adc(ADC_OFF|ADC_TAD_MUL_0);
   setup_spi(FALSE);
   setup_wdt(WDT_OFF);
   setup_timer_0(RTCC_INTERNAL);
   setup_timer_1(T1_DISABLED);
   setup_timer_2(T2_DISABLED,0,1);
   setup_timer_3(T3_DISABLED|T3_DIV_BY_1);
   setup_comparator(NC_NC_NC_NC);
   setup_vref(FALSE);
   setup_low_volt_detect(FALSE);
   setup_oscillator(False);



Any help would be of great value.
Thanks for your attention.
Otavio Gomes.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Sun Jul 22, 2007 7:52 pm     Reply with quote

I didn't look at your code in detail, but I noticed the following problems:
Quote:

output_high(PIN_C0); //SDA and SCL lines.
output_high(PIN_C1);

This is wrong. The i2c bus is never driven high by the PIC. It's either
driven low, or allowed to be pulled high by the pull-up resistors.
The CCS driver code should set those two pins to "floating" by itself.
If you still want to do it, you should use the output_float() function.


Quote:

i2c_start();
i2c_write(0xa2);
i2c_write(0x02); //address of the seconds.
i2c_start();
i2c_write(0xa3); //read address of the RTC.
bseg = i2c_read();
i2c_stop();

You have several places in your code where you do a single i2c read
operation. The PCF8563 data sheet says that the last read operation
in an i2c operation must do a "NAK". Look at the bit diagrams in
Figures 14 and 15 in the data sheet, for examples. They show
"no acknowledgment from Master" on the last read operations.
In CCS, you do a NAK by giving the i2c_read() function a parameter of 0.
Example:
Code:
data = i2c_read(0);

You need to fix this in several places in your code.
otavio_fisica



Joined: 20 Jul 2006
Posts: 29

View user's profile Send private message Send e-mail MSN Messenger

That's it!!
PostPosted: Sun Jul 22, 2007 8:54 pm     Reply with quote

Thank you PCMprogrammer. You have just solved my problem. It was the i2c_read(0). I haven't paid enough attention to the datasheet. Thank you very much.
KaraMuraT



Joined: 16 May 2006
Posts: 65
Location: Ankara/Turkey

View user's profile Send private message Send e-mail

PostPosted: Mon Jul 23, 2007 5:56 am     Reply with quote

PCM Programmer already mentioned the big problems. I can add some imprevements.

You do not need to restart for every register. 8563 switches to the next register every time you read/write. For example if you write first to minute register, than PCF8563 is ready to get seconds, you can write directly the seconds value. You can find the register order in the datasheet.
_________________
/// KMT
/// www.muratursavas.com
Guest








Yes.
PostPosted: Mon Jul 23, 2007 6:18 am     Reply with quote

Thank you KaraMuraT. I will implement this changes. It will make the code simpler. I will post the result here later.
Thank you again people.
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