I2C RTC : PCF8563 lesen geht schreiben nicht !

Gast #530382
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
#530969
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
}
#568085
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
}

  
#568188
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
}

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren