|
|
View previous topic :: View next topic |
Author |
Message |
otavio_fisica
Joined: 20 Jul 2006 Posts: 29
|
Problem with the real time clock PCF8563 |
Posted: Sun Jul 22, 2007 7:33 pm |
|
|
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
|
|
Posted: Sun Jul 22, 2007 7:52 pm |
|
|
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
|
That's it!! |
Posted: Sun Jul 22, 2007 8:54 pm |
|
|
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
|
|
Posted: Mon Jul 23, 2007 5:56 am |
|
|
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. |
Posted: Mon Jul 23, 2007 6:18 am |
|
|
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. |
|
|
|
|
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
|