Forum: Mikrocontroller und Digitale Elektronik I2C - Pull Up Widerstände


von Teddy (Gast)


Lesenswert?

Hallo,

ich versuche mich zur Zeit mit dem I2C Schnittstelle zu beschäftigen. 
Dazu habe ich mehrere IC´s bestellt, die den I2C unterstützen z.B. den 
MCP23107.
Darum geht es erstmal nicht.

Im Datenblatt von Atmel steht, dass für den I2C 2 Pull Up Widerstände 
gebraucht werden für die SDA und SCL Leitungen.
Kann ich nicht die Internen Pull Ups verwenden?

Der Clock, also SCL könnte ich quasi als Ausgang schalten und dann den 
Pull Up aktivieren. Wie mache ich das mit der SDA Leitung? Dort ist der 
PIN mal Eingang und Ausgang.


Lg

von spess53 (Gast)


Lesenswert?

Hi

>Kann ich nicht die Internen Pull Ups verwenden?

Die sind zu groß. Lies mal

https://www.nxp.com/documents/user_manual/UM10204.pdf

MfG Spess

von oldeurope O. (Gast)


Lesenswert?

spess53 schrieb:
> Die sind zu groß.

nö, zu hochohmig.

;-)

von S. Landolt (Gast)


Lesenswert?

> Kann ich nicht die Internen Pull Ups verwenden?
Der Pullup-Widerstand bildet zusammen mit den unweigerlich vorhandenen 
Kapazitäten ein RC-Glied, hier einen Tiefpass. Wie dieser Begriff 
impliziert, werden Signale geschwächt, je höher deren Frequenz ist. 
Fazit: Je nach Aufbau und angeschlossenen Einheiten kann es reichen oder 
auch nicht. Schreibt ja auch Atmel: "The internal pull-ups can in some 
systems eliminate the need for external ones."

von spess53 (Gast)


Lesenswert?

Hi

Mutierst du jetzt auch noch zum Korinthenkacker.

MfG Spess

von Mark U. (residuum)


Lesenswert?

Der Link oben gibt die Antwort auf Deine Frage in
Kapitel 3.1.1 und
Kapitel 7

von oldeurope O. (Gast)


Lesenswert?

S. Landolt schrieb:
> werden Signale geschwächt

Da hat mal jemand oszillographiert:
Beitrag "Re: Leonardo Pro Micro mit OLED"

:-)

LG
old.

von Wolfgang (Gast)


Lesenswert?

Teddy schrieb:
> z.B. den MCP23107

Was soll das sein?

> Kann ich nicht die Internen Pull Ups verwenden?

Wenn du Soft-I2C machst und die Pull-Ups deines (unbekannten) µC 
ausreichend niederohmig sind, kannst du das machen. Bei Nutzung der 
Hardware-Unit für den I2C, wirst du kaum Gelegenheit haben, deinem 
Prozessor da rein zu reden.

von S. Landolt (Gast)


Lesenswert?

Wolfgang schrieb:
> Bei Nutzung der
> Hardware-Unit für den I2C, wirst du kaum Gelegenheit haben, deinem
> Prozessor da rein zu reden.

Das verstehe ich nicht. Es geht doch offenbar um einen Atmel-uC, und 
selbst der angejahrte ATmega8 hat diese Möglichkeit.
Falls man unbedingt Wert darauf legt, kann man ja die Frequenz 
hinreichend absenken.

von Einer K. (Gast)


Lesenswert?

S. Landolt schrieb:
> Das verstehe ich nicht. Es geht doch offenbar um einen Atmel-uC, und
> selbst der angejahrte ATmega8 hat diese Möglichkeit.
> Falls man unbedingt Wert darauf legt, kann man ja die Frequenz
> hinreichend absenken.

20k bis 50k interne Pullup reichen (meist) nicht.

Die vorgeschlagenen 4k7 sind schon mal ein guter Anfang, wenn der Bus 
nicht zu lang, oder nicht zu viele Bausteine dran hängen.

Erst ein Oszi schafft Klarheit.
Ein LA ist das falsche Werkzeug, da er die Flanken rechteckig formt, und 
einem damit das Wesentliche durch die Lappen gehen kann.
Den LA kann man verwenden, wenn man weiß, dass die Flanken sauber genug 
sind.

Bitte die Spezifikation lesen und auch so anwenden.

von Teddy (Gast)


Lesenswert?

Ich habe keinen Oszi, wie kann ich mit einem Handmultimeter oder mit 
paar elektronischen Bauelementen gucken, ob die I2C Schnittstelle 
funktioniert?

von S. Landolt (Gast)


Lesenswert?

"Ob die I2C Schnittstelle funktioniert" lässt sich auch mit einem 
Oszilloskop nicht feststellen, schließlich geht in die 
Funktionsfähigkeit erheblich mehr ein als die elektrischen Verhältnisse 
auf dem Bus.
  Worin besteht denn das Hindernis, externe Pull-ups zu verwenden?

von Clemens L. (c_l)


Lesenswert?

Teddy schrieb:
> wie kann ich ... gucken, ob die I2C Schnittstelle funktioniert?

Du drehst die Frequenz solange höher, bis es nicht mehr funktioniert. 
Dann nimmst du sicherheitshalber ein Zehntel davon.

von Teddy (Gast)


Lesenswert?

S. Landolt schrieb:
> "Ob die I2C Schnittstelle funktioniert" lässt sich auch mit einem
> Oszilloskop nicht feststellen, schließlich geht in die
> Funktionsfähigkeit erheblich mehr ein als die elektrischen Verhältnisse
> auf dem Bus.
>   Worin besteht denn das Hindernis, externe Pull-ups zu verwenden?

Keine. Werde dies noch machen.
Muss ich die Ports als Ausgänge definieren oder regelt das der I2C 
Controller selber?

von HildeK (Gast)


Lesenswert?

Teddy schrieb:
> Der Clock, also SCL könnte ich quasi als Ausgang schalten und dann den
> Pull Up aktivieren. Wie mache ich das mit der SDA Leitung? Dort ist der
> PIN mal Eingang und Ausgang.

Unabhängig davon, dass es, wie schon gesagt, mit den internen Pulls 
nicht gehen wird:
- Pullups gibts nur, wenn der Pin auf Input steht
- auch ein I2C-Takt darf nicht auf HIGH getrieben werden, der Slave 
könnte Clock stretching machen. Das ist zwar bei dem MCP23017 (nicht 
23107!) nicht so, aber andere Devices machen das ggf. Man müsste also 
beide so bedienen.

Wenn du einen Pinx in einer Funktion wie SDA schalten willst (bei 
ATMEL), brauchst du jeweils zwei Befehle:
- HIGH_pulled: DDRx auf Input, PORTx auf '1', aktiviert dann den Pull
- LOW: PORTx auf '0', DDRx auf Output

Mit externen Pullups, die bei I2C notwendig sind, geht das dann so:
- PORTx immer auf '0' lassen
- HIGH: DDRx auf Input
- LOW:  DDRx auf Output

von S. Landolt (Gast)


Lesenswert?

> regelt das der I2C Controller selber?
Exemplarisch aus dem Datenblatt des ATmega1284P zu TWCR:
When TWEN is written to one, the TWI takes control over the I/O pins 
onnected to the SCL and SDA pins, enabling the slew-rate limiters and 
spike filters.


Aber eine Kommunikation im Anderthalbstundenrhythmus liegt mir nicht -
Da sprach der Prinz von Pakistan ...

von Teddy (Gast)


Lesenswert?

Was denn nun? Im Datenblatt steht wohl, dass der Controller es 
automatisch tut aber Herr HildeK meint, man müsse selber die Ports 
definieren.

Was ist mit High und Low gemeint?
Die SDA und SCL Ports liegen im Arduino Boards bei A4 und A5.
Also:

DDRD=0X00
PortD= 0X00  ?

von Prinz von Pakistan (Gast)


Lesenswert?

Das müsste HildeK selbst beantworten.
Nach meinem Dafürhalten spricht er von Soft-I2C, dies aber halte ich als 
Einstieg für einen Anfänger für wenig geeignet.

von Patrick J. (ho-bit-hun-ter)


Lesenswert?

Hi

Da es hier, auf ein Mal, um einen Arduino geht - siehe dort bitte in der 
entsprechenden Funktion nach, WAS Du beschalten musst.

... gehe davon aus, daß je ein 4K7 als PullUp Verwendung findet ...

Den Rest macht die Lib des Arduino. (also IN/OUT umschalten, Pegel 
erfassen und aus dem Müll Bytes raus fischen)

Bei etwas mehr Eigeninteresse hätte Dich wohl eine beliebige 
Suchmaschine zu Hintergrundinformationen gebracht - Du hast das Bild der 
Arduino-Jünger nicht sonderlich verbessert ...

MfG

von Teddy (Gast)


Lesenswert?

Es ist ein Arduino Board, aber programmiert wird über das Atmel Studio.

von Einer K. (Gast)


Lesenswert?

Teddy schrieb:
> Keine. Werde dies noch machen.
> Muss ich die Ports als Ausgänge definieren oder regelt das der I2C
> Controller selber?

Genau!
Bau die 4k7 Pullup ein, den Rest macht die Arduino Wire Lib für dich.

Warnung:
Ein paar Arduinos haben die nötigen Pullup schon an Bord.
Prüfe das.
Vorher!

von Teddy (Gast)


Lesenswert?

Ähh eben nicht.
Ich greife nicht auf die Arduino Libs sondern programmiere zu Fuß wie 
ich nur den Avr Chip habe.

von HildeK (Gast)


Lesenswert?

Teddy schrieb:
> Was denn nun? Im Datenblatt steht wohl, dass der Controller es
> automatisch tut aber Herr HildeK meint, man müsse selber die Ports
> definieren.

Ich habe nur exemplarisch aufgezeigt, wie man es machen könnte. Ich habe 
nicht den Überblick, ob alle Controler I2C als Hardware unterstützen.
Und du hattest ja bis dahin keinen Controller genannt - oder?

von Einer K. (Gast)


Lesenswert?

Teddy schrieb:
> Ähh eben nicht.

Dann streiche:
>  den Rest macht die Arduino Wire Lib für dich.

von Patrick J. (ho-bit-hun-ter)


Lesenswert?

Hi

Welcher µC?
Wenn AVR, die ATtiny können TWI/I²C nicht von Haus aus.
Die ATmega, bei Denen ich bisher rumgeschmökert hatte, wohl schon.
Das Datenblatt des verwendeten µC könnte Klarheit darüber geben, ob die 
erforderlichen PullUps in den µC direkt verbaut sind oder ob trotzdem 
externe PullUps verwendet werden müssen.

Selber habe ich 'komplett zu Fuß' programmiert mit mäßigem Erfolg (alle 
paar tausend Ausgaben macht das Display, was Es will ... oder ich sende 
eben Mist).
Umgeschaltet wird hier NUR zwischen IN (ohne PullUp, Der hängt außen 
dran) und OUT (dann auf LOW) - da brauchst Du nur für ein HIGH oder das 
Einlesen des Pegel den Pin auf IN zu stellen und für ein zu sendendes 
LOW den Pin auf OUT umschalten.
Nach der Bitzeit bzw. spätestens nach den Nutzbits wieder auf IN, was 
den Bus auf HIGH gehen lässt (wegen der externen PullUp).
Wenn da kein HIGH anliegt, zieht 'wer Anders' am Bus - und dort beginnt 
die Kunst, die I²C-Komunikation beschussfest zu machen.

Aktiv können alle Teilnehmer die Drähte bestenfalls auf LOW ziehen.

MfG

von spess53 (Gast)


Lesenswert?

Hi

>Selber habe ich 'komplett zu Fuß' programmiert mit mäßigem Erfolg (alle
>paar tausend Ausgaben macht das Display, was Es will ... oder ich sende
>eben Mist).

Schon mal die Atmel AppNotes versucht?

MfG Spess

von Teddy (Gast)


Angehängte Dateien:

Lesenswert?

Es ist ein Atmega328P. Dieser kann I2C.
Ich habe zur Hand nur 5kOhm Widerstände, diese sollten auch gehen oder?
Ich komme hier eigentlich nicht klar. Ich bin dem Datenblatt und dieser 
Seite http://www.embedds.com/programming-avr-i2c-interface/ gefolgt, 
jedoch kann ich an einen Pin des MCP23017 nichts schalten.
Es liegt keine Spannung an, mag jemand mal den Code anschauen?

von spess53 (Gast)


Lesenswert?

Hi

>Ich bin dem Datenblatt und dieser
>Seite http://www.embedds.com/programming-avr-i2c-interface/ gefolgt,
>jedoch kann ich an einen Pin des MCP23017 nichts schalten.

Liegt es jetzt an den I2C-Routinen oder am Verständnis des MCP23017? Für 
jemand, der noch nie I2C programmiert hat hätte ich etwas einfacheres 
empfohlen.

MfG Spess

von Teddy (Gast)


Lesenswert?

Beides. Ist hart da von Null auf durchzublicken.

von spess53 (Gast)


Lesenswert?

Hi

>Beides. Ist hart da von Null auf durchzublicken.

Warum fängst du dann mit Secondhand Software an, und nicht mit den Atmel 
Appnotes? Irgendwo bei AVR31.. sollte sich etwas finden lassen.

MfG Spess

von Teddy (Gast)


Lesenswert?

spess53 schrieb:
> Hi
>
> Beides. Ist hart da von Null auf durchzublicken.
>
> Warum fängst du dann mit Secondhand Software an, und nicht mit den Atmel
> Appnotes? Irgendwo bei AVR31.. sollte sich etwas finden lassen.
>
> MfG Spess

Da ich aber bereits an der Sache dran bin, würde ich es gerne zu Ende 
machen wollen.

von spess53 (Gast)


Lesenswert?

Hi

>Da ich aber bereits an der Sache dran bin, würde ich es gerne zu Ende
>machen wollen.

Hast du denn schon mal eine funktionierende Verdindung zu I2C-Slave 
hergestellt?

MfG Spess

von spess53 (Gast)


Lesenswert?

Hi

>Hast du denn schon mal eine funktionierende Verdindung zu I2C-Slave
>hergestellt?

Korrektur;

Hast du denn schon mal eine funktionierende Verdindung zu Irgend einem 
I2C-Slave hergestellt?

MfG Spess

von Teddy (Gast)


Lesenswert?

spess53 schrieb:
> Hi
>
>>Hast du denn schon mal eine funktionierende Verdindung zu I2C-Slave
>>hergestellt?
>
> Korrektur;
>
> Hast du denn schon mal eine funktionierende Verdindung zu Irgend einem
> I2C-Slave hergestellt?
>
> MfG Spess

Scheint leider nicht zu funktionieren.
Nachdem ich die Adresse 0x20 gesendet habe, wird ja im Status Register 
ein Flag gesetzt. Diese überprüfe ich gemäß Datenblatt.
Wird sie erfüllt, ok. Wenn nicht, dann soll bei mir eine LED leuchten.
Und sie leuchtet >.<
ergo, läuft nicht.

Ich habe zu Testzwecken eine fertige Arduino Bibliothek heruntergeladen, 
um zu Überprüfen, ob mein Aufbau ersten in Ordnung ist und zweitens, der 
Chip funkioniert.
Letzendlich ist beides okay.

Das heißt, der Wurm sitzt irgendwo in meinem Programm Code.
Diese habe ich zuvor hochgeladen.

von Teddy (Gast)


Lesenswert?

Ich hänge hier noch die If Abfrage ein.
Dieser steht in der I2C_Senden Funktion:
  if((TWSR & 0xF8)!=0x18)
  {
    PORTB=0x01;
  }

von Teddy (Gast)


Lesenswert?

spess53 schrieb:
> Hi
>
>>Hast du denn schon mal eine funktionierende Verdindung zu I2C-Slave
>>hergestellt?
>
> Korrektur;
>
> Hast du denn schon mal eine funktionierende Verdindung zu Irgend einem
> I2C-Slave hergestellt?
>
> MfG Spess

Ich glaube, jetzt habe ich die Verbindung zum Slave hergestellt.
Die eingegebene Adresse war anscheinend falsch.
Die Adresse lautet gemäß Seite 8 von dem MCP Manual 0x40, wenn ich A0, 
A1 und A2 auf 0 lege.
Oder interpretiere ich das falsch?

von Wolfgang (Gast)


Lesenswert?

Teddy schrieb:
> Die Adresse lautet gemäß Seite 8 von dem MCP Manual 0x40, wenn ich A0,
> A1 und A2 auf 0 lege.
> Oder interpretiere ich das falsch?

0x40 ist der Wert des ersten Bytes bei einem Schreibzugriff.
Die Slave Adresse für A0..2=0 ist immer 0x20 (Datenblatt Fig. 1-2)

von Teddy (Gast)


Lesenswert?

Da steht dann aber
0100 0000 = 0x40

von Wolfgang (Gast)


Lesenswert?

Teddy schrieb:
> Da steht dann aber
> 0100 0000 = 0x40

Eben, das Control Byte ist 0x40 und setzt sich zusammen aus der I2C 
Slave Adresse in den ersten 7 Bit (0b0100000) und dem R/W Bit an 
unterster Stelle, zusammen
1
0x40 = 0x20 << 1 | RW
.

von Pat A. (patamat)


Lesenswert?

Teddy schrieb:
> Da steht dann aber
> 0100 0000 = 0x40

Das ist die Slaveadresse incl. R/W-Bit. Oft werden I2C-Adressen auch 
ohne R/W-Bit angegeben. Das wäre hier dann 0x20.

Bei I2C heißt es immer Aufpassen, ob 7- oder 8-Bit Adressen gemeint 
sind.

von Teddy (Gast)


Lesenswert?

Dann stehe ich gerade auf dem Schlauch und komme nicht weiter.

Die Adresse 0x20 wird eingegeben und versendet, aber es taucht immer die 
Fehlermeldung auf, dass die Adresse anscheinend nicht stimmt, oder der 
ACK Bit vom Slave nicht empfangen werden konnte.

Habe auf die Fehlermeldung 0x18 und 0x20 geprüft (siehe Seite 273 vom 
Atmega 328P Datenblatt).

von spess53 (Gast)


Lesenswert?

Hi

>Dann stehe ich gerade auf dem Schlauch und komme nicht weiter.

Dann zeige doch mal deine Routine mit der die Adresse gesendet wird.

MfG spess

von Fana Ticker (Gast)


Lesenswert?

Wolfgang schrieb:
> 0x40 ist der Wert des ersten Bytes bei einem Schreibzugriff.
> Die Slave Adresse für A0..2=0 ist immer 0x20 (Datenblatt Fig. 1-2)

Auch wenn hier verschiedene widersprüchliche Weisheiten
verbreitet werden ist die Adresse für diesen Baustein
immer noch 0x40 für schreiben und 0x41 für lesen (wenn
A0, A1 und A2 = 0).

Auch nach Datenblatt Fig. 1-2

von Teddy (Gast)


Angehängte Dateien:

Lesenswert?

spess53 schrieb:
> Hi
>
>>Dann stehe ich gerade auf dem Schlauch und komme nicht weiter.
>
> Dann zeige doch mal deine Routine mit der die Adresse gesendet wird.
>
> MfG spess

Die C Datei habe ich doch hochgeladen.
Aber ich stelle es gerne erneut hoch.

von spess53 (Gast)


Lesenswert?

Hi

> void I2C_Adresse(uint8_t Adresse)
>{
>  TWDR = Adresse;

In dem Fall muss Adresse aus 0x40 + RW-Bit bestehen (wenn A0/1/2=0 
sind).

MdG Spess

von Teddy (Gast)


Lesenswert?

spess53 schrieb:
> Hi
>
>> void I2C_Adresse(uint8_t Adresse)
>>{
>>  TWDR = Adresse;
>
> In dem Fall muss Adresse aus 0x40 + RW-Bit bestehen (wenn A0/1/2=0
> sind).
>
> MdG Spess

Also war 0x40 doch richtig?
Für schreiben ist RW-Bit 0, also ist die Adresse 0x40.
Da kommt keine Fehlermeldung. Aber dennoch wird nichts durchgeschaltet, 
wenn ich den oben genannten Code durchlaufen lasse.

Bei RW-Bit=1 zum schreiben ist die Adresse 0x41 und da kommt wieder die 
Fehlermeldung.

von Wolfgang (Gast)


Lesenswert?

Fana Ticker schrieb:
> Auch nach Datenblatt Fig. 1-2

In Fig 1-2 hat die Slave Adresse 7 Bit, wie es der I2C-Spezifikation 
(S.15) entsprich und genau den Wert 0x20. Was da an Bits rangepfriemelt 
ist, ändert nichts an dem Wert.
http://i2c2p.twibright.com/spec/i2c.pdf

von Teddy (Gast)


Lesenswert?

Wolfgang schrieb:
> Fana Ticker schrieb:
>> Auch nach Datenblatt Fig. 1-2
>
> In Fig 1-2 hat die Slave Adresse 7 Bit, wie es der I2C-Spezifikation
> (S.15) entsprich und genau den Wert 0x20. Was da an Bits rangepfriemelt
> ist, ändert nichts an dem Wert.
> http://i2c2p.twibright.com/spec/i2c.pdf

Du hängst am Ende sozusagen eine Null dran, richtig?
Dann ist die Adresse 0x20.
Aber ich kann doch nur Byteweise senden, d.h. ich nehme den RW-Bit mit 
und sage dem Slave, ob er lesen oder schreiben soll.

Mit 0x40 ist die 7 Bit Adresse + RW-Bit enthalten.

Aber es läuft bei mir sowieso nicht.

von spess53 (Gast)


Angehängte Dateien:

Lesenswert?

Hi

>In Fig 1-2 hat die Slave Adresse 7 Bit, wie es der I2C-Spezifikation
>(S.15) entsprich und genau den Wert 0x20. Was da an Bits rangepfriemelt
>ist, ändert nichts an dem Wert.
>http://i2c2p.twibright.com/spec/i2c.pdf

Solange sich die Hersteller nicht 100%-ig daran halten bleibt das graue 
Theorie. Einige Hersteller geben gleich beider Werte (Anhang) an.

MfG Spess

von Teddy (Gast)


Lesenswert?

Hallo Jungs,
leider bleibt der Durchbruch aus.
Ich krieg es nicht hin.

Die Sendung der Adresse 0x40 scheint zu funktionieren, es taucht keine 
Fehlermeldung auf. Aber wenn ich statt schreiben, lesen will (0x41), 
dann kommt wieder die Fehlermeldung auf.
Die Fehlermeldung wird in Form einer LED gekennzeichnet. (siehe oben in 
der C-Datei)

In der Main steht folgendes:
int main(void)
{
  DDRB=0x01;
  PORTB=0x00;
    I2C_Init();
    I2C_Start();
    I2C_Adresse(0x40);
  I2C_Senden(IODIRA); //IODIRA = 0x00
  I2C_Senden(0x00);  //Alle Ports von A auf Ausgang
  I2C_Senden(OLATA);  //OLATA = 0x14
  I2C_Senden(0xFF);  //Alle Ports von A auf HIGH
  I2C_Stop();

}

Die einzelnen Funktionen sind oben in der Datei beschrieben.
Vielleicht sehe ich den Wald vor lauter Bäumen nicht.

von Wolfgang (Gast)


Lesenswert?

Fana Ticker schrieb:
> Auch wenn hier verschiedene widersprüchliche Weisheiten
> verbreitet werden ist die Adresse für diesen Baustein
> immer noch 0x40 für schreiben und 0x41 für lesen (wenn
> A0, A1 und A2 = 0).

Du willst es nicht begreifen.

Die I2C-Spezifikation kennt nur 7-Bit Adressen. Wenn jemand eigene 
Bezeichnungen einführt, soll er das nicht als I2C-Adresse bezeichnen. 
Irreführende Funktionsnamen für Funktionen, denen das fertig 
zusammengebaute Control-Byte übergeben werden muss ( 
"I2C_Adresse(0x40)", sind da mit eingeschlossen.

von Teddy (Gast)


Lesenswert?

Wolfgang schrieb:
> Fana Ticker schrieb:
>> Auch wenn hier verschiedene widersprüchliche Weisheiten
>> verbreitet werden ist die Adresse für diesen Baustein
>> immer noch 0x40 für schreiben und 0x41 für lesen (wenn
>> A0, A1 und A2 = 0).
>
> Du willst es nicht begreifen.
>
> Die I2C-Spezifikation kennt nur 7-Bit Adressen. Wenn jemand eigene
> Bezeichnungen einführt, soll er das nicht als I2C-Adresse bezeichnen.
> Irreführende Funktionsnamen für Funktionen, denen das fertig
> zusammengebaute Control-Byte übergeben werden muss (
> "I2C_Adresse(0x40)", sind da mit eingeschlossen.

Da du hier anscheinend besser auskennst.
Weiß du warum es bei mir nicht funktioniert!?

von Teddy (Gast)


Lesenswert?

Hi Jungs,
ich komme nicht voran. Ihr müsst mir die Lösung nicht sagen, aber es 
würde mir helfen, wenn ihr mir ein Tipp/eine Richtung geben könntet wo 
ich weitersuchen kann.

Danke. Der Gewinner bekommt am Ende einen Eis, versprochen.

von Gerhard O. (gerhard_)


Lesenswert?

Teddy,

Jetzt will ich's mal versuchen:

An Deiner Stelle würde ich mich bezüglich der Slave Addresse einzig und 
alleine ans Datenblatt halten.

Diese Bezeichnung 7-Bit Slave Adresse ist ganz irreführend weil nämlich 
in der Realität dieses sogenannte 7-Bit SA mit dem RW Bit verbunden wird 
und besteht letztlich IMMER aus einem 8-Bit Datenwort.

Schau Dir mal das Bild vom Spess53 an. Da werden A6 bis A0 angegeben mit 
einem Platzhalter Bit für Write oder Read Operation. Somit ist das der 
Funktion zugeleitete SA Byte immer 8-bit. Dem PCF8574 sendest Du als 
Schreib Byte also 0b01000000 oder 0x40 und 0x41 zum Lesen. Die Addresse 
ist dann nicht A6-A0 "010000" oder "00100000" sondern "0100000x" und das 
ist immer 0x40 oder 0x41.

Wenn man unsicher ist, immer das Datenblatt zu Rate ziehen und die meist 
angegebenen Beispiele studieren. Anhand dieser Diagramme kann man ohne 
Zweifel sehen wie der Hase läuft. Nochmals, das SA Wort wird immer als 
8-Bit Byte gesendet. Die reine angegebene 7-bit Addresse muß dann immer 
um eine Stelle nach links geshiftet werden und das RW Bit dazu gedacht 
werden.

Nur die Arduino Wire Bibliothek macht eine Ausnahme. Bei der darf nur 
die 7-bit Addresse des ICs weiter gegeben werden. Bei allen anderen 
Bibliotheken die mir bekannt sind muß die erweitete 7-bit Addresse als 
8-bit Wort mit angefügtem RW Bit in der üblichen Weise angegeben werden.

Als Pull-Ups verwende ich bei normalen 3.3V/5V Systemen meist 3.9K. 
Niedriger ist da wegen der unvermeidlichen Verdrahtungskapazitäten 
welche die Pulse abrunden eher besser.

Grüße,
Gerhard

von Patrick J. (ho-bit-hun-ter)


Lesenswert?

Hi

spess53 schrieb:
> Schon mal die Atmel AppNotes versucht?

Habe das I2C-Protokoll per Datenblätter und Logik-Analyser erforscht und 
hart in Assembler nachgebaut.
Als Quelle diente ein Arduino, Der I2C von Haus aus kann' - Dem habe ich 
quasi 'unter den Rock geschaut'.
Die AppNotes habe ich nur überflogen, bekomme beim USI-Zeug irgendwie 
Gehirnfrost - da hat sich noch keine Logik ergeben ... die Datenblätter 
der ATtiny gehen Da ja auch etwas drauf ein - wird wohl noch werden.

@Teddy
Wo sitzt die besagte Error-LED?
In Deinem Code sehe ich davon nicht viel, auch scheinst Du nur 
schreibend auf den Slave zuzugreifen.
Mir ist aber auch nicht ersichtlich, wo das ACK in Deinem Code empfangen 
wird - könnte mit meinen eher nicht vorhandenen C-Kenntnissen zusammen 
hängen.

MfG

von S. Landolt (Gast)


Lesenswert?

> Aber wenn ich statt schreiben, lesen will (0x41),
> dann kommt wieder die Fehlermeldung auf.

In I2C_Adresse:
> if((TWSR & 0xF8)!=0x18)
Den Statuscode 0x18 finde ich nur bei Master Transmitter Mode, nicht im 
Receiver Mode.

von Teddy (Gast)


Lesenswert?

@Gerhard. Danke für die AUsführungen.
Langsam dämmerts bei mir im Hirn. Es wird zwar denke ich noch bisschen 
dauern, bis ich das kapiert habe, aber bin denke ich auf dem richtigen 
Weg,.

> In I2C_Adresse:
>> if((TWSR & 0xF8)!=0x18)
> Den Statuscode 0x18 finde ich nur bei Master Transmitter Mode, nicht im
> Receiver Mode.

In der Tat. Da muss ich echt aufpassen und das Senden und Empfangen 
nicht vermischen.
Die Hexazahl für das Empfangen lautet dann 0x40.
GUT! Danke.

> @Teddy
> Wo sitzt die besagte Error-LED?
> In Deinem Code sehe ich davon nicht viel, auch scheinst Du nur
> schreibend auf den Slave zuzugreifen.
> Mir ist aber auch nicht ersichtlich, wo das ACK in Deinem Code empfangen
> wird - könnte mit meinen eher nicht vorhandenen C-Kenntnissen zusammen
> hängen.
>
> MfG

Die LED sitzt eigentlich an einem beliebigen Port. Hier ist es 
PORTB=0x01.
Die LED leuchtet immer, wenn die Transaktionen nicht geklappt haben. 
Diese frage ich in den IF ANweisungen ab.
Beim Senden der Adresse (im Schreibmodus) z.B. steht:
if((TWSR & 0xF8)!=0x18)
{
  PORTB=0x01;
}
Hier wird der Statusregister abgefragt. Der Statusregister TWSR hat die 
Bits bei 0xF8, durch das "verUNDen" werden die gesetzten Bits gefiltert 
und mit der 0x18 verglichen. 0x18 sagt aus, dass die Adresse erfolgreich 
gesendet und das ACK Bit erfolgreich empfangen worden ist (gemäß 
Datenblatt).
Falls nicht, soll die LED leuchten.


Dann mache ich bei der Ansteuerung des MCP23017 falsch. Ich glaube ich 
schicke die Datenbytes falsch rüber.
Denn wenn ich folgendes sende:

    I2C_Init();
    I2C_Start();
    I2C_Adresse(0x40);
  I2C_Senden(IODIRA); //Register für die Richtung des Ports
  I2C_Senden(0x00);   //Alle Ports von A auf Ausgang
  I2C_Senden(OLATA);  //Alle Ports von A auf High
  I2C_Senden(0xFF);
  I2C_Stop();

Kann ich keine Spannungen bei Port A messen.

von S. Landolt (Gast)


Lesenswert?

Vielleicht vereinzeln, also:

  I2C_Init();

  I2C_Start();
  I2C_Adresse(0x40);
  I2C_Senden(IODIRA); //Register für die Richtung des Ports
  I2C_Senden(0x00);   //Alle Ports von A auf Ausgang
  I2C_Stop();

  I2C_Start();
  I2C_Adresse(0x40);
  I2C_Senden(OLATA);  //Alle Ports von A auf High
  I2C_Senden(0xFF);
  I2C_Stop();

von Teddy (Gast)


Lesenswert?

S. Landolt schrieb:
> Vielleicht vereinzeln, also:
>
>   I2C_Init();
>
>   I2C_Start();
>   I2C_Adresse(0x40);
>   I2C_Senden(IODIRA); //Register für die Richtung des Ports
>   I2C_Senden(0x00);   //Alle Ports von A auf Ausgang
>   I2C_Stop();
>
>   I2C_Start();
>   I2C_Adresse(0x40);
>   I2C_Senden(OLATA);  //Alle Ports von A auf High
>   I2C_Senden(0xFF);
>   I2C_Stop();

Nein, leider auch nicht.
Ich muss mal das Datenblatt nochmal anschauen.

Beitrag #5087467 wurde vom Autor gelöscht.
von Christian S. (roehrenvorheizer)


Angehängte Dateien:

Lesenswert?

Hallo

anbei ein Codeschnipsel. Vielleicht wird die Ansteuerung klarer.

MfG

von Teddy (Gast)


Lesenswert?

Christian S. schrieb:
> Hallo
>
> anbei ein Codeschnipsel. Vielleicht wird die Ansteuerung klarer.
>
> MfG

Bin deinen Code durchgegangen.
Ist fast, was "Daten senden" angeht, das gleiche. Habe einiges 
übernommen.
Hat leider nichts gebracht.

Falls du den MCP23017 noch hast, kannst du die Ansteuerung mal mit 
meinem Code und Bibliothek probieren?

von S. Landolt (Gast)


Lesenswert?

Könnten wir das aktuelle Programm sehen?

Ich habe hier nur einen MCP23S17, also die SPI-Version, aber ein 
minimalistisches Programm mit der zweifachen Sequenz
0x40 0x00 0x00
0x40 0x14 0xFF
schaltet hier GPA auf Vdd.

von S. Landolt (Gast)


Lesenswert?

PS: natürlich liegen dabei die drei Adressleitungen auf Vss bzw. GND.

von Teddy (Gast)


Angehängte Dateien:

Lesenswert?

S. Landolt schrieb:
> Könnten wir das aktuelle Programm sehen?
>
> Ich habe hier nur einen MCP23S17, also die SPI-Version, aber ein
> minimalistisches Programm mit der zweifachen Sequenz
> 0x40 0x00 0x00
> 0x40 0x14 0xFF
> schaltet hier GPA auf Vdd.

Bitte sehr. Sind im Anhang.

von S. Landolt (Gast)


Lesenswert?

> Bitte sehr.
Danke schön.

Was passiert, wenn Sie in main statt
I2C_Senden(IOCON);

I2C_Senden(IODIRA);

schreiben?

von Teddy (Gast)


Lesenswert?

Ich habe ehrlich gesagt keine Ahnung warum da IOCON steht, da sollte 
IODIRA stehen.
Mit IODIRA klappts auch nicht.

von S. Landolt (Gast)


Lesenswert?

> Mit IODIRA klappts auch nicht
Schade.

Und das Vereinzeln hatten Sie ja auch schon probiert!? Vielleicht noch 
mal versuchen?

von S. Landolt (Gast)


Lesenswert?

PS: denn ich kann in Fig. 1-1 bei write keine Möglichkeit zum 
Hintereinanderschachteln erkennen.

von Teddy (Gast)


Lesenswert?

S. Landolt schrieb:
>> Mit IODIRA klappts auch nicht
> Schade.
>
> Und das Vereinzeln hatten Sie ja auch schon probiert!? Vielleicht noch
> mal versuchen?

Klaro.
  I2C_Init();

  I2C_Start();
  I2C_Adresse(I2C_Slave_Schreiben);
  I2C_Senden(IODIRA);
  I2C_Senden(0x00);
  I2C_Stop();

  I2C_Start();
  I2C_Adresse(I2C_Slave_Schreiben);
  I2C_Senden(OLATA);
  I2C_Senden(0xFF);
  I2C_Stop();

Geht auch nicht.

von S. Landolt (Gast)


Lesenswert?

Tja, jetzt bin ich am Ende. Sorry.

von Teddy (Gast)


Lesenswert?

S. Landolt schrieb:
> Tja, jetzt bin ich am Ende. Sorry.

Schade.
Es gibt sicher andere Experten hier, aber sie halten sich im 
Hintergrund.
Schade.

von Einer K. (Gast)


Lesenswert?

Auch wenn ich mich im Hintergrund halte, bin ich vermutlich kein 
Experte.
Habe aber schon erfolgreich deine Bausteine getrieben.
Per Arduino IDE und zugehöriger Lib.

Das würde ich, an deiner Stelle, jetzt genau so machen, und das 
Ergebnis, mit LA und Oszi, vergleichen.

Dann erscheint der Fehler.
Ich bin mir da sicher.

von Teddy (Gast)


Lesenswert?

Arduino F. schrieb:
> Auch wenn ich mich im Hintergrund halte, bin ich vermutlich kein
> Experte.
> Habe aber schon erfolgreich deine Bausteine getrieben.
> Per Arduino IDE und zugehöriger Lib.
>
> Das würde ich, an deiner Stelle, jetzt genau so machen, und das
> Ergebnis, mit LA und Oszi, vergleichen.
>
> Dann erscheint der Fehler.
> Ich bin mir da sicher.

Habe leider kein LA oder Oszi.
Ich denke mit einem LA konnte man den Fehler mit Sicherheit finden.
Wieder Geld ausgeben? >.<

von Pat A. (patamat)


Lesenswert?

Ein LA ist ein überaus nützliches Hilfsmittel beim Debugging rund um 
Mikrocontroller, Bussen und Schnittstellen. Einfache, aber dennoch 
brauchbare kosten auch kein Vermögen. Such z.B. auf eBay mal nach "Logic 
Analyzer Compatible Saleae" - Kosten < 6€

Die Software dazu hat in der Regel auch Protocol-Analyser für  die 
zumindest gebräuchlichsten Protokolle wie I2C, SPI, UART etc. Damit 
sieht man nicht nur die Signale, sondern auch was sie bedeuten. Bei I2C 
z.B. die Start- und Stop-Condition, Adressierung, das ACK-Bit usw.

Das erleichtert die Fehlersuche ungemein.

von Wolfgang (Gast)


Lesenswert?

Teddy schrieb:
> Ich denke mit einem LA konnte man den Fehler mit Sicherheit finden.
> Wieder Geld ausgeben? >.<

An den 7€ kann es doch nicht liegen.
http://www.ebay.com/itm/131752135890

von Teddy (Gast)


Lesenswert?

Wolfgang schrieb:
> Teddy schrieb:
>> Ich denke mit einem LA konnte man den Fehler mit Sicherheit finden.
>> Wieder Geld ausgeben? >.<
>
> An den 7€ kann es doch nicht liegen.
> Ebay-Artikel Nr. 131752135890

7€? Wie zuverlässig ist das Ding? Ich gebe gerne bis 50€ aus.
Leider sind die guten anscheinend ab 100€

von Klaus (Gast)


Lesenswert?

Teddy schrieb:
> 7€? Wie zuverlässig ist das Ding? Ich gebe gerne bis 50€ aus.
> Leider sind die guten anscheinend ab 100€

Wieviele Biere bekommst du in deinem Lieblingsbiergarten für 7€? Und wie 
schnell ist der eine Teil davon im Kopf und der andere Teil in der 
Schüssel?

Kauf 7 Stück a 7€, sind knapp 50. Dann kannst du 6 mal einen fatalen 
Fehler beim Benutzen machen und hast noch ein Leben über. Ob die "guten" 
so viel besser sind, daß da nie ein Fehler passiert?

Ein Gerät, bei dem die Eingänge unzerstörbar sind bekommt man aber auch 
für 100€ nicht.

MfG Klaus

von Pat A. (patamat)


Lesenswert?

Teddy schrieb:
> Habe leider kein LA oder Oszi.
> Wieder Geld ausgeben? >.<

Teddy schrieb:
> 7€? Wie zuverlässig ist das Ding? Ich gebe gerne bis 50€ aus.

Such Dir einen aus:
http://sigrok.org/wiki/Supported_hardware#Logic_analyzers

von Teddy (Gast)


Lesenswert?

Ich habe es jetzt geschafft.
Die ANsteuerung der Ausgänge erfolgt über GPIOA/B und nihct über 
OLATA/B.

von Peter D. (peda)


Lesenswert?

Prinz von Pakistan schrieb:
> Nach meinem Dafürhalten spricht er von Soft-I2C, dies aber halte ich als
> Einstieg für einen Anfänger für wenig geeignet.

Eher umgekehrt, SW-I2C ist einfach, robust und portabel. Man muß ja nur 
die 4 Grundfunktionen (Start, Stop, Byte lesen, Byte schreiben) 
implementieren und dann benutzen. Benutzt man nur Slaves mit 
SCL-Eingang, kann man den SCL-Pin als Push/Pull programmieren, d.h. den 
Pullup sparen.

Insbesondere das HW-I2C der AVRs ist recht zickig, wenn längere 
Leitungen dran hängen und Störungen einkoppeln können. Da kann es sich 
schonmal komplett aufhängen.
Ich habe es nur mit einem Watchdog zuverlässig zum Laufen gebracht. D.h. 
ein Timerinterrupt schlägt zu, wenn es sich zwischen Start und Stop 
aufhängt, disabled es, macht bis zu 9 SCL-Takte, bis SDA wieder high ist 
und startet den unterbrochenen Transfer neu.

Nur das HW-I2C der original Philips P80C552, P89C668 hat bei mir 100% 
zuverlässig funktioniert. Den Watchdog mußte ich erst beim Umstieg auf 
Atmel nachträglich einbauen, da ja NXP seine 8051-er eingestampft hat.

von Michael W. (Gast)


Lesenswert?

S. Landolt schrieb:
> Der Pullup-Widerstand bildet zusammen mit den unweigerlich vorhandenen
> Kapazitäten ein RC-Glied, hier einen Tiefpass.

Mal langsam, das würde ja bedeutet, dass die Widerstände zu KLEIN wären!

Dem ist aber nicht so! Die internen pullups sind meistens zu GROSS!

Typisch sind 3k3 oder 4k7 für einen Teilnehmer bis hin zu 1,2k für 15 
Teilnehmer.

Die Eingangskapazität liegt dann bei etwa einem halben Nanofarad und das 
ergibt immer noch eine ausreichend hohe Grenzfrequenz

von Klaus (Gast)


Lesenswert?

Gerhard O. schrieb:
> Diese Bezeichnung 7-Bit Slave Adresse ist ganz irreführend weil nämlich
> in der Realität dieses sogenannte 7-Bit SA mit dem RW Bit verbunden wird
> und besteht letztlich IMMER aus einem 8-Bit Datenwort.

Das gilt aber nur für Leute, die ansonsten noch nie ein etwas 
aufwändigeres Protokoll gesehen haben. Das sich in einem Oktet mehr als 
nur ein Feld befindet, ist da absolut üblich. Schau dir nur mal die 
Oktets in einem HDLC Frame an. Und da kommt auch niemand auf die Idee, 
N(R), N(S) und Poll-Bit in einen Klump zu hauen, nur weil alle in einem 
Oktet liegen. Der Fall von 2 Feldern, Adresse und R/W Bit ist da eher 
was ganz simples.

Um das ganze etwas leichter zu machen, wird im Standard von I2C-Adresse 
und vom Adress-Byte, gesprochen. Da das bei den Arduino-Leute wohl immer 
noch zu Verwechselungen geführt hat (beides fängt mit A an), wird auch 
der Begriff Control-Byte für das erste Byte eines I2C-Frames verwendet.

MfG Klaus

von Michael W. (Gast)


Lesenswert?

Klaus schrieb:
> N(R), N(S)

Was meinst Du mit den Signalen?

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.