mikrocontroller.net

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


Autor: Neubi (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Hauke Sattler (hauke)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Frank N. (betafrank)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Neubi,

hab mal zusammenkopiert, läuft bei mir auf nem Mega128.
//iic.c:////////////////////////////////////////////////
/******************************************************/
void init_iic(void){
   TWSR = 0;         //Prescaler
   TWBR = (F_CPU / 100000UL - 16) / 2;     // 100kHz
}
/******************************************************/
int start_iic(unsigned char address){
   /* Returnwerte:
   * 0 -> Startbedinung erfolgreich gesendet
   * 1 -> Probleme beim sender der Start-Bedinung
   * 2 -> Probleme beim senden der Addresse
   *      bzw. kein Device mit der angegebenen Addresse
   */
  //Senden der START Bedingung
  TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN);
  //Warten bis TWI Bedingung gesendet wurde
  while(!(TWCR & (1<<TWINT)));
  //TWI Status berprfen
  if((TWSR & 0xF8) != TW_START) return 1;
  //Adresse des anzusprechenden Devices senden
  TWDR = address;
  TWCR = (1<<TWINT) | (1<<TWEN);
  //Warten bis TWI Bedingung gesendet wurde
  while(!(TWCR & (1<<TWINT)));
  //TWI Status überprüfen
  if((TWSR & 0xF8) != TW_MT_SLA_ACK) return 2;
  return 0;
}
/******************************************************/
void write_iic(U8 data){
  TWDR = data;
  TWCR = (1<<TWINT) | (1<<TWEN);
  //Warten bis TWI Bedingung gesendet wurde
  while(!(TWCR & (1<<TWINT)));
}
/******************************************************/
void stop_iic(void){
  TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWSTO);
}

//rtc.c:////////////////////////////////////////////////

#define RTC_WR 0xA2         // Schreibadresse PCF8563
#define  BIN2BCD(b) (((b)%10) | (((b)/10)<<4))
/******************************************************/
void write_time_rtc(void){
   start_iic(RTC_WR);
   write_iic(0x02);
   write_iic(BIN2BCD(gtime.sec));
   write_iic(BIN2BCD(gtime.min));
   write_iic(BIN2BCD(gtime.hour));
   stop_iic();
}

Autor: Patrick Lechner (pazulator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Frank!

Hast du auch den code fürs auslesen?

Wär echt nett! Danke!

Autor: Frank N. (betafrank)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hier ist er:
#define RTC_RD 0xA3         // Leseadresse PCF8563
#define  BCD2BIN(b) (((b)&0xf) + ((b)>>4)*10)
void read_rtc(void){
   //Time
   start_iic(RTC_WR);
   write_iic(0x02);
   rep_start_iic(RTC_RD);
   gtime.sec  = read_iic_ack() & 0x7F;
   gtime.min  = read_iic_ack() & 0x7F;
   gtime.hour = read_iic_ack() & 0x3F;
   gtime.sec  = BCD2BIN(gtime.sec);
   gtime.min  = BCD2BIN(gtime.min);
   gtime.hour = BCD2BIN(gtime.hour);
   //Date
   gdate.day  = read_iic_ack() & 0x3F;
                read_iic_ack();   //Dummyread Wochentag == egal
   gdate.mon  = read_iic_ack() & 0x1F;
   gdate.year = read_iic_nack();
   stop_iic();
   gdate.day  = BCD2BIN(gdate.day);
   gdate.mon  = BCD2BIN(gdate.mon);
   gdate.year = BCD2BIN(gdate.year);
}

Für alle Fälle gleich noch die Init- u. Reset-Routine (init_rtc() ggf. 
anpassen)
void reset_rtc(void){
   gtime.hour = gtime.min = gtime.sec = 0;
   gdate.year = gdate.mon = gdate.day = 1;
   start_iic(RTC_WR);
   write_iic(0x02);
   write_iic(0x00);  //sec
   write_iic(0x00);  //min
   write_iic(0x00);  //hour
   write_iic(0x01);  //day
   write_iic(0x00);  //weekday
   write_iic(0x01);  //month
   write_iic(0x01);  //year
   stop_iic();
}

U8 init_rtc(void){
   U8 val = 0;
   U8 volatile tmp;

   for(tmp=0;tmp<100;tmp++); //theoretisch unnötig. Praktisch schon

   start_iic(RTC_WR);
   write_iic(0x00);
   write_iic(0x00);         //ControlRegister0
   write_iic( (1<<4) | (1<<0) );  //ControlRegister1: TP & TIE setzen
   stop_iic();

   for(tmp=0;tmp<100;tmp++);

   start_iic(RTC_WR);
   write_iic(0x09);
   write_iic(0x80);  //AE disabled min
   write_iic(0x80);  //AE disabled hour
   write_iic(0x80);  //AE disabled day
   write_iic(0x80);  //AE disabled weekday
   write_iic(0x80);  //CLKOUT enabled@32.768kHz
   write_iic(0x82);  //Timer mit 1Hz aktivieren
   write_iic(0x01);  //Timer laden 1s (test)
   stop_iic();

   for(tmp=0;tmp<100;tmp++);

   start_iic(RTC_WR);
   write_iic(0x02);
   rep_start_iic(RTC_RD);
   val = read_iic_nack();
   stop_iic();

   if(val & 0x80) //Stromausfall? VL-Flag reset und Date/Time reset
      return(1);  //Bit7==1 -> Stromausfall - reset_rtc() angezeigt
   else
      return(0);
}

  

Autor: Patrick Lechner (pazulator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
super

doch wie sieht read_iic_ack() aus?

Autor: Frank N. (betafrank)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Achso... g

Wenn ich nicht Details geändert habe, sollte der Code der von Peter 
Fleury sein.
/*************************************************************************/
U8 read_iic_ack(void){
/*************************************************************************/

   /* Für alle Bytes bis auf das letzte zu übertragende Byte
   */
  TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWEA);

  //Warten bis TWI Bedingung gesendet wurde
  while(!(TWCR & (1<<TWINT)));

  //TWI Status berprfen
  if((TWSR & 0xF8) == TW_MR_DATA_ACK) return TWDR;
  return 1;
}

/*************************************************************************/
U8 read_iic_nack(void){
/*************************************************************************/
   /* Für das letzte zu übertragende Byte
   */
  TWCR = (1<<TWINT) | (1<<TWEN);

  //Warten bis TWI Bedingung gesendet wurde
  while(!(TWCR & (1<<TWINT)));

  //TWI Status überprfen
  if((TWSR & 0xF8) == TW_MR_DATA_NACK) return TWDR;
  return 2;
}

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.