Forum: Mikrocontroller und Digitale Elektronik I2C RTC : PCF8563 lesen geht schreiben nicht !


von Neubi (Gast)


Lesenswert?

hey,

hab eine I2C RTC (PCF8563). das auslesen der uhrzeit funktioniert 
problemlos; dh der slave antwortet brav mit allen ack's etc. nur das 
schreiben der gewünschten uhrzeit ist mir irgendwie unmöglich ...

genauer : SCHREIBEN der uhrzeit
- start setzen   -> OK
- slaveadresse (0xA2) schreiben   -> OK
- slave setzt ack  -> OK
- registerindex (0x02) schreiben -> OK
- KEIN ack vom slave ???? -->> NOK !!


fehler bereits ausgeschlossen :
- fclk auf ein minimum reduziert -> keine besserung
- mit osci signale gemessen -> alles schön sauber
- keine kollision mit anderen i2c bausteinen



.... hat jemand von euch schon mal so ein verhalten gehabt ???!

für jede hilfe dankbar,
thx neubi

von Hauke S. (hauke)


Lesenswert?

Probier evt mal meinen I²C Sniffer aus.

Findest du unter:
Beitrag "I2C Monitor mit Mega8"
Der aktuelle Code ist im drittletzten Post.

Gib einfach mal den gelogten Sniff an, dann kan man dir evt. 
weiterhelfen.

cu
Hauke

von Frank N. (betafrank)


Lesenswert?

Hallo Neubi,

hab mal zusammenkopiert, läuft bei mir auf nem Mega128.
1
//iic.c:////////////////////////////////////////////////
2
/******************************************************/
3
void init_iic(void){
4
   TWSR = 0;         //Prescaler
5
   TWBR = (F_CPU / 100000UL - 16) / 2;     // 100kHz
6
}
7
/******************************************************/
8
int start_iic(unsigned char address){
9
   /* Returnwerte:
10
   * 0 -> Startbedinung erfolgreich gesendet
11
   * 1 -> Probleme beim sender der Start-Bedinung
12
   * 2 -> Probleme beim senden der Addresse
13
   *      bzw. kein Device mit der angegebenen Addresse
14
   */
15
  //Senden der START Bedingung
16
  TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN);
17
  //Warten bis TWI Bedingung gesendet wurde
18
  while(!(TWCR & (1<<TWINT)));
19
  //TWI Status berprfen
20
  if((TWSR & 0xF8) != TW_START) return 1;
21
  //Adresse des anzusprechenden Devices senden
22
  TWDR = address;
23
  TWCR = (1<<TWINT) | (1<<TWEN);
24
  //Warten bis TWI Bedingung gesendet wurde
25
  while(!(TWCR & (1<<TWINT)));
26
  //TWI Status überprüfen
27
  if((TWSR & 0xF8) != TW_MT_SLA_ACK) return 2;
28
  return 0;
29
}
30
/******************************************************/
31
void write_iic(U8 data){
32
  TWDR = data;
33
  TWCR = (1<<TWINT) | (1<<TWEN);
34
  //Warten bis TWI Bedingung gesendet wurde
35
  while(!(TWCR & (1<<TWINT)));
36
}
37
/******************************************************/
38
void stop_iic(void){
39
  TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWSTO);
40
}
41
42
//rtc.c:////////////////////////////////////////////////
43
44
#define RTC_WR 0xA2         // Schreibadresse PCF8563
45
#define  BIN2BCD(b) (((b)%10) | (((b)/10)<<4))
46
/******************************************************/
47
void write_time_rtc(void){
48
   start_iic(RTC_WR);
49
   write_iic(0x02);
50
   write_iic(BIN2BCD(gtime.sec));
51
   write_iic(BIN2BCD(gtime.min));
52
   write_iic(BIN2BCD(gtime.hour));
53
   stop_iic();
54
}

von Patrick L. (pazulator)


Lesenswert?

Hallo Frank!

Hast du auch den code fürs auslesen?

Wär echt nett! Danke!

von Frank N. (betafrank)


Lesenswert?

Hier ist er:
1
#define RTC_RD 0xA3         // Leseadresse PCF8563
2
#define  BCD2BIN(b) (((b)&0xf) + ((b)>>4)*10)
3
void read_rtc(void){
4
   //Time
5
   start_iic(RTC_WR);
6
   write_iic(0x02);
7
   rep_start_iic(RTC_RD);
8
   gtime.sec  = read_iic_ack() & 0x7F;
9
   gtime.min  = read_iic_ack() & 0x7F;
10
   gtime.hour = read_iic_ack() & 0x3F;
11
   gtime.sec  = BCD2BIN(gtime.sec);
12
   gtime.min  = BCD2BIN(gtime.min);
13
   gtime.hour = BCD2BIN(gtime.hour);
14
   //Date
15
   gdate.day  = read_iic_ack() & 0x3F;
16
                read_iic_ack();   //Dummyread Wochentag == egal
17
   gdate.mon  = read_iic_ack() & 0x1F;
18
   gdate.year = read_iic_nack();
19
   stop_iic();
20
   gdate.day  = BCD2BIN(gdate.day);
21
   gdate.mon  = BCD2BIN(gdate.mon);
22
   gdate.year = BCD2BIN(gdate.year);
23
}

Für alle Fälle gleich noch die Init- u. Reset-Routine (init_rtc() ggf. 
anpassen)
1
void reset_rtc(void){
2
   gtime.hour = gtime.min = gtime.sec = 0;
3
   gdate.year = gdate.mon = gdate.day = 1;
4
   start_iic(RTC_WR);
5
   write_iic(0x02);
6
   write_iic(0x00);  //sec
7
   write_iic(0x00);  //min
8
   write_iic(0x00);  //hour
9
   write_iic(0x01);  //day
10
   write_iic(0x00);  //weekday
11
   write_iic(0x01);  //month
12
   write_iic(0x01);  //year
13
   stop_iic();
14
}
15
16
U8 init_rtc(void){
17
   U8 val = 0;
18
   U8 volatile tmp;
19
20
   for(tmp=0;tmp<100;tmp++); //theoretisch unnötig. Praktisch schon
21
22
   start_iic(RTC_WR);
23
   write_iic(0x00);
24
   write_iic(0x00);         //ControlRegister0
25
   write_iic( (1<<4) | (1<<0) );  //ControlRegister1: TP & TIE setzen
26
   stop_iic();
27
28
   for(tmp=0;tmp<100;tmp++);
29
30
   start_iic(RTC_WR);
31
   write_iic(0x09);
32
   write_iic(0x80);  //AE disabled min
33
   write_iic(0x80);  //AE disabled hour
34
   write_iic(0x80);  //AE disabled day
35
   write_iic(0x80);  //AE disabled weekday
36
   write_iic(0x80);  //CLKOUT enabled@32.768kHz
37
   write_iic(0x82);  //Timer mit 1Hz aktivieren
38
   write_iic(0x01);  //Timer laden 1s (test)
39
   stop_iic();
40
41
   for(tmp=0;tmp<100;tmp++);
42
43
   start_iic(RTC_WR);
44
   write_iic(0x02);
45
   rep_start_iic(RTC_RD);
46
   val = read_iic_nack();
47
   stop_iic();
48
49
   if(val & 0x80) //Stromausfall? VL-Flag reset und Date/Time reset
50
      return(1);  //Bit7==1 -> Stromausfall - reset_rtc() angezeigt
51
   else
52
      return(0);
53
}

  

von Patrick L. (pazulator)


Lesenswert?

super

doch wie sieht read_iic_ack() aus?

von Frank N. (betafrank)


Lesenswert?

Achso... g

Wenn ich nicht Details geändert habe, sollte der Code der von Peter 
Fleury sein.
1
/*************************************************************************/
2
U8 read_iic_ack(void){
3
/*************************************************************************/
4
5
   /* Für alle Bytes bis auf das letzte zu übertragende Byte
6
   */
7
  TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWEA);
8
9
  //Warten bis TWI Bedingung gesendet wurde
10
  while(!(TWCR & (1<<TWINT)));
11
12
  //TWI Status berprfen
13
  if((TWSR & 0xF8) == TW_MR_DATA_ACK) return TWDR;
14
  return 1;
15
}
16
17
/*************************************************************************/
18
U8 read_iic_nack(void){
19
/*************************************************************************/
20
   /* Für das letzte zu übertragende Byte
21
   */
22
  TWCR = (1<<TWINT) | (1<<TWEN);
23
24
  //Warten bis TWI Bedingung gesendet wurde
25
  while(!(TWCR & (1<<TWINT)));
26
27
  //TWI Status überprfen
28
  if((TWSR & 0xF8) == TW_MR_DATA_NACK) return TWDR;
29
  return 2;
30
}

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.