Forum: Mikrocontroller und Digitale Elektronik TWI Bus hängt sich auf


von Andreas S. (newpiccer)


Angehängte Dateien:

Lesenswert?

Moin zusammen,
ich betreibe ein Arduino Uno Board. An den I2C-Bus (TWI) habe ich einen 
Temperatursensor MLX90614 angeschlossen. Die I2C-Adresse des Sensors ist 
0x5A. Im Anhang ist das Programm dazu.
Mein Problem: Das Programm wird 2 - 5 mal durchlaufen und hängt sich 
dann hinter der Start-Condition auf.(Die LED bleibt an.) Die 
Datenleitung wird, wahrscheinlich vom Slave, auf GND gehalten.
Der Sensor schickt
1. an der richtigen Stelle ein Acknowledge
2. korrekte Temperaturwerte, die lassen sich sehr gut am Oszi ablesen.
Und das eben 2 - 5 mal. Was ja eigentlich nicht sein kann. Entweder es 
funzt oder eben nicht. Aber nicht ein paar Mal und dann nicht mehr.
Für Ideen wäre ich sehr dankbar.

Einen schönen Tag
Andreas

von Andreas S. (newpiccer)


Lesenswert?

Ganz unten muss es natürlich heißen:
TWCR = (1<<TWINT) | (1<<TWEN); //Initialize the transmission, now the 
last data to be received
    while (!(TWCR & (1<<TWINT))); //Wait for Interrupt Flag, address has 
been sent
    while ((TWSR & 0xF8)!= 0x58); //Check for acknowledgement
    Temperatur_HI = TWDR;

von Stephan (Gast)


Lesenswert?

Hi Andreas,

ich sags mal so - wäre der Einsatz von:
https://www.arduino.cc/en/Reference/Wire
in Deinem Fall nicht besser?
VG, Stephan

von Olaf (Gast)


Lesenswert?

> Und das eben 2 - 5 mal. Was ja eigentlich nicht sein kann. Entweder es
> funzt oder eben nicht. Aber nicht ein paar Mal und dann nicht mehr.

Das beschriebene Verhalten ist fuer I2C vollkommen normal.
Du musst dich erstmal damit abfinden. Es liegt an dir deine
Software so zu programmieren das sie bei so einem Fehler wieder korrekt
aufsetzt und weitermachen kann. Sei sogar dankbar das dir schon jetzt 
auffaellt.

Sobald du dein Softwareproblem geloest hast kannst du als naechste mal 
die Qualitaet deiner FLanken/Uebertragung anschauen. Vermutlich stimmen 
die Pegel nicht, du hast Groundbounce, kein Abblock-C, whatever. Sobald 
du diese Hardwareprobleme geloest hast wird dein Problem nur noch alle 
paar Tage oder Monate auftreten. Je nachdem wie EMV-Gerecht deine 
Hardware aufgebaut ist. Ganz weg bekommt man das bei I2C niemals.

Olaf

von Helge (Gast)


Lesenswert?

>Ganz weg bekommt man das bei I2C niemals

Wie löst du das konkret?

von Stefan F. (Gast)


Lesenswert?

Andreas S. schrieb:
> Die Datenleitung wird, wahrscheinlich vom Slave, auf GND gehalten.

Prüfe es, indem du die Verbindung zum Master trennst oder dessen Reset 
Knopf gedrückt hältst (falls dadurch nicht auch der Slave resetted 
wird).

von Stefan F. (Gast)


Lesenswert?

Helge schrieb:
> Wie löst du das konkret?

Erst einmal die Ursache ermitteln, bevor man die passende Lösung sucht.

von Andreas S. (newpiccer)


Lesenswert?

Vielen Dank für die schnellen Antworten!

Hallo Stephan,
ja, natürlich ist das einfacher. Die Übertragung dauert mir aber zu 
lange, gesamt ca. 600us. Wenn alles läuft, würde ich das Ganze in den 
Interrupt packen, zumindest die Teile die bei 100kHz bis zu 100us 
dauern.

Hallo Olaf,
meine Erfahrung mit dem I2C ist, dass er zuverlässig arbeitet. Bei 
meinen Projekten, die ich mit einem PIC gemacht habe, habe ich keine 
Störungen(mehr). Ich habe allerdings auch lange daran rumgebastelt, bis 
ich die Übertragung so hatte, dass sie zuverlässig ist. Ein falscher 
Befehl und nix funzt mehr. Mit dieser Erfahrung hatte ich gedacht, dass 
womöglich jemand den kleinen Fehler in meinem AVR Programm findet, der 
da noch drin sein muss.
Und natürlich hast du recht, dass sich das mit Fehlerroutinen umgehen 
lässt. Die würde ich aber erst einbauen, wenn das Ganze grundsätzlich 
funzt.

Hallo Helge,
statt einer einfachen while-Schleife, die auf ein ganz bestimmtes 
Ereignis wartet, einzubauen, kann man z.B. Zeitstrukturen einbauen. Wenn 
eine bestimmte Zeit lang, das erwartete Ereignis nicht eintrifft, kann 
man die Übertragung abbrechen und neu anfangen...

von Dergute W. (derguteweka)


Lesenswert?

Moin,

Um rauszufinden, wer den Bus nicht loslaesst, kanns nicht schaden, ganz 
kleine Serienwiderstaende (<50 Ohm) in die SDA und SCL Leitungen 
reinzubauen.

Gruss
WK

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?

Philips hat damals eine Recovery Routine in den Specs für I²C 
vorgeschlagen.
Dabei wird bis zu 9 mal SCL gepulst und darauf gehört, ob SDA wieder auf 
high springt.
Wimre soll man dann eine STOP Bedingung anschliessen und der Bus spielt 
wieder.

von Andreas S. (newpiccer)


Lesenswert?

Hallo DerguteW,
hört sich sehr spannend an!
Was mache ich denn dann mit den Serienwiderständen?
Was muss ich da wie messen?

Vielen Dank
Andreas

von Dergute W. (derguteweka)


Lesenswert?

Moin,

Andreas S. schrieb:
> Was muss ich da wie messen?

Wenn der Bus haengt, dann misst du das bisschen Spannung zwischen GND 
und jeweils einem Pin des Widerstands. So kriegst du raus, ob Strom 
durch den R fliesst und wenn ja, in welche Richtung...

Gruss
WK

von Olaf (Gast)


Lesenswert?

> meine Erfahrung mit dem I2C ist, dass er zuverlässig arbeitet. Bei
> meinen Projekten, die ich mit einem PIC gemacht habe, habe ich keine
> Störungen(mehr).

Nein. I2C ist per Design nicht zuverlaessig.

Wenn ein Slave ein falsche Kommando empfaengt kann es passieren das er 
sein Datenleitung runterzieht und das naechste Kommando auch nicht mehr 
richtig empfaengt.

Fehler bei der Uebertragung koennen also dafuer sorgen das sich ein Bus 
weghaengt. (z.B ein Burst, RF-Einstrahlung, Angorapullover)

Du kannst den dann wieder aufbauen. Ueblicherweise indem man einfach 
Clocks raushaut in der Hoffnung das damit die Statemachine im Slave 
wieder aufsetzt.

Es gibt aber auch Bausteine die koennen die Clockleitung runterziehen. 
Das war es dann. Dann kannst du nur noch bei deinem Baustein die Vcc 
abschalten und wieder einschalten.

Jetzt gibt es natuerlich Bausteine die machen sowas lieber als andere. 
Ausserdem haengt es natuerlich stark von deinem Hardwaredesign ab. Bei 
einem schlechten Design hast du die Probleme oft, bei einem guten 
vielleicht nur alle paar Jahre mal. Und es haengt auch von der Anwendung 
hab. Bei einem MP3-Player den du in der Woche nur 3h nutzt und den du 
bei einem Problem automatisch mal aus/einschaltet wird das nicht so 
recht auffallen. Bei der Temperatursteuerung sagen wir mal deines 
Kuehlschranks die 24h laeuft waere es bloed wenn die alle 5Jahre mal 
versagt und deine Pommes auftauen.

Weil das den Herstellern auch aufgefallen ist gibt es mittlerweile 
moderne I2C Erweiterungen. Da haben die Bausteine eine minimal 
Taktfrequenz. Wenn der Baustein da eine Weile nix mehr empfaengt dann 
resetet er sich intern um die Finger vom Bus zu nehmen.

Ich will damit nicht sagen das man I2C nicht verwenden kann. Man sollte 
sich dessen nur bewusst sein und Fehler einplanen.

Olaf

von L.K. (Gast)


Lesenswert?

Andreas S. schrieb:
> Was mache ich denn dann mit den Serienwiderständen?

Wieso Serienwiderstände? I2C hat nur 2 Pullups. Mit irgendwelchen 
Serienwiderständen versaust Du nur Dein Signal.

von Fragender (Gast)


Lesenswert?

Wiederstände von <50Ohm habe ich schon öfters in Schaltungen gesehen. 
Die Funktion ist mir in Abhängigkeit des Einbauortes nicht ganz klar. 
Wenn ich die Widerstände zwischen Master und den Slaves schalte kann ich 
zwar die Richtung feststellen, doch welcher IC es ist kann ich nicht 
messen.
Können diese Widerstände nicht mein Pegel des Busses beeinflussen?
LG Fr

von L.K. (Gast)


Lesenswert?

Fragender schrieb:
> Können diese Widerstände nicht mein Pegel des Busses beeinflussen?

genau, der Low-Pegel wird für bestimmte Teilnehmer des Busses höher, 
weil der Serienwiderstand und der Pullup als Spannungsteiler wirken, 
d.h. die verschlechteren das Signal.

von Peter D. (peda)


Lesenswert?

Fragender schrieb:
> Wiederstände von <50Ohm habe ich schon öfters in Schaltungen gesehen.

Normale IO-Pins sind oft leistungsstark, was Reflexionen bewirken kann. 
Z.B. wenn man den Master in SW implementiert. Da verbessert dann ein 
Serienwiderstand die Störsicherheit.

Pins vom HW-I2C sollten aber schon intern die Slew-Rate begrenzen. Das 
sollte dann im Datenblatt stehen.

von L.K. (Gast)


Lesenswert?

Peter D. schrieb:
> Normale IO-Pins sind oft leistungsstark, was Reflexionen bewirken kann.

Der typische I2C-Bus ist reflexionsfrei, wenn die Pullup-Widerstände der 
Spannung, Busfrequenz und Teilnehmerzahl entsprechend korrekt berechnet 
sind, vor allem dürfen sie nicht zu hoch sein. Bei normaler Belegung 
hängen am I2C-Bus nur hochohmige Eingänge und Open-Drain-Ausgänge, bei 
Software-I2C sind die Ausgänge push-pull, was auch für saubere Pegel 
sorgt.

von Dergute W. (derguteweka)


Lesenswert?

Moin,

L.K. schrieb:
> Der typische I2C-Bus ist reflexionsfrei, wenn die Pullup-Widerstände der
> Spannung, Busfrequenz und Teilnehmerzahl entsprechend korrekt berechnet
> sind, vor allem dürfen sie nicht zu hoch sein. Bei normaler Belegung
> hängen am I2C-Bus nur hochohmige Eingänge und Open-Drain-Ausgänge, bei
> Software-I2C sind die Ausgänge push-pull, was auch für saubere Pegel
> sorgt.
Das glaube ich nicht, Tim.

Fragender schrieb:
> doch welcher IC es ist kann ich nicht
> messen.

Dann sind's zu wenige Widerstaende ;-)

> Können diese Widerstände nicht mein Pegel des Busses beeinflussen?
Die sollten halt so klein sein, dass der Pegel nicht zu stark 
beeinflusst wird.

Ich finds erstaunlich, dass zwar auf der einen Seite Leute irgendwelche 
I2C Monster mit zig Slaves via meterweise tüddelkabel zwischendrinnen 
aufbauen wollen, aber auf der anderen Seite Leute gleich halbtot vor 
Entsetzen vom Stangerl fallen, wenn man mal ein paar Serienwiderstaende 
anraet.
Wers mit seinem Gewissen garnicht vereinbaren kann, der darf auch 0 Ohm 
Widerstaende hernehmen und die dann nur im "'s dud ned" Fall durch 
gerinfuegig hoehere Werte ersetzen. Ist deutlich weniger Gefuddel als 
die Leitungen aufzutrennen.

Gruss
WK

von Georg G. (df2au)


Lesenswert?

L.K. schrieb:
> bei
> Software-I2C sind die Ausgänge push-pull, was auch für saubere Pegel
> sorgt.

Da hast du ein häufig auftretendes Problem bei Schludersoftware gut 
beschrieben.
Push-Pull am I2C ist ein absolutes noGo. Für LOW darfst du niederohmig 
nach GND ziehen, für HIGH schaltest du den Port auf Eingang. Sonst sind 
einige Funktionen unmöglich (Clock Stretching als Beispiel).

von L.K. (Gast)


Lesenswert?

Georg G. schrieb:
> Push-Pull am I2C ist ein absolutes noGo.

Der aktive Part hat als Ausgang bei Software-I2C sehr wohl push-pull.
Bei HW-I2C open-drain oder OC.
Als Eingang hochohmig.

von HildeK (Gast)


Lesenswert?

Probleme beim I2C können natürlich durch die SW verursacht sein.
Aber man sollte auch klären, wie die HW aussieht:
- Welche Leitungslängen liegen vor? (Temp-Sensoren könnten weit weg 
installiert sein ...)
- Welche Pullups am I2C-Bus sind verwendet worden bei welchem 
Logikpegel?

Oder habe ich Aussagen dazu übersehen?

von Georg G. (df2au)


Lesenswert?

L.K. schrieb:
> Der aktive Part hat als Ausgang bei Software-I2C sehr wohl push-pull.

Was war an "Push Pull ist ein Fehler" missverständlich? Sieh dir bitte 
die Spec an oder eine der gängigen Libs (Fleury als Beispiel).

von Olaf (Gast)


Lesenswert?

> bei Software-I2C sind die Ausgänge push-pull, was auch für saubere
> Pegel sorgt.

Und genau das ist der groesste Murks den man machen kann.
Natuerlich ist der Ausgang immer Low und man schaltet den Port fuer
Highpegel auf Eingang um. Sonst braucht man sich nicht zu wundern
wenn das Zeug nicht richtig laeuft.

Olaf

von Spess53 (Gast)


Lesenswert?

Hi

>Der aktive Part hat als Ausgang bei Software-I2C sehr wohl push-pull.

AVR 300: Software I2C™ Master Interface

MfG Spess

von Wolfgang (Gast)


Lesenswert?

L.K. schrieb:
> Wieso Serienwiderstände? I2C hat nur 2 Pullups. Mit irgendwelchen
> Serienwiderständen versaust Du nur Dein Signal.

Unfug. Da sollen keine MegaOhm Widerstände rein.
Ein Spannungsabfall von wenigen 100mV ist absolut unkritisch. Guck dir 
mal die Spezifikation für die Erkennung eines Low-Pegels auf den 
Leitungen an.

von Christian J. (Gast)


Lesenswert?

Matthias S. schrieb:
> Philips hat damals eine Recovery Routine in den Specs für I²C
> vorgeschlagen.
> Dabei wird bis zu 9 mal SCL gepulst und darauf gehört, ob SDA wieder auf
> high springt.

Ja, die kannste auch vergessen. Ich habe das Problem seit langem mit 
meiner Wetter Uhr. I2C über Cortex Hardware. 1-2 Monat hängt I2C sich 
auf am EEPROM.(Lochrasteraufbaue in freier Luft) Und da hilft nur ein 
Stecker raus/rein. Die EEPROM Statemachine kriegt man nicht mehr in die 
Spur. I2C hängt sich immer dann auf, wenn die beiden SM außer Takt 
geraten. Und da reicht ein Glitch aus von wenigen Nanosekunden.

von Stefan F. (Gast)


Lesenswert?

Andreas S. schrieb:
> Was mache ich denn dann mit den Serienwiderständen?

Das hat er so gemeint:
1
              3,3V
2
            +-----+
3
            |     |
4
           |~|   |~|   PullUps 2,7kΩ
5
           |_|   |_|
6
            |     |
7
I²C Bus ================================================= SDA und SCL
8
            |     |          |     |          |     |
9
           |~|   |~|        |~|   |~|        |~|   |~|   
10
           |_|   |_|        |_|   |_|        |_|   |_|   47Ω
11
            |     |          |     |          |     |
12
           SDA   SCL        SDA   SCL        SDA   SCL
13
          Mikrochip 1      Mikrochip 2       Mikrochip 2

Wenn jetzt irgend ein Mikrochip den Bus permanent auf Low zieht, kannst 
du ihn anhand der Spannungsabfälle an den unteren Widerständen 
identifizieren. Bei einem wirst du aufgrund des Stromflusses ca. 50mV 
Spannungsabfall messen, bei den anderen nicht.

Es sei denn, mehrere Mikrochips blockieren den Bus gleichzeitig. Aber 
das siehst du dann schon. Viel Glück.

von Helge (Gast)


Lesenswert?

Christian J. schrieb:
> Und da hilft nur ein
> Stecker raus/rein

Würde es auch helfen per watchdog IC den MCU zu resetten ohne VCC 
abzuschalten?

von Stefan F. (Gast)


Lesenswert?

Helge schrieb:
> Würde es auch helfen per watchdog IC den MCU zu resetten ohne VCC
> abzuschalten?

Nicht, wenn ein anderes IC den Bus blockiert.

von Olaf (Gast)


Lesenswert?

> Würde es auch helfen per watchdog IC den MCU zu resetten ohne VCC
> abzuschalten?

Nein. Die Statemachine in der eine MCU kannst du ja neu initialisieren 
und wenn der Hersteller da keinen grossen Murks gebaut hat, kommt vor, 
sollte sie dann wieder gehen. Das Problem sind aber deine Slave.

Olaf

von Helge (Gast)


Lesenswert?

Ok, wie wird das aber denn in professionellen Produkten gemacht? Da 
müsste man ja jeden Slave abschaltbar machen? Eine Zeitschaltuhr für die 
Steckdose zB, die eine RTC verwendet müsste dann ja höchst unzuverlässig 
sein, wenn sich da nach 5 Monaten Betrieb plötzlich der Bus aufhängt.
Irgendwo wurde beschrieben als Lösung, wenn der Bus hängt, einen GPIO 
pin mit SDA zu verbinden, und im Fehlerfall damit SDA auf LOW zu 
ziehen..aber das resettet doch auch nicht die Slaves?

von Stefan F. (Gast)


Lesenswert?

Helge schrieb:
> Da müsste man ja jeden Slave abschaltbar machen?

Ja, in der Tat. habe ich auch schon so gesehen.

Helge schrieb:
> im Fehlerfall damit SDA auf LOW zu
> ziehen..aber das resettet doch auch nicht die Slaves?

Vielleicht hatte dieser Slave eine spezielle Funktion/Schaltung die das 
als Reset-Signal interpretiert hat.

von Joachim B. (jar)


Lesenswert?

Stefan ⛄ F. schrieb:
> Nicht, wenn ein anderes IC den Bus blockiert.

deswegen muss man die Möglichkeit haben dem I2C Blockierer wenigstens 
einen power on reset aufzudrücken.
Bei kleinen I2C kann man das sogar aus einem Port speisen, bei dicken 
Verbrauchern hilft vielleicht ein Photomos Relais, ist jedenfalls 
sicherer zu erzeugen als an den I2C Pins zu wackeln, auch das SOLL Ja 
einen Reset auslösen, aber wenn der Slave nicht reagiert hilft nur 
Stecker ziehen oder Power für den abschalten!

von Peter D. (peda)


Lesenswert?

Dumme I2C-Slaves (EEPROM, IO-Port, ADC) kann man einfach 9-mal takten, 
dann ist SDA wieder high. VCC abschalten ist Quatsch.

Nur Slaves mit MC können sich aufhängen. Meistens liegt das daran, daß 
das Slave-I2C buggy ist. Bei den AVRs habe ich deshalb ein Timeout 
einbauen müssen. Wenn sich da der Slave aufhängt, d.h. SDA >1ms low 
bleibt, wird das I2C disabled und wieder neu aufgesetzt.

von Helge (Gast)


Lesenswert?

@Peter, dann wäre das bei RTC, OLED und EEPROM doch kein Thema?
Ganz schön verwirrend das ganze

von Olaf (Gast)


Lesenswert?

> Ok, wie wird das aber denn in professionellen Produkten gemacht? Da
> müsste man ja jeden Slave abschaltbar machen?

Professionell ist ein weites Feld. Bei irgendeinem Aldi-Grabbelzeug wird 
das den Hersteller gar nicht interessieren. Bei wichtigem SIL2 Kram 
verbaut man einfach kein I2C. Dazwischen gibt es dann die Moeglichkeit 
zu schalten. Zum Beispiel ueber Loadswitches oder manchmal kann man 
sogar direkt einen Portpin als VCC verwenden.

Olaf

von Helge (Gast)


Lesenswert?

Wie würde man das mit den Pullup Widerständen machen? VCC des EEPROMs 
könnte man an einen pin vom MCU direkt hängen. Display und RTC über 
Highside switches abtrennen. So könnte man alle Slaves abtrennen, die 
Pullups wären trotzdem dann noch mit VCC verbunden. Brauchen die 
ebenfalls einen Switch? Könnte mir vorstellen, dass die Slaves 
rückgespeist werden. Beim Display ist das manchmal der Fall zb

von Stefan F. (Gast)


Lesenswert?

Die Pull-Ups musst du natürlich auch abschalten, denn (fast) kein IC 
verträgt an seinen Eingängen wesentlich mehr Spannung als die eigene 
Versorgungsspannung.

von Peter D. (peda)


Lesenswert?

Gute Erfahrungen hatte ich mit original Phillips-MCs gemacht, die laufen 
einfach 24/7 ohne jeden Timeout oder sonstige Würgarounds.
Z.B. der bekannte P80C652 oder der Nachfolger P89C668. Leider hat NXP 
die verbannt.
Atmel hat I2C leider nicht mehr verstanden und sowohl bei den 8051 als 
auch den AVRs gepatzt. Das Atmel I2C ist SW-mäßig zum Philips I2C 
identisch, aber eben nicht in der HW-Implementierung. Auch hat sich 
Tekmos am TK89C668 als NXP-Ersatz versucht und ist gescheitert. Deren 
I2C blieb schon beim Init hängen.
Single-Master schaffen viele MCs gerade noch, aber Multimaster oder 
Slave sind ein Problem.
Ich hab daher alle Neuentwicklungen auf CAN umgestellt.

von Helge (Gast)


Lesenswert?

>Ich hab daher alle Neuentwicklungen auf CAN umgestellt.
Hast du hierzu mehr Informationen?

von Olaf (Gast)


Lesenswert?

> Gute Erfahrungen hatte ich mit original Phillips-MCs gemacht, die laufen

Die Probleme treten aber in aller Regel im Slave auf und nicht im 
Master. Den Master kannst du ja jederzeit neu konfigurieren oder besser 
aufsetzen auf das du dort keine Probleme hast.

> Single-Master schaffen viele MCs gerade noch, aber Multimaster oder
> Slave sind ein Problem.

Das ist richtig. Auch wenn ich vermute das da ein Teil der Probleme 
immer auch vor dem Monitor sitzt. I2C, besonders als Teil eine 
Multiseriellen-Einheit die auch noch SPI und RS232 kann, ist auch fuer 
den Anwender komplex.
Allerdings halte ich Multimaster bei I2C sowieso fuer quatsch. Wenn man 
eine solche Funktionalitaet braucht hat man IMHO die Grenze 
ueberschritten wo dieser Busttyp noch sinnvoll ist.

Olaf

von Andreas S. (newpiccer)


Lesenswert?

Moin Alle,
vielen Dank für eure Beiträge.
Wieder einmal bin ich in die Datenblattfalle getappt:
Wer braucht schon sowas? Das geht doch auch ohne!
In meinen PIC-Projekten hatte ich das große Glück, dass ich von Anfang 
an zwischen zwei Temperaturabfragen vom MLX90614 20ms Pause eingeschoben 
habe. Nach 20ms geht aber der Temperatursensor von sich aus in IDLE, 
wenn nichts mehr von ihm verlangt wird! Will man ihn aber häufiger 
benutzen, muss man alle Daten von ihm verlangen, sonst wird er bockig:
Er stellt nicht nur zwei Temperaturwerte (LO-Byte, HI-Byte) zur 
Verfügung, sondern auch noch einen PEC (Prüfwert). Den muss man auch 
noch abfragen, bevor man die Kommunikation mit ihm beendet. Zwei bis 
fünf Mal macht er trotzdem mit, macht dann aber zu!
Sobald ich das dritte Datum auch noch abgefragt hatte, war alles in 
Butter.
Jetzt würde ich euch ja meinen Source-Code im nötigen Format zeigen, 
weil ich gelernt hab, dass PDF nicht gewünscht ist, aber wie mache ich 
das?

Einen schönen Tag
Andreas

von Stefan F. (Gast)


Lesenswert?

Andreas S. schrieb:
> Jetzt würde ich euch ja meinen Source-Code im nötigen Format zeigen,
> weil ich gelernt hab, dass PDF nicht gewünscht ist, aber wie mache ich
> das?

Als Datei anhängen, würde ich mal sagen. Oder wenn er kurz ist, in 
entsprechende Tags einbetten, also
1
[c] und [/c]
.

von HildeK (Gast)


Lesenswert?

Andreas S. schrieb:
> Jetzt würde ich euch ja meinen Source-Code im nötigen Format zeigen,
> weil ich gelernt hab, dass PDF nicht gewünscht ist, aber wie mache ich
> das?

Einfach den/die C-Quellfiles hier anhängen.
Die Forensoftware hat eine Funktion 'Codeansicht' mit gutem 
Syntax-Highlighting.
PDF ist tatsächlich Sch.... hier.

von Andreas S. (newpiccer)


Lesenswert?

Ich versuche es mal:
1
while (1) {
2
    _delay_us(50);
3
  //Start:
4
    TWCR = (1<<TWINT)|(1<<TWSTA)|(1<<TWEN); //Start transmission
5
    while (!(TWCR & (1<<TWINT))); //Wait for Interrupt Flag, startcondition is sent
6
    while((TWSR & 0xF8)!= 0x08); //Start condition has been transmitted
7
  //Send slave address and read/write (1/0)
8
    TWDR = (0x5A<<1); //0x5A << 1 plus LSB = 0 Master write
9
    TWCR = (1<<TWINT) | (1<<TWEN); //Initialize the transmission
10
    while (!(TWCR & (1<<TWINT))); //Wait for Interrupt Flag, address has been sent
11
    while((TWSR & 0xF8)!= 0x18);  //Slaveaddress + W has been send, ACK
12
  //Send 8-bit-data to the slave
13
    TWDR = 0x07; //Adress of the temperatur register
14
    TWCR = (1<<TWINT) | (1<<TWEN); //Initialize the transmission
15
    while (!(TWCR & (1<<TWINT))); //Wait for Interrupt Flag, register has been sent
16
    while((TWSR & 0xF8) != 0x28);//Data has been transmitted, ACK
17
  //Send repeated start condition
18
    TWCR = (1<<TWINT)|(1<<TWSTA)|(1<<TWEN); //Repeated Start Condition
19
    while (!(TWCR & (1<<TWINT))); //Wait for Interrupt Flag, startcondition is sent
20
    while((TWSR & 0xF8)!= 0x10); //Rep. start condition has been send, ACK
21
  //Send slave address and read/write (1/0)
22
    TWDR = (0x5A<<1)|(1<<0); //0x5A << 1 plus LSB = 1 Master read
23
    TWCR = (1<<TWINT) | (1<<TWEN); //Initialize the transmission
24
    while (!(TWCR & (1<<TWINT))); //Wait for Interrupt Flag, address has been sent
25
    while ((TWSR & 0xF8)!= 0x40); //Slaveaddress + R has been send, ACK
26
  //Read 8-bit-data from the slave
27
    TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWEA); //Initialize the transmission, not the last data to be received
28
    while (!(TWCR & (1<<TWINT))); //Wait for Interrupt Flag, address has been sent
29
    while ((TWSR & 0xF8)!= 0x50); //Data has been received, ACK
30
    Temperatur_LO = TWDR;
31
  //Read again 8-bit-data from the slave
32
    TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWEA); //Initialize the transmission, not the last data to be received
33
    while (!(TWCR & (1<<TWINT))); //Wait for Interrupt Flag, address has been sent
34
    while ((TWSR & 0xF8)!= 0x50); //Data has been received, ACK
35
    Temperatur_HI = TWDR;
36
  //Read PEC from the slave
37
    TWCR = (1<<TWINT) | (1<<TWEN); //Initialize the transmission, now the last data to be received
38
    while (!(TWCR & (1<<TWINT))); //Wait for Interrupt Flag, address has been sent
39
    while ((TWSR & 0xF8)!= 0x58); //Data has been received, NACK terminates the transmission
40
    PEC = TWDR;
41
  //Send stop condition
42
    TWCR= (1<<TWINT)|(1<<TWEN)|(1<<TWSTO);
43
    while(!(TWCR & (1<<TWSTO)));  // Wait till stop condition is transmitted
44
  }
Na sieht doch ganz gut aus.
Vielen Dank.

von Stefan F. (Gast)


Lesenswert?

Andreas S. schrieb:
> Na sieht doch ganz gut aus.

Wenn du jetzt noch die wiederholten Registerzugriffe in Funktionen mit 
sprechenden Namen packst, wird der Code besser lesbar, weniger 
Fehleranfällig und du kannst dir die wiederholten Kommentare sparen. 
Etwa so:
1
void TWI_Start()
2
{
3
    TWCR = (1<<TWINT)|(1<<TWSTA)|(1<<TWEN); //Start transmission
4
    while (!(TWCR & (1<<TWINT))); //Wait for Interrupt Flag, startcondition is sent
5
    while((TWSR & 0xF8)!= 0x08); //Start condition has been transmitted
6
}
7
8
#define READ true
9
#define WRITE false
10
void TWI_Send_Address(uint8_t slaveAddr, bool readMode)
11
{
12
    if (readMode)
13
    {
14
       TWDR = (slaveAddr<<1)+1; // LSB = 1 Master read
15
    }
16
    else
17
    {
18
       TWDR = (slaveAddr<<1)+0; // LSB = 0 Master write
19
    }
20
    TWCR = (1<<TWINT) | (1<<TWEN); //Initialize the transmission
21
    while (!(TWCR & (1<<TWINT))); //Wait for Interrupt Flag, address has been sent
22
    if (readMode)
23
    {
24
        while ((TWSR & 0xF8)!= 0x40); //Slaveaddress + R has been send, ACK
25
    }
26
    else
27
    {
28
        while((TWSR & 0xF8)!= 0x18);  //Slaveaddress + W has been send, ACK
29
    }
30
}
31
32
void TWI_Send_Data(uint8_t data)
33
{
34
    TWDR = (data); 
35
    TWCR = (1<<TWINT) | (1<<TWEN); //Initialize the transmission
36
    while (!(TWCR & (1<<TWINT))); //Wait for Interrupt Flag, address has been sent
37
    while((TWSR & 0xF8) != 0x28);//Data has been transmitted, ACK
38
}
39
40
void TWI_Repeat_Start()
41
{
42
    TWCR = (1<<TWINT)|(1<<TWSTA)|(1<<TWEN); //Repeated Start Condition
43
    while (!(TWCR & (1<<TWINT))); //Wait for Interrupt Flag, startcondition is sent
44
    while((TWSR & 0xF8)!= 0x10); //Rep. start condition has been send, ACK
45
}
46
47
#define ACK true
48
#define NACK false
49
uint8_t TWI_Read(bool sendAck)
50
{
51
    TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWEA); //Initialize the transmission, not the last data to be received
52
    while (!(TWCR & (1<<TWINT))); //Wait for Interrupt Flag, address has been sent
53
    if (sendAck)
54
    {
55
        while ((TWSR & 0xF8)!= 0x50); //Data has been received, ACK
56
    }
57
    else
58
    {
59
        while ((TWSR & 0xF8)!= 0x58); //Data has been received, NACK terminates the transmission
60
    }
61
    return TWDR;
62
}
63
64
void TWI_Stop()
65
{
66
    TWCR= (1<<TWINT)|(1<<TWEN)|(1<<TWSTO);
67
    while(!(TWCR & (1<<TWSTO)));  // Wait till stop condition is transmitted
68
}
69
70
while (1) 
71
{
72
    _delay_us(50);
73
    TWI_Start();
74
    TWI_Send_Address(0x5A,WRITE); // Address of the I²C slave
75
    TWI_Send_Data(0x07); //Adress of the temperatur register
76
    TWI_Repeat_Start();
77
    TWI_Send_Address(0x5A,READ);
78
    Temperatur_LO = TWI_Read(ACK);
79
    Temperatur_HI = TWI_Read(ACK);
80
    PEC = TWI_Read(NACK);
81
    TWI_Stop();
82
}

von Andreas S. (newpiccer)


Angehängte Dateien:

Lesenswert?

Stefan ⛄ F. schrieb:
> Wenn du jetzt noch die wiederholten Registerzugriffe in Funktionen mit
> sprechenden Namen packst, wird der Code besser lesbar

Ja, da hast du natürlich Recht. Aber mir ging es erst mal darum, das 
Programm ans Laufen zu kriegen...

Mein Ziel war es, das Ganze ins Interrupt zu packen, da sieht es sowieso 
nochmal anders aus. (s. Anhang)
Das Programm ist geschrieben für Atmel Studio 7.0, in dem es den Data 
Visualizer gibt. Baud Rate 38400! Nicht 9600.

Schönen Tag
Andreas

von Olaf (Gast)


Lesenswert?

> habe. Nach 20ms geht aber der Temperatursensor von sich aus in IDLE,
> wenn nichts mehr von ihm verlangt wird! Will man ihn aber häufiger

Glaubst du es macht Sinn eine Temperatur so haeufig abzufragen?
Zumal dann auch die Gefahr besteht das sich der arme Sensor durch
das haeufige auslesen auch selbst staerker erwaermt und ungenauer misst?

Olaf

von Andreas S. (newpiccer)


Lesenswert?

Hallo Olaf,
wenn man einen Roboter mit 0,5m/s fahren lässt und man damit auf der 
Suche nach Wärmequellen ist, die ca. 2cm breit sind, dann hast du keine 
andere Wahl. Daher ist es auch wichtig, dass Programmteile, die ein 
eigenes Modul im MC haben, in den Interrupt gepackt werden, damit alle 
möglichen Sensoren "gleichzeitig" ausgelesen werden können und zur 
Verarbeitung zur Verfügung stehen und auch dafür noch genug Zeit ist.
Ich kann mir übrigends nicht vorstellen, dass bei einer Duty-Zeit von 
ca. 600us und einer Not-Duty-Zeit von 20ms, sich ein Sensor signifikant 
erwärmt. Jedenfalls sind die Werte die so ermittelt werden plausibel und 
ausreichend. Müsste ich mal testen...

Vielen Dank.
Einen schönen Tag
Andreas

von Dergute W. (derguteweka)


Lesenswert?

Moin,

Andreas S. schrieb:
> wenn man einen Roboter mit 0,5m/s fahren lässt und man damit auf der
> Suche nach Wärmequellen ist, die ca. 2cm breit sind, dann hast du keine
> andere Wahl.

Hat schon einen Grund, warum HD-Videosignale nur eher selten ueber I2C 
gehen. Bei dir sind nur Aufloesung und betrachtete Wellenlaenge anders 
;-)

Gruss
WK

von Peter D. (peda)


Lesenswert?

Olaf schrieb:
> Allerdings halte ich Multimaster bei I2C sowieso fuer quatsch.

Nö, es ist sogar recht effizient für die Verbindung von mehreren MCs. 
Niemand muß auf den anderen warten, jeder kann senden, wenn er die 
Antwort parat hat. Multimaster-I2C ist quasi der Vorläufer des CAN.
Und die Phillips-MCs beweisen ja, das es geht, wenn man die I2C-Hardware 
entsprechend der Spezifikation entwickelt. Die laufen 24/7 jahrelang 
durch.
Daß die Atmel AVRs buggy sind, ist ja bekannt:
http://www.robotroom.com/Atmel-AVR-TWI-I2C-Multi-Master-Problem.html

von Dergute W. (derguteweka)


Lesenswert?

Moin,

Peter D. schrieb:
>> Allerdings halte ich Multimaster bei I2C sowieso fuer quatsch.
>
> Nö, es ist sogar recht effizient für die Verbindung von mehreren MCs.

Auch wenn du es recht effizient nennst, ich halte es auch fuer Quatsch.

Ich bin der Ansicht: Wenn man sowas wie Multimaster braucht, ist i2c 
nicht mehr der Bus der Wahl. Dann sollte man andere Busse verwenden. Ist 
ja nicht nur der Bus entscheidend, ich muss ja irgendwie auch 
verhindern, dass z.b. 2 Master ins Gehege kommen, wenn jeder am selben 
Device ueber mehrere Kommandos rumschrauben will.
Auch wenns I2C Leitungstreiber gibt, um ueber 15m lange, nasse 
Schnuersenkel einen Slave anzubinden, werd' ich sowas sicherlich nie 
verwenden, nur weil's sowas beklopptes gibt.

Und nicht nur bei AVR gibts Multimasterprobleme. Ich erinnere mich noch 
mit Grauen an ein i2c-peripheral in einem coldfire prozessor, was nur 
Multimaster konnte und alle Furz lang dann der Ansicht war, ein anderer 
(real nicht vorhandener) Master haette grad den Bus, weshalb jetzt 
erstmal nix mehr ginge bis zum naechsten Reset.

Gruss
WK

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?

Andreas S. schrieb:
> Ich versuche es mal

Das sieht so ziemlich nach dem Standardcode fürs (imo beknackte) TWI 
Interface aus. Jetzt muss mir aber mal einer erklären, warum man sich 
das antut.
Das ganze ist doch so zeitraubend, das man auch gleich Bitbanging machen 
kann oder (wie ich das tue) gleich eine passende I2C Lib einsetzt, die 
beide Optionen (Hardware IF oder Bitbanging) bietet.

von Peter D. (peda)


Lesenswert?

Dergute W. schrieb:
> Wenn man sowas wie Multimaster braucht, ist i2c
> nicht mehr der Bus der Wahl.

Was denn dann?
Multimaster-I2C macht die Programmierung sehr einfach. Jeder darf 
senden, wann er Zeit dazu hat. Wichtige Echtzeitaufgaben müssen auf die 
Kommunikation keinerlei Rücksicht nehmen, sie erfolgt ohne Priorität im 
Hintergrund. Durch das Clock-Stretching darf der I2C-Interrupt jederzeit 
unterbrochen werden.

Im Gegensatz dazu muß bei RS-485 der Slave so schnell wie möglich 
antworten. Und der Master muß jedesmal die maximale Antwortzeit 
abwarten, nachdem er die Senderichtung auf Slave umgeschaltet hat. Die 
Kommunikation benötigt also die höchste Priorität und kann andere 
Echtzeitaufgaben stören.

Da ich zuerst Philips genommen hatte, konnte ich ja nicht wissen, daß 
andere Hersteller bei ihrer I2C-Implementierung patzen. Die 
I2C-Spezifikation von Philips sieht auch sehr wasserdicht aus. Alle 
Bedingungen und Timings sind eindeutig definiert. Warum sich andere 
nicht danach richten, kann ich mir nicht erklären.

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Angehängte Dateien:

Lesenswert?

Bin auch Philips Fan und richte mich bei Problemen immer zuerst nach den 
Specs aus den Niederlanden.
Ich hänge mal die 'amtliche' Referenz von Philips an. Die ist nicht sehr 
gross, aber interessant.

von Dergute W. (derguteweka)


Lesenswert?

Moin,

Peter D. schrieb:
> Was denn dann?

Einer ist der Master, der schraubt am Slave via i2c bus. Wenn noch 
irgendwer anderes was von dem Slave haben will, dann soll der sich an 
den Master wenden. Ueber irgendein anderes Interface als ausgerechnet 
diesen i2c Bus. Weil der Master Bescheid weiss, wie's dem Slave grad 
geht, ob der grad Zeit hat oder erst spaeter, weil der Master grad an 
ihm am schrauben ist.

> Multimaster-I2C macht die Programmierung sehr einfach. Jeder darf
> senden, wann er Zeit dazu hat.

Naja, nur auf den ersten Blick. Les' ich grad ein i2c-eeprom komplett 
aus, kann ich mich bei Multimasterbetrieb nicht aufs Autoincrement der 
Adressen verlassen, wenn da potentiell wer anderes zwischenrein quaken 
kann. Beim Schreiben noch weniger.

Lad' ich grad in einen DVB-T Demodulator den DSP Code, will ich nicht, 
dass mir da irgend ein Armloch mittendrinn den Bus klaut, bloss weil der 
wissen will, wie spaet's grad ist. Und weil die Uhr grad auch mal erst 
noch aufwachen muss und clk-stretched, fuehlt sich der Demod nicht mehr 
geliebt und macht Faxen.

Alles streng nach Philips I2C Multimasternorm, aber eher stressfoerdernd 
in der Realitaet.

Gruss
WK

von Peter D. (peda)


Lesenswert?

Dergute W. schrieb:
> Naja, nur auf den ersten Blick. Les' ich grad ein i2c-eeprom komplett
> aus, kann ich mich bei Multimasterbetrieb nicht aufs Autoincrement der
> Adressen verlassen, wenn da potentiell wer anderes zwischenrein quaken
> kann. Beim Schreiben noch weniger.

Nö, solange Du kein STOP sendest, bleibst Du der aktive Master.
Fürs Pagewrite mußt Du ein STOP senden, aber für die nächste Page mußt 
Du eh die komplette Startadresse senden.
EEPROMs lege ich nicht auf den Modulbus, sondern schließe sie direkt an 
den MC an.

von Dergute W. (derguteweka)


Lesenswert?

Moin,

Peter D. schrieb:
> Fürs Pagewrite mußt Du ein STOP senden, aber für die nächste Page mußt
> Du eh die komplette Startadresse senden.

Jepp, beim Schreiben sollte nix passieren koennen, stimmt.
Aber beim "current adress read" muss ich mich verlassen, das keiner seit 
meinem letzten Read am Adresszeiger im eeprom gedreht hat. Genauso bei 
anderen Slaves, die Subaddressierung mit autoincrement unterstuetzen. 
Das machen ein bis zwei, hab' ich geruechteweise gehoert.
Ja, ich weiss, das liegt nicht am Bus, dass da was schief gehen kann. 
Aber es schraenkt die Rieeeesenvorteile des Multimasterbetriebs doch arg 
ein. Mal ganz davon abgesehen, wenn man es mit real existierender HW und 
ihren Spirenzchen zu tun hat.

> EEPROMs lege ich nicht auf den Modulbus, sondern schließe sie direkt an
> den MC an.

Aber warum das denn, streng nach Philips ist das doch gar kein Problem 
<unschuldig guck' & pfeif> ;-)

Gruss
WK

von Peter D. (peda)


Lesenswert?

Dergute W. schrieb:
> Aber warum das denn

Der EEPROM speichert z.B. lokale Kalibrationen des Moduls und außerdem 
schränkt das den Adreßraum unnötig ein. Je nach Typ können nur 1..8 
EEPROMs am selben Bus hängen, z.B. nur ein 24LC16.

von Olaf (Gast)


Lesenswert?

> Je nach Typ können nur 1..8
> EEPROMs am selben Bus hängen, z.B. nur ein 24LC16.

Hast du schon jemals gesehen das jemand 8Stk davon auf einer Platine 
hatte? Das waer doch ziemlich doof. Da kann doch dann besser ein fettes 
FRAM nehmen.

Olaf

von HildeK (Gast)


Lesenswert?

Andreas S. schrieb:
> Ich versuche es mal:while (1) {

> Na sieht doch ganz gut aus.

Ja, viel besser, aber so ist es eher für kurze Codeabschnitte gedacht 
und sinnvoll. Deinen würde ich so als Grenzfall betrachten ...
Eingangs hattest du doch PDFs angehängt, genau so geht das mit dem 
C-Quellfile.
Sieht dann so aus wie z.B. in dem Beitrag (auf Codeansicht klicken):
Beitrag "Re: Atmega Taster einlesen und in Register schreiben funktioniert nicht wie geplant"

Wobei: ganz aktuell scheint die 'Codeansicht' beim Syntax-Highlightning 
beschädigt zu sein. Ich hoffe, das ist nur temporär.

von Stefan F. (Gast)


Lesenswert?

Matthias S. schrieb:
> Jetzt muss mir aber mal einer erklären, warum man sich das antut.

Wegen:

● Slew-rate limited output drivers
● Noise suppression circuitry rejects spikes on bus lines

(https://ww1.microchip.com/downloads/en/DeviceDoc/Atmel-7810-Automotive-Microcontrollers-ATmega328P_Datasheet.pdf 
Kapiterl 21.1)

von Stefan F. (Gast)


Lesenswert?

Dergute W. schrieb:
> Aber beim "current adress read" muss ich mich verlassen, das keiner seit
> meinem letzten Read am Adresszeiger im eeprom gedreht hat.

Das finde ich auch logisch, denn STOP kennzeichnet das Ende der 
Transaktion. Verkettete Transaktionen gibt es nicht.

Die gleichen "Probleme" hast du auch bei Multi-Threaded Systemen, wenn 
du die Boundaries von Transaktionen  missachtest, und das betrifft nicht 
nur I²C.

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
Noch kein Account? Hier anmelden.