Hallo,
ich bin Neuling auf dem Gebiet der Mikrocontroller und versuche mich
aktuell an einem Nachbau der Wort-Uhr. Das ganze will ich mit einem
STM8S-Discovery Evalboard realisieren, auf das mich ein Kollege
aufmerksam gemacht hat. Ich habe noch keine Erfahrungen mit anderen
MCUs. Bisher bin ich mit dem Ding auch recht gut voran gekommen, trotz
der, wie ich finde, guten FW Lib dauert es natürlich seine Zeit, sich in
neue Gebiete einzuarbeiten.
Wie dem auch sei, nun versuche ich mit einer DS1307 RTC per I2C zu
kommunizieren, die mir später beim Abschalten der Energiezufuhr die Zeit
speichern und weiterzählen soll, das klappt jedoch überhaupt nicht.
Natürlich habe ich mich über das I2C Protokoll informiert und mir einige
SW Beispiele für die AVRs angeschaut. Wenn ich versuche, die gewonnenen
Informationen für mich anzuwenden, klappt es jedoch überhaupt nicht.
Die RTC ist wie im Anhang zu erkennen angeschlossen (PE1 ist I2C Clock,
PE2 I2C Data). VBat liegt erstmal auf GND, für Testzwecke verzichte ich
darauf erst einmal. f_Master beträgt 2 Mhz. Die Software soll zum Testen
folgendes machen:
- in der main-Funktion, vor dem Betreten der Hauptschleife, die RTC im
Register 00h mit 0x00 beschreiben (Clock Halt Bit 0, damit der Quarz
anschwingt)
- jetzt einmal je Sekunde das Register 00h (Sekunden) auslesen und in
die Variable "sek" schreiben, deren Wert ich mir dann im Debugger
angucken kann; das erfolgt in der Hauptschleife, nachdem eine
Flag-Variable durch einen Interrupt auf 1 gesetzt wurde
SW ("Initialisierung")
1 | // I2C Config -> Output 100kHz, Input 2 Mhz, Ack on current byte, 7 bit address mode,
|
2 | I2C_DeInit();
|
3 | I2C_Init(100000, 0xA2, I2C_DUTYCYCLE_2, I2C_ACK_CURR, I2C_ADDMODE_7BIT, 2);
|
4 | I2C_Cmd(ENABLE);
|
5 |
|
6 |
|
7 | I2C_GenerateSTART(ENABLE); // start
|
8 | I2C_Send7bitAddress(0xD0, I2C_DIRECTION_TX); // address 1101000 + 0 (WRITE)
|
9 | I2C_SendData(0x00); // set register pointer 00h
|
10 | I2C_SendData(0x00); // write 0x00 to 00h (oscillator enabled)
|
11 | I2C_GenerateSTOP(ENABLE); // stop
|
In der Main-Schleife:
1 | if (I2C_FLAG == 1) {
|
2 |
|
3 | GPIO_WriteReverse(GPIOE, P5);
|
4 |
|
5 | I2C_AcknowledgeConfig(I2C_ACK_CURR);
|
6 | I2C_GenerateSTART(ENABLE);
|
7 | I2C_Send7bitAddress(0xD0, I2C_DIRECTION_TX);
|
8 | I2C_SendData(0x00); // set register pointer to 00h
|
9 | I2C_GenerateSTOP(ENABLE);
|
10 |
|
11 | I2C_GenerateSTART(ENABLE);
|
12 | I2C_Send7bitAddress(0xD0, I2C_DIRECTION_RX);
|
13 | I2C_AcknowledgeConfig(I2C_ACK_NONE); // NAck after next byte sent
|
14 | sek = I2C_ReceiveData();
|
15 | I2C_GenerateSTOP(ENABLE);
|
16 |
|
17 | I2C_FLAG = 0;
|
18 | }
|
Ergebnis ist, dass keine Informationen von der RTC kommen, sondern immer
0xd1, das eigentlich zuletzt gesendete byte im Data Register und damit
in "sek" steht.
Ich habe mir beim Debuggen mal die Registerwerte angeschaut. Nach dem
Funktionsaufruf I2C_Init... stimmen die Werte für die Control Register 1
und 2, aus den anderen Registern werde ich jedoch nicht schlau, da
bestimmte Bits beim Lesen dieser resettet werden. Es gibt ein Flag Bit
für "Acknowledge Failure", das jedoch nie gesetzt ist.
Im STM8S Reference Manual steht unter anderem:
"Following the address transmission and after clearing ADDR, the master
sends bytes from
the DR register to the SDA line via the internal shift register."
Also habe ich das Bit ADDR manuell nach dem Senden der Adresse auf 0
gesetzt, weil die von ST definierten Funktionen dies anscheinend nicht
tun, aber auch mit der Maßnahme ändert sich nichts.
Sonstige bisherige Maßnahmen (ohne Erfolg):
- Pullups von 4k7 auf 10k erhöht
- DS1307 ausgetauscht
Wie kann ich überprüfen, ob auf der SDA bzw. SCL überhaupt was los ist,
also ob der STM8S überhaupt versucht, zu kommunizieren? Vorhanden ist
leider nur ein einfaches Multimeter. Gibt es ansonsten irgendwelche
anderen Anfänger- oder sonstige Fehler, die ich begangen habe?
Ich bin für alle Hinweise dankbar! Besonders interessant wären SW
Beispiele für den STM8S für I2C, die ST Seite ist da leider etwas
sparsam und ansonsten findet sich im Internet auch nichts.
MfG Dave