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
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
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 berprfen
|
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 | }
|
Hallo Frank! Hast du auch den code fürs auslesen? Wär echt nett! Danke!
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 | }
|
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 berprfen
|
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 überprfen
|
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.