Hi Forum,
ich versuche seit einiger Zeit, meine DS 1307 RTC mit einem Amtega 328
anzusprechen. Dazu wollte ich als ersten Test in eines der RAM-Register
der RTC einen Wert schreiben (48) (Adresse des Registers ist 0x08) und
den dann wieder auslesen und via LCD ausgeben (in der Hoffnung das eine
1 rauskommt).
Verschaltet habe ich das folgendermaßen:
____ ______ _________
| 1|---|QUARZ | | |
|R 2|---|______| | Atmega |
|T 3|---[+3V via Spannungsteiler] | 328 | ___
|C 4|---[GND] | |--| |
| 5|-----------------------------------|SDA |--| LCD |
| 6|-----------------------------------|SCL |--| in |
| 7|x | |--| 4bit|
| 8|---[+5V] | |--|Modus|
|_____| |__________|--|_____|
CPU-FREQ ist 1mHz
als Programm auf dem avr habe ich zum schreiben der Daten folgendes:
void write_RTC()
{
power_twi_enable();
PORTC |= (1<<PORTC5) | (1<<PORTC4);
TWBR = 2;
_delay_ms(5);
TWCR = 0xA4; //start
while (!(TWCR & (1<<TWINT)));
TWDR = 0x08; //SLA + W
TWCR = 0x84;
while (!(TWCR & (1<<TWINT)));
TWDR = 48; //data
TWCR = 0x84;
while (!(TWCR & (1<<TWINT)));
TWCR = 0x94; //stop
_delay_ms(5);
}
und zum lesen:
void read_RTC()
{
power_twi_enable();
PORTC |= (1<<PORTC5) | (1<<PORTC4);
TWBR = 2;
_delay_ms(5);
TWCR = 0xA4; //start
while (!(TWCR & (1<<TWINT)));
TWDR = (0x08 | 0x01); //SLA + R
TWCR = 0x84;
while (!(TWCR & (1<<TWINT)));
twi_var = TWDR; //read data
TWCR = 0x94; //stop
}
Ich habe, wie es im Datenblatt des AVR auch steht, die internen Pull-Up
Widerstände aktiviert. Auf dem Oszilloskop kann ich auch sehen, dass auf
den Leitungen was passiert (hat leider nur einen Kanal, drum kann ich
nicht genau nachvollziehen was passiert).
Wenn ich das Programm jetzt starte, dann wird mir auf dem LCD ein
asiatisches Schriftzeichen angezeigt. Wenn ich aber in der Funktion zum
auslesen statt
TWDR = (0x08 | 0x01); //SLA + R
TWDR = 48;
setze, dann wird mir auf dem Bildschirm eine 0 angezeigt, bei 49 eine 1
etc. Drum denke ich, dass das TWDR-Register überhaupt nicht angetastet
wird vom uC, kann mir aber nicht erklären warum. Ich habe auch schon das
Datenblatt gewälzt und mir das Tutorial hier im Forum dazu angeschaut,
konnte aber leider keinen Fehler finden.
Es wäre toll, wenn jemand einen Rat hätte.
vielen Dank schon mal,
Tristan
benutze als pullup hardware 2x 4,7k
die fleury LIB hilft auch
http://homepage.hispeed.ch/peterfleury/avr-software.html
bist du sicher das deine Adresse stimmt, ich sehe da immer Verwirrung
zwischen 7-Bit Betrachtung I2C >> 1 und 8-Bitbetrachtung I2C & 0xFE r/w
Bit ausgeklammert
mit der Fleury LIB und der richtigen Adresse kein Problem, mit Arduino
auch kein Problem!
also habe jetzt die internen pull-ups abgeschalten und externe 4,7kOhm
genutzt, was aber auch keine Verbesserung bringt
Ich wollte zum Mindest für den Anfang ohne Lib arbeiten, damit ichs mal
verstehe.
@joachim B
was meinst du im dritten Absatz? Da werde ich nicht so recht schlau
draus.
Aber vielen Dank für die schnellen Antworten!
Edit:
hier noch das Datenblatt:
http://cdn-reichelt.de/documents/datenblatt/A200/DS_1307.pdf
Ich habe mich jetzt an der Grafik auf Seite 4 orientiert mit den
Adressen, allerdings steht auf Seite 2: "Access is obtained by
implementing a
START condition and providing a device identification code followed by a
register address."
Was ist denn da mit "device identification code" gemeint?
schaust du ins Datenblat hast du für die I2C Adresse ein Byte = 8 Bits,
aber nur die Bits 7-1 gelten, Bit 0 ist für R/W read write.
Nun gilt aber erst mal es gibt nur 7 Bit 127 I2C Adressen,
redet einer von Adresse 0x20 was meint der ?
ich habe mir angewöhnt die 127 Adressen rechts zu shiften um im
Datenblatt bei den richtigen Bits zu bleiben
1
#if (ARDUINO>0)
2
DEBUG_PRINTLN(F(" -> Scanning..."));
3
4
_i2c_key=0;
5
byteerror,address;
6
intnDevices=0;
7
for(address=1;address<127;address++)
8
{// The i2c_scanner uses the return value of
9
// the Write.endTransmisstion to see if
10
// a device did acknowledge to the address.
11
Wire.beginTransmission(address);
12
error=Wire.endTransmission();
13
14
if(error==0)
15
{DEBUG_PRINT(F("I2C device found at address 0x"));
Tristan V. schrieb:> Adressen, allerdings steht auf Seite 2: "Access is obtained by> implementing a> START condition and providing a device identification code followed by a> register address."> Was ist denn da mit "device identification code" gemeint?
Die Adresse naturlich.
1
TWDR=0x08;//SLA + W
2
TWDR=(0x08|0x01);//SLA + R
Wo hast du diese Adressen her ?
DS1307 hat die Adresse 0xD0 (schreiben) und 0xD1 (lesen).
Probiere es mal mit richtigen Adressen... ;-)
Joachim B. schrieb:> ich habe mir angewöhnt die 127 Adressen rechts zu shiften um im> Datenblatt bei den richtigen Bits zu bleiben
Ja, sicher.
Welches Datenblatt ?
Hier ist es fur DS1307:
Marc V. schrieb:> Ja, sicher.> Welches Datenblatt ?
alle, kein spezielles, ich nutze
DS3231, (DS1307 erst später), PCF8574(a) und Oled
mit dem PCF8574 habe ich mal angefangen
https://www.nxp.com/documents/data_sheet/PCF8574.pdf
Seite 12 und die ganze shifterei verwirrt doch nur, wenn jedes Bit an
seinem Platz bleibt dann ergeben sich halt völlig andere
Betrachtungsweisen der I2C Adresse
@ Marc Vesely:
diese Adresse ist aus dem Datenblatt zur RTC von Reichelt, in dem steht
aber auch nichts von der 0xD0 bzw. D1 Adresse drin. Das war eine der
Sachen, die mich so verwundert hat.
Um das Lesen aus der RTC zu umgehen, habe ich die Funktion mal so
umgeschrieben, dass sie den SQW-Ausgang auf 1Hz einschaltet und auch
noch versucht, eine Fehlererkennung zu implementieren.
das kam bei raus (bitte reißt mir nicht den Kopf ab :D)
1
voidwrite_RTC()
2
{
3
power_twi_enable();
4
TWBR=2;
5
TWSR&=~(1<<TWPS0)&~(1<<TWPS1);
6
_delay_ms(5);
7
8
TWCR=(1<<TWEN)|(1<<TWSTA)|(1<<TWINT);//start
9
while(!(TWCR&(1<<TWINT)));
10
if(!((TWSR&0xF8)==0x08))
11
write_data_to_LCD_as_string("start error");
12
13
TWDR=(0xD0);//SLA + W
14
TWCR=(1<<TWEN)|(1<<TWINT);
15
while(!(TWCR&(1<<TWINT)));
16
if(!((TWSR&0xF8)==0x40))
17
write_data_to_LCD_as_string("address error");
18
19
TWDR=(0x07);//register address
20
TWCR=(1<<TWEN)|(1<<TWINT);
21
while(!(TWCR&(1<<TWINT)));
22
if(!((TWSR&0xF8)==0x40));
23
write_data_to_LCD_as_string("address error");
24
25
TWDR=0x10;//data
26
TWCR=(1<<TWEN)|(1<<TWINT);
27
while(!(TWCR&(1<<TWINT)));
28
if(!((TWSR&0xF8)==0x50))
29
write_data_to_LCD_as_string("data error");
30
31
TWCR=0x94;//stop
32
_delay_ms(5);
33
}
ich bekomme auf dem LCD 2x address error und data error, start scheint
aber zu funktionieren.
vielen Dank,
Tristan
ok, also ich habe die Tabelle nochmal durchgeguckt und die Werte
geändert, da habe ich irgendwiegepennt...
Allerdings funktioniert es jetzt immer noch nicht so recht. Ich denke,
ich belass es erstmal dabei, nächste Woche habe ich die Möglichkeit das
nochmal persönlich mit jemandem zu besprechen der Ahnung davon hat, das
dürfte für Alle einfacher sein als die Ferndiagnose durch die Glaskugel
:D
Aber vielen Dank für die vielen und schnellen Hilfen,
ich melde mich wenn es klappt :)
Tristan