Hallo Gemeinde
Wie kannn ich die Adresse eines I2C Teilnehmers ermitteln. Aus dem
Datenblatt. Ist Klar.
Wie kann ich die Adresse ermitteln mit einem Programm? Habe das Programm
von Peter gesehen, Ist ein Sniffer. Kann ich damit die Adresse
ermitteln?
Es gibt einige Sachen auf dem Arduino. Möchte es aber in normalen C
machen und auf einem Display mit I2C ausgeben.
Hat da jemand ein Programm dazu oder eine Idee?
achim
Achim Seeger schrieb:> Wie kannn ich die Adresse eines I2C Teilnehmers ermitteln.
Du brauchts irgendeine Feedbackleitung von dem jeweiligen I2C-IC.
Anderes ist es nicht zu machen, weil es im I2C-Protokoll nicht
vorgesehen wurde.
I2C Komponenten wurden z.B. in PHILIPS-TVs eingebaut, wo der Entwickler
deren Adresse vor Hardware-Legung schon kannte.
Habe es in einigen Beiträgen gesehen.
Es werden alle möglichen Adressen gesendet. Welche Adresse antwortet ist
vorhanden.
Manche machen es sehr einfach.
Möchte die Adresse nicht über extra Programm auslesen und am PC
anzeigen, sondern über ein Display im Bus.
Hat jemand eine Idee dazu?
Achim Seeger schrieb:> Hat da jemand ein Programm dazu oder eine Idee?> achim
Jede Device auf I2C Bus muss eigene Adresse bestätigen, mit ACK.
Also, Adresse ausgeben, auf ACK warten, wenn ja, irgendwo merken
und STOP senden.
Adresse um eins erhöhen und...
Unter Linux gibt es das Tool i2cdetect, welches genau das macht was du
willst. Es benutzt zwei verschiedene Methoden (schreiben & lesen), die
je nach zu scannender Adresse benutzt werden (weil die jeweils eine oder
andere Methode bei manchen Chips Probleme bereiten kann).
Hier der Code zum Scannen (in C):
https://github.com/groeck/i2c-tools/blob/master/tools/i2cdetect.c#L58
Von den zwei geschachtelten for-schleifen nicht verwirren lassen, das
kommt daher dass die Ausgabe in 16 Spalten erfolgt:
http://playground.arduino.cc/Main/I2cScanner
läuft prima
ich nutze das auf dem nano und geben das auf nokia 5110 LCD
dummerweise betrachtet jeder die Adressgenerierung anders
ich schaue ins Datanblatt und nehme alle Bits ! für ein Adressbyte !
in o.g. Link wurde das nicht getan was zu einer Verwirrung bei mir
führte die ich dann später auflösen konnte.
ist zwar am Arduino aber nun gut....
meine Tastatur liegt bei mir auf 0x70, das letzte Bit ist aber R/W
vorbehalten was für die PI (der anderen) Schreiber eben nicht zählt oder
anders gesagt, es sind nur 127 Adressen nach alter Definition möglich,
ergo wurden nur die vordersten 7 Bit beguckt was zu 0x38 führt
mit einem links shift habe ich meine kleine Welt wieder gerade gerückt,
wie man das auch betrachtet ist ja egal, nur muss man sich vorher über
die Betrachtungsweise einigen.
Sieht sehr gut aus.
Hallo Simon
Dein Programm läuft unter Linux. Kann man das einfach umschreiben auf
einen AT? Ansonsten werde ich mir gründlich ansehen.
Hallo Joachim
Du hast sogar die Umrechnung in hex dabei. Das lohnt sich langsam was zu
machen.
achim
Joachim B. schrieb:> dummerweise betrachtet jeder die Adressgenerierung anders
Probleme gibt es immer dann, wenn das Adressierungsbyte
fälschlicherweise als Adresse bezeichnet wird.
Wolfgang A. schrieb:> Probleme gibt es immer dann, wenn das Adressierungsbyte> fälschlicherweise als Adresse bezeichnet wird.
Warum "fälschlicherweise"?
Es ist aber durchaus weit verbreitete Praxis, genau das zu tun.
Ist eben einfach praktischer das Read-Flag in die Adresse reinzuodern,
als diese immer noch um ein Bit linksschieben zu müssen.
Viele Hersteller von ICs mit I2C-Schnittstelle geben die Slave-Adressen
genau so an. Analog Devices z.B. in seinen Datenblättern zu HDMI
Schnittstellen ICs und Video Encodern und Decodern.
Auch auf Softwareseite wird es anscheinend von den meisten
Programmierern so gehandhabt, dass man einer
I2C_Read/Write/irgendwwas-Routine die Slave-Adresse als gerade
8-Bit-Zahl übergibt.
Thorsten S. schrieb:> Warum "fälschlicherweise"?> Es ist aber durchaus weit verbreitete Praxis, genau das zu tun.
Es ist durchaus weit verbreitete Praxis, in Tempo 30 Zonen schneller zu
fahren. Trotzdem ist es falsch.
Der Aufbau von Telegrammen bei einem Dateübertragungsprotokoll steht der
Spezifikation. Da ist bei I2C ein 7 Bit Adressfeld definiert, und auch
wo es im Telegram steht: in den zuerst übertragenen 7 Bit. Und dort
steht auch, wo weitere Bits des Adressfeldes bei 10 Bit Adressen zu
finden sind.
> Auch auf Softwareseite wird es anscheinend von den meisten> Programmierern so gehandhabt, dass man einer> I2C_Read/Write/irgendwwas-Routine die Slave-Adresse als gerade> 8-Bit-Zahl übergibt.
Wie man an I2Cdetect (weiter oben) sieht, ist dem nicht so. Da werden
sogar die in den I2C-Spec reservierten Adressen beim Scan ausgelassen,
es kommt also keine Adresse größer als 0x78 vor.
MfG Klaus
Achim Seeger schrieb:> Hallo Simon> Dein Programm läuft unter Linux.
Ich habs nicht geschrieben, das ist Teil von GNU/Linux
> Kann man das einfach umschreiben auf> einen AT? Ansonsten werde ich mir gründlich ansehen.
Relevant sind ja sowiso nur die Zeilen 58 bis 121. Ein bisschen was
musst du natürlich ändern:
* Wenn du die Darstellung nicht willst kannst du natürlich die
for-Schleifen zusammenfassen und alle printf+fflush rauswerfen
* Bei "/* Select detection command for this address */" musst du vorher
halt den mode festlegen (vlt. möchtest du das ja auch für den User
einstellbar machen, wobei ich bisher mit MODE_AUTO nie Probleme hatte)
* "/* Skip unwanted addresses */" kannst du eigentlich rauswerfen, da
wird (soweit ich verstehe) überprüft ob der Bus den entsprechenden
Lese/Schreib-Befehl unterstützt
* "/* Set slave address */" musst du natürlich mit den entsprechenden
Tools auf dem AVR machen. Der Teil mit "if (errno == EBUSY)" kann auch
weg, weil das die Fehlerbehandlung ist wenn ein Treiber das Gerät schon
benutzt.
* "/* Probe this address */" Die Write und Read Befehle natürlich durch
die entsprechenden beim AVR ersetzten
* "if (res < 0)" Kein Plan wie du deine Ergebnisse verarbeiten willst,
hier musst du das dann programmieren
Klaus schrieb:> Wie man an I2Cdetect (weiter oben) sieht, ist dem nicht so. Da werden> sogar die in den I2C-Spec reservierten Adressen beim Scan ausgelassen,> es kommt also keine Adresse größer als 0x78 vor.
Wie es I2Cdetect macht, ist vollkommen wurscht.
Alle 24xxx haben 0xA0 Adressen, wie du die finden willst wenn keine
Adresse größer als 0x78 vorkommt, ist mir schleierhaft.
I2C Adressen sind normalerweise 7-bit und zwar die oberen 7-bit.
R/W wird bei der Adresse einfach nicht benutzt. Deswegen hat
Thorsten auch Recht, wenn er schreibt, dass I2C-Adressen gerade sind.
Marc Vesely schrieb:> I2C Adressen sind normalerweise 7-bit und zwar die oberen 7-bit.
Also was jetzt?
Du hast recht: i2c-Adressen haben 7 bit. Damit geht der theoretische
Adressraum von 0 bis 127, und 0xA0 ist keine gültige Adresse.
"die oberen 7 bit" gibt es nicht.
Auch wenn sich einige hier auf den Kopf stellen, die Adresse besteht aus
sieben Bit und das R/W-Bit gehört nicht dazu. So hat es Philips (jetzt
NXP) spezifiziert und festgeschrieben. Sonst entspricht es de facto
nicht der I2C Spezifikation.
http://www.nxp.com/documents/application_note/AN10216.pdf
Es darf natürlich jeder aus diesen oder jenen Gründen andere
Konventionen verwenden, aber dann soll er sich nicht wundern, wenn es
Kommunikationsprobleme gibt.
Bei einem gewöhnlichen EF-Haus hat die Haustür auch nicht zwei
Hausnummer - eine zum Rein- und eine zum Rausgehen ;-)
Wolfgang A. schrieb:> Bei einem gewöhnlichen EF-Haus hat die Haustür auch nicht zwei> Hausnummer - eine zum Rein- und eine zum Rausgehen ;-)
Genialer Vergleich - Danke!
Marc Vesely schrieb:> Alle 24xxx haben 0xA0 Adressen, wie du die finden willst wenn keine> Adresse größer als 0x78 vorkommt, ist mir schleierhaft.
Dann guck mal ins Datenblatt, was da als "Slave Address" bezeichnet ist
z.B. 24xx1026 (Figure 5-1: Ccontrol Byte Format)
http://ww1.microchip.com/downloads/en/DeviceDoc/20002270D.pdf
Und damit auch jeder den Unterschied merkt und es zu keinen
Verwechselungen kommen kann, hat Maxim das betreffende Byte lieber
"Control Byte" genannt ;-)
Michael Reinelt schrieb:> Du hast recht: i2c-Adressen haben 7 bit. Damit geht der theoretische> Adressraum von 0 bis 127, und 0xA0 ist keine gültige Adresse.>> "die oberen 7 bit" gibt es nicht.
No comment.
Wolfgang A. schrieb:> Dann guck mal ins Datenblatt, was da als "Slave Address" bezeichnet ist> z.B. 24xx1026 (Figure 5-1: Ccontrol Byte Format)> http://ww1.microchip.com/downloads/en/DeviceDoc/20002270D.pdf
Habe ich. Da steht genau das, was ich auch geschrieben habe.
Michael Reinelt schrieb:> Also was jetzt?>> Du hast recht: i2c-Adressen haben 7 bit. Damit geht der theoretische> Adressraum von 0 bis 127, und 0xA0 ist keine gültige Adresse.>> "die oberen 7 bit" gibt es nicht.
Natürlich haben die Adressen nur 7bit. (zu den erweiterten auf 10 sag
ich jetzt absichtlich nichts)
Aber da die meisten uC nunmal in vollen 8bit denken, sehen diese 7bit
irgendwo abgelegt halt so aus.
1
X A7 A6 A5 A4 A3 A2 A1 A0
Wenn man die Adresse dann auf den Bus für Operationen schicken will wird
einmal nach links geshiftet und das letzte Bit entsprechend für Read
oder Write gesetzt.
Dann kommt die Stelle an, der der Praktiker sich einschaltet. Wenn man
die Adresse in der Form:
1
A7 A6 A5 A4 A3 A2 A1 A0 0
im Programm hinterlegt, dann spart man sich die Shift-Opperation. Das
R/W Bit wird dann mit einer einfachen Oder-Verknüpfung hinzugefügt, und
der Wert wird direkt auf den Bus geschickt. Kein Programmierer der Welt
würde jetzt aber diesen Wert als "Adresse+0bit" abspeichern, sondern er
heißt zur allgemeinen Verwirrung eben auch "Adresse".
Die 7 Adressbits oder höherwertigen Bits hier als "obere Bits" zu
bezeichnen würde ich jetzt nicht als falsch erachten...
Die Adresse besteht also grundsätzlich nur aus 7 bit. Wo der
Programmierer die letztendlich hinschreibt ist dann anscheinend nicht
definiert und das macht jeder wie er gerade lustig ist. Und darum kann
man da jetzt auch noch ewig weiterdikutieren ohne einen gemeinsamen
Nenner zu finden.
Mann muss leider jedes mal wieder aufpassen wie es implementiert wurde.
Können wir dieses Thema dann abhaken, bevor es ausartet?
Bernhard F. schrieb:> Können wir dieses Thema dann abhaken, bevor es ausartet?
Gerne. Wenn sich dann bitte alle nochmal den Beitrag von Wolfgang
Beitrag "Re: I2C Adresse ermitteln" durchlesen und zu
Herzen nehmen, dann können wir die Diskussion wirklich beenden.
Bernhard F. schrieb:> Aber da die meisten uC nunmal in vollen 8bit denken, sehen diese 7bit> irgendwo abgelegt halt so aus.> X A7 A6 A5 A4 A3 A2 A1 A0
Sind im Prinzip gleicher Meinung, aber:
A7 A6 A5 A4 A3 A2 A1 A0 X
Und so steht es auch in den meisten DaBla, was ja auch logisch ist.
Bit 0 gehört nicht zur Adresse, weil das eben Kontrollbit ist, hat
mit der Adresse genau Nullkommanichts zu tun, wird ganz einfach ein-
oder ausgeblendet.
Marc Vesely schrieb:> Und so steht es auch in den meisten DaBla, was ja auch logisch ist.> Bit 0 gehört nicht zur Adresse, weil das eben Kontrollbit ist, hat> mit der Adresse genau Nullkommanichts zu tun, wird ganz einfach ein-> oder ausgeblendet.
ich weiss nicht was daran so schwierig ist. Ob das in den meisten
Datenblättern steht ist irrelevant. Die I2C-Spezifikation besagt dass
die Adresse 7 Bit hat, und damit von 0 bis 127 geht. Was gibts da
herumzudiskutieren? Ob das vorausschauende Shiften jetzt bequem oder
lässig oder faul oder dumm oder sonstwas ist: irrelevant. Es ist nur mit
Sicherheit eines: nicht Standardkonform.
Michael Reinelt schrieb:> Datenblättern steht ist irrelevant. Die I2C-Spezifikation besagt dass> die Adresse 7 Bit hat, und damit von 0 bis 127 geht.
Nein, das ist eben dein Denkfehler.
Es besagt nur, dass es 128 verschiedene Adressen geben kann.
Wenn ich die höherwertigen 4 Bits nehme, dann habe ich 16 verschiedene
Adressen,aber keine Adresse kann kleiner als 16 sein (außer 0).
Klarer ?
Marc Vesely schrieb:> Es besagt nur, dass es 128 verschiedene Adressen geben kann.
Soweit richtig.
Du bist hartnäckig :-)
Probieren wir es mal anders: du stimmst mir zu, dass die mehrdeutige
Betrachtungsweise einer i2c-Adresse verwirrend und lästig ist? Wenn man
irgendwo liest "Adresse 42" damit nicht klar ist ob jetzt 0x2a oder 0x54
gemeint ist?
Du stimmst mir zu, dass es verwirrend ist, wenn ein i2c-teilnehmer nach
"deiner" betrachtungsweise zwei Adressen hat? nämlich 0x54 zum lesen und
0x55 zum Schreiben? Während er in "meiner" Betrachtungsweise immer die
gleiche Adresse hat, nämlich 0x2a, geshiftet und geodert mit dem
R/W-Bit?
Den Einwand, man könnte sich das Shiften sparen, indem man gleich mit
der 8-Bit-Adresse arbeitet, lasse ich nicht gelten: die drei Taktzyklen
sind bei den gemächlichen 100/400 kHz nicht der Rede wert (und wird im
Optimalfall sowieso vom Compiler wegoptimiert). Und wie immer gilt das
biblische Motto "premature optimization is the root of all evil!".
Jede mir bekannte relevante I2C-Implementierung arbeitet mit "meiner"
Adressierung. Die andere kommt nur dann vor, wenn der Programmierer
glaubte, intelligent sein zu müssen ("premature optimization is the root
of all evil!"). Alle mir bekannten Datenblätter sprechen in der anderen
Betrachtungsweise nicht mehr von der I2C-Adresse, sondern von einem
"Control byte" oder einem "Address byte", aber nicht von der
i2c-Adresse.
Zitat aus einer i2c-Spec: "Some vendors incorrectly provide two 8-bit
slave addresses for their device, one to write to the device and one to
read from the device. This 8-bit number actually encodes the 7-bit slave
address and the read/write bit. "
Du stimmst mir zu dass ein 7-bit-Wert tatsächlich Werte von 0 bis 127
annehmen kann, und nicht "gerade Zahlen zwischen 0 und 254"?
Wenn du ein x-beliebiges Format hast, welches 32 bit umfasst, und die
Definition sagt, "Bit 17 bis 21 sind Wert X", rechnest du dann mit 5 Bit
= 0..31 für Wert X, oder rechnest du alle niederwertigen Bits mit ein?
Dabei ist es so einfach: eine 7-bit-adresse ist eine 7-bit-adresse ist
eine 7-bit-adresse ist eine 7-bit-adresse und hat damit 7 bit und 7 bit
sind 7 bit und mit 7 bit lassen sich Adressen von 0..127 abdecken.
Eine Adresse 0xA? ist keine 7-bit-adresse ist keine 7-bit-adresse weil
sie sich mit 7 bit nicht adressieren lässt.
Michael Reinelt schrieb:> Du bist hartnäckig :-)
Ja. Du bist aber auch nicht gerade das, was man nachgiebig nennt. :-)
> Du stimmst mir zu dass ein 7-bit-Wert tatsächlich Werte von 0 bis 127> annehmen kann, und nicht "gerade Zahlen zwischen 0 und 254"?
Nein, nicht in diesem Fall. Es bedeutet nur 2^7 verschiedene Werte.
Die Anzahl der bits gibt nur an, wieviele verschiedene Zustände,
also auch Adressen, damit ausgedrückt werden können.
Die Position der bits gibt deren Wertigkeit.
Also wenn bits (7-6-5-4) 16 verschidene Zustände annehmen können und
bits (3-2-1-0) auch, stellt das noch lange nicht denselben Wert.
> Wenn du ein x-beliebiges Format hast, welches 32 bit umfasst, und die> Definition sagt, "Bit 17 bis 21 sind Wert X", rechnest du dann mit 5 Bit> = 0..31 für Wert X, oder rechnest du alle niederwertigen Bits mit ein?
Erstens ist das noch lange nicht dasselbe weil Wert und Adresse eben
nicht dasselbe sind. Bei einer Adresse blendet man einfach die nicht
benötigten bits aus, genauso wie bei der I2C Adresse. Und genau
deswegen sagt man dann aber nicht, dass die Adresse 0x11 gemeint ist,
sondern Adresse 0x11xxxx.
> Jede mir bekannte relevante I2C-Implementierung arbeitet mit "meiner"> Adressierung. Die andere kommt nur dann vor, wenn der Programmierer> glaubte, intelligent sein zu müssen ("premature optimization is the root> Du stimmst mir zu, dass es verwirrend ist, wenn ein i2c-teilnehmer nach> "deiner" betrachtungsweise zwei Adressen hat? nämlich 0x54 zum lesen und> 0x55 zum Schreiben? Während er in "meiner" Betrachtungsweise immer die> gleiche Adresse hat, nämlich 0x2a, geshiftet und geodert mit dem> R/W-Bit?
Mal abgesehen davon, dass das R/W bit genau umgekehrt gesetzt wird, ist
deine Aussage ganz Falsch.
I2C_Adr = 0xA0
Beim lesen ist I2C_Adr | rw_bit
Beim schreiben nicht mal das.
Und warum du die Adresse nach rechts schiebst, ist mir ganz unklar.
Marc Vesely schrieb:> Michael Reinelt schrieb:>> Du bist hartnäckig :-)> Ja. Du bist aber auch nicht gerade das, was man nachgiebig nennt. :-)
Dann haben sich ja zwei gefunden :-)
>> Du stimmst mir zu dass ein 7-bit-Wert tatsächlich Werte von 0 bis 127>> annehmen kann, und nicht "gerade Zahlen zwischen 0 und 254"?> Nein
Schade. Aber einen Versuch war's wert ;-)
ich teile deine Einschätzung trotzdem nicht.
>> Wenn du ein x-beliebiges Format hast, welches 32 bit umfasst, und die>> Definition sagt, "Bit 17 bis 21 sind Wert X", rechnest du dann mit 5 Bit>> = 0..31 für Wert X, oder rechnest du alle niederwertigen Bits mit ein?> Erstens ist das noch lange nicht dasselbe weil Wert und Adresse eben> nicht dasselbe sind.
Warum? Anders gefragt: "Bit 17..21 sind irgendeine Sub-Adresse". Ist
dann deine Sub-Adresse 0..31 oder was? Nochmal anders: "Bit 17..21 sind
die Registernummer". Ist dann deine Registernummer 0..31 oder nicht? Wo
liegt der Unterschied zwischen registernummer und Adresse?
>> Du stimmst mir zu, dass es verwirrend ist, wenn ein i2c-teilnehmer nach>> "deiner" betrachtungsweise zwei Adressen hat? nämlich 0x54 zum lesen und>> 0x55 zum Schreiben? Während er in "meiner" Betrachtungsweise immer die>> gleiche Adresse hat, nämlich 0x2a, geshiftet und geodert mit dem>> R/W-Bit?> Mal abgesehen davon, dass das R/W bit genau umgekehrt gesetzt wird
Ok, der Punkt geht an dich. Meine Entschuldigung:
http://www.staff.uni-mainz.de/pommeren/Buchstabendreher/lechts.html> ist deine Aussage ganz Falsch.> I2C_Adr = 0xA0> Beim lesen ist I2C_Adr | rw_bit> Beim schreiben nicht mal das.> Und warum du die Adresse nach rechts schiebst, ist mir ganz unklar.
ich schiebe nicht nach rechts, sondern (gemäß Spezifikation) nach links,
und setze dann Bit 0 gemäß R/W.
Mir gefaellt die "Control Byte" Definition von Microchip noch am Besten.
Das Control Byte enthält eben ein 7-bit Addressenfeld und das R/W
Controlbit.
Mfg,
Gerhard
Gerhard O. schrieb:> Mir gefaellt die "Control Byte" Definition von Microchip noch am Besten.> Das Control Byte enthält eben ein 7-bit Addressenfeld und das R/W> Controlbit.
Die Definition gefällt mir zwar nicht, aber damit kann ich mich
anfreunden: Die nennen es "Control byte" und nicht (fälschlicherweise)
"i2c-address"
Michael Reinelt schrieb:> Gerhard O. schrieb:>> Mir gefaellt die "Control Byte" Definition von Microchip noch am Besten.>> Das Control Byte enthält eben ein 7-bit Addressenfeld und das R/W>> Controlbit.>> Die Definition gefällt mir zwar nicht, aber damit kann ich mich> anfreunden: Die nennen es "Control byte" und nicht (fälschlicherweise)> "i2c-address"
Es werden sich damit von einigen Herstellern sowieso große Freiheiten
genommen wenn man sich errinnert wie oft gerade bei EEPROMS das Control
Byte oft die verschiedensten Zusatzfunktion hat und nur die oberen vier
Bits wirklich den Namen Addresse oder Funktionsidentifier verdienen. Bei
gewissen EEPROMS sind Teile davon eine Erweiterung des
Datenaddress-Bitfeld.
Moral von der Geschicht: Das Datenblatt sich zu Gemüt führen und sich
danach ohne Denken richten;-)
Gerhard
Marc Vesely schrieb:> Der Klügere gibt nach ;-D
Das ist jetzt aber unfair! ;-)
Gerhard O. schrieb:> Moral von der Geschicht: Das Datenblatt sich zu Gemüt führen
Das bleibt einem sowieso nie erspart. Zur Verwirrung mit der i2c-Adresse
kommen dann noch so Besonderheiten wie von dir beschrieben, oder die
DOG-Displays, die sich gleich zwei i2c-Adressen genehmigen, SMBus (wo
das repeated-start ganz anders funktioniert) oder EEBus (ganz
eigenartig)
Michael Reinelt schrieb:> Marc Vesely schrieb:>> Der Klügere gibt nach ;-D>> Das ist jetzt aber unfair! ;-)>> Gerhard O. schrieb:>> Moral von der Geschicht: Das Datenblatt sich zu Gemüt führen>> Das bleibt einem sowieso nie erspart. Zur Verwirrung mit der i2c-Adresse> kommen dann noch so Besonderheiten wie von dir beschrieben, oder die> DOG-Displays, die sich gleich zwei i2c-Adressen genehmigen, SMBus (wo> das repeated-start ganz anders funktioniert) oder EEBus (ganz> eigenartig)
Eben! Im Wandel der Zeit und Proliferation der I2C Bausteine mussten
halt "Krücken" gefunden weden die eben damals noch ungedachte (Im
Standard) neue Funktionen erst ermöglichten.
Ist ja auch gar nicht so schlimm weil die meisten Datenblätter I2C
Transaktionen sowieso äusserst ausführlich beschreiben und im
allgemeinen leicht zu verstehen sind. (Mir geht es zumindest so)
Hallo
Habe eure Diskussion verfolgt.
Finde richtig nett, das ihr euch einig geworden seit. Leider habe ich
ein paar Lösungen dadurch gefunden, aber so richtig ist noch nichts
dabei.
Hat jemand Erfahrung mit Peter Dannegger Programm I2C Sniffer?
achim
Achim Seeger schrieb:> Finde richtig nett, das ihr euch einig geworden seit. Leider habe ich> ein paar Lösungen dadurch gefunden, aber so richtig ist noch nichts> dabei.
Nachdem ich eindeutig gewonnen habe, kann ich mich auch wieder melden.
Warum probierst du es nicht mit einem selbstgeschriebenem Programm,
dabei lernst du doch viel mehr als mit fremden Programmen ?
Hallo Marc
habe schon einiges gemacht. Leider ist es reines Caos.
Die Anbindung und Aufruf zum Bus geht bereits. Auch die Anzeige auf dem
Display. Leider komme ich mit der eigentlichen Adresswahl und speichern
der Ergebnisse nicht weiter.
Keine Angst, habe schon genug Programme hier reingestellt. Kannst ja mal
unter Multitasking nachsehen oder dem Nibo2.
Werde auch einiges dazu reinstellen
1
#include"i2clcd.h"
2
#include"i2cmaster.h"
3
#include"avr/io.h"
4
#include"util/delay.h" // Versuch am LM 75 mit 0x91
5
#include"avr/interrupt.h"
6
7
#define lm75_r 0x91 // Leseadresse des LM75
8
uint8_tmsb_temp;// Oberes Temperatur-Byte
9
uint8_tlsb_temp;// Unteres Temperatur-Byte
10
uint16_ttemp_wrd;// Ganzes Temperatur-Wort
11
uint8_tret;// Kontrollvariable für I2C Kommunik.
12
uint8_tx;// X-Position der Kommastelle
13
signedchartemperatur;// Variable m. Vorzeichen für die Temp.berechnung
14
charBuffer[20];// Umwandlungs-Variable für LCD Anzeige
15
16
voidtemperfassung(void)// Versuch einen Wert zu geben
17
{
18
ret=i2c_start(lm75_r);// Start Lesen des LM75
19
if(ret==0)// obere1unteres Bit le schr.
20
{// Wenn LM75 ein OK sendet...
21
msb_temp=i2c_readAck();//...speichere oberes Bit
22
lsb_temp=i2c_readNak();//...speichere unteres Bit
23
}
24
else// Fehlererkennung
25
{// Wenn LM75 kein OK sendet
26
lcd_command(LCD_CLEAR);// Leere Display
27
lcd_printlc(1,13,"READ");// "Lesevorgang"
28
lcd_printlc(2,13,"NOK");// "Nicht OK (NOK)"
29
}
30
}
Soweit ein Teil meines Versuches. geht dabei um die Ausgabe eines Wertes
und wird auf ausgabe der Adresse erweiter (wenn es klappt).
Ist bei weitem nicht vorzeigbar oder etwa fertig. Die komplette Sache
der Adressen fehlt noch. (nicht alles in der Luft zerreissen)
achim
Achim Seeger schrieb:> Soweit ein Teil meines Versuches. geht dabei um die Ausgabe eines Wertes> und wird auf ausgabe der Adresse erweiter (wenn es klappt).
Ich dachte, du wolltest nur sehen, wer auf dem Bus antwortet und wer
nicht ?
> Ist bei weitem nicht vorzeigbar oder etwa fertig. Die komplette Sache> der Adressen fehlt noch. (nicht alles in der Luft zerreissen)
Keine Angst, ich programmiere meistens in Assembler, aber warte mal
ein paar Minuten...
>> for (uint8_t Srch_Adr=0; Srch_Adr < 255; Srch_Adr +=2)>>>>Wie konntest du nur... Das wird ein langer Thread werden ;)
Das zeigt doch nur das die 8Bit Darstellung der I2C Adresse
plus dem R/W Bit eingängiger ist. Den Schwachsinn mit der
7Bit Adresse und dann doch in einem Byte senden, nur halt
um 1 geschoben erfasst man halt nicht so schnell.
Genau genommen gibt es doch 256 I2C Adressen.
128 zum lesen und 128 zum schreiben;)
Bernhard F. schrieb:> Wie konntest du nur... Das wird ein langer Thread werden ;)
Hmmm. Lange hin und her überlegt, abgewogen, für und wider abge-
schätzt, Argumente und Gegenargumente, die Entscheidung war für mich
überhaupt nicht leicht...
Aber vielleicht ist Michael Reinelt schlafen gegangen oder er hätte
das einfach übersehen ohne deine Bemerkung ?
Jetzt ist es natürlich zu spät für irgendwelche Korrekturen.
Für Morgen:
Ja, Michael, ich weiss es, aber ich bin eben hartnäckig :-)
holger schrieb:> Das zeigt doch nur das die 8Bit Darstellung der I2C Adresse> plus dem R/W Bit eingängiger ist.
Das wären dann 9 bit wenn ich richtig addiert habe ?
> Den Schwachsinn mit der> 7Bit Adresse und dann doch in einem Byte senden, nur halt> um 1 geschoben erfasst man halt nicht so schnell.
Sag das den I2C Herstellern, die machen es nämlich alle so.
Und wenn ich die Adresse so verwende, wie es die I2C Hersteller
auch tun, brauche ich genau nichts zu schieben.
Marc Vesely schrieb:> for (uint8_t Srch_Adr=0; Srch_Adr < 255; Srch_Adr +=2)
Die Schleife wird aber halbwegs lange laufen... mit 7 Bit wär dir das
nicht passiert :-)
Außerdem sollten in deiner Schleife auch noch reservierte Adressen
übersprungen werden, das wären zumindest die 0 (General Call), 1 (CBUS),
2 (anderes Busformat) und alles ab 120 (10-Bit-Adressierung).
Michael Reinelt schrieb:> Außerdem sollten in deiner Schleife auch noch reservierte Adressen> übersprungen werden, das wären zumindest die 0 (General Call), 1 (CBUS),> 2 (anderes Busformat) und alles ab 120 (10-Bit-Adressierung).
Wieso meine Schleife ? Ist für Achim.
Adresse 0 wird nicht bestätigt, die anderen kann er ja ruhig senden,
da nach dem ersten Byte sowieso STOP gesendet wird.
Ehrlich gesagt, mich interessiert es auch ob das funktionieren wird.
Gesniffert habe ich schon auf dem I2C bus, aber so etwas hatte ich noch
nie versucht.
Marc Vesely schrieb:> Wieso meine Schleife ? Ist für Achim.
Aber du hast sie doch vorgeschlagen.
Hinweis: Die terminiert nie, ist eine Endlosschleife, die Bedingung
"Srch_Adr < 255" ist immer wahr: zuletzt bei 254, nach "Srch_Adr +=2"
ists wieder 0, und nochmal von vorne...
> Adresse 0 wird nicht bestätigt,
Doch, von allen Slaves die auf General Call lauschen.
> die anderen kann er ja ruhig senden,> da nach dem ersten Byte sowieso STOP gesendet wird.
Man sollte es vermeiden, bevor andere Devices sich verschlucken. Hat
schon seinen grund, warum i2cdetect die (gemäß i2c-Spezifikation)
auslässt.
> Ehrlich gesagt, mich interessiert es auch ob das funktionieren wird.> Gesniffert habe ich schon auf dem I2C bus, aber so etwas hatte ich noch> nie versucht.
Funktionieren wird es ziemlich sicher.
Marc Vesely schrieb:> Wieso meine Schleife ? Ist für Achim.
ich war zwar nicht gemeint, finde deinen Ansatz aber trotzdem
interessant:
1
while(!(TWCR&(1<<TWINT)));
2
if((TWSR&0xF8)!=START){
3
Fehler_Rut();// Bus wird nicht freigegeben
mein Problem, ich frage im Interrupt eine Tastatur ab, genauer Tasten
die am PCF8574 hängen, das klappte prima.
Als im main loop einer RTC am I2C hinzu kam konnte ich Abstürze durch
Tastenbetätigungen provozieren, musste schon sehr viele Tasten betätigen
in kurzer Zeit.
Dann lernte ich das I2C Interruptgesteuert läuft und mir kam der
Verdacht wenn mitten in der main loop der I2C angesprochen wird ohne
beendet zu sein und die I2C Abfrage in IRQ dazwischen funkt muss das
kollidieren.
Momentan verriegel ich die beiden Zugriffe gegeneinander.
nun kommts:
Leichter wäre es wenn ich im Interrupt fragen könnte ob der Bus frei
ist, es macht ja nix wenn der IRQ alle 10ms aufruft wenn mir einmal für
10ms eine Abfrage auf Tasten entgeht sollte der Timer IRQ mitten in eine
main loop I2C Abfrage reinspringen.
meine eigenen Versuche mit den
while (!(TWCR & (1<<TWINT))); // Ende vom Verkehr abwarten ?
scheiterten wenn der Timer IRQ zuschlug, der I2C Zugriff der main loop
wurde durch Unterbrechung nicht beendet.
oder habe ich das irgendwie noch nicht komplett verstanden ?
Joachim, irgendwie werd ich aus deiner problembeschreibung nicht
schlau...
Grundsätzlich gibt es zwei Möglichkeiten, einen I2C-master am AVR zu
realisieren: Mit oder ohne (TWI-)interrupts. Mischen sollte man die
beiden nicht...
oder ist dein problem, dass du I2C-Zugriffe sowohl in der Main also in
einem (Timer?) Interrupt machst? Das kann natürlich nicht gutgehen...
Vielleicht solltest du mal dienen Code zeigen...
Michael Reinelt schrieb:> oder ist dein problem, dass du I2C-Zugriffe sowohl in der Main also in> einem (Timer?) Interrupt machst? Das kann natürlich nicht gutgehen...
jau genau, mit Verriegelung kein Problem, der Ansatz den belegten Bus
abzufragen hatte ich ja auch und das sollte auch funktionieren.
wenn der BUS in main loop belegt ist Tastaturabfrage in der IRQ
überspringen ....
mein Fehler war wohl das ich in der ISR auf Ende vom Transfer der main
loop warten wollte ...
peinlich
Joachim B. schrieb:> wenn der BUS in main loop belegt ist Tastaturabfrage in der IRQ> überspringen ....
ich würde das an deiner Stelle ganz anders machen: Da I2C mit 100kHz
vergleichsweise "schnarchlangsam" ist (ein Byte dauert fast 0.1ms)
gehört das nicht in eine ISR. ich würde im Timer-Interrupt nur ein Flag
setzen "10 Millisekunden sind vorbei" und alle i2c-Zugriffe in der Main
abwickeln.
Michael Reinelt schrieb:> ....ich würde im Timer-Interrupt nur ein Flag> setzen "10 Millisekunden sind vorbei" und alle i2c-Zugriffe in der Main> abwickeln.
ne genau das wollte ich ja vermeiden
wenn in der main loop eine längere Berechnung läuft entgehen mit
Tastaturdrücke !
Oder ich muss in jeder Stelle gucken ob ich das Tastaturabfrage Flag
gesetzt ist -> nervig !
ne das mit Flag ist OK wenn in der Timer IRQ mein LCD Update gesetzt
wird alle 330ms dann wird auch gleich i2c busy gesetzt und die
Tastenabfrage übersprungen, in der main loop wird i2c busy wieder
rückgesetzt wenn die RTC ausgelesen wurde und LCD update erfolgt ist.
Joachim B. schrieb:> Leichter wäre es wenn ich im Interrupt fragen könnte ob der Bus frei> ist, es macht ja nix wenn der IRQ alle 10ms aufruft wenn mir einmal für> 10ms eine Abfrage auf Tasten entgeht sollte der Timer IRQ mitten in eine> main loop I2C Abfrage reinspringen.>> meine eigenen Versuche mit den> while (!(TWCR & (1<<TWINT))); // Ende vom Verkehr abwarten ?> scheiterten wenn der Timer IRQ zuschlug, der I2C Zugriff der main loop> wurde durch Unterbrechung nicht beendet.>> oder habe ich das irgendwie noch nicht komplett verstanden ?
Mal sehen, ob ich das richtig verstanden habe:
Du fragst deine Tasten in der Timer ISR ab ?
Wenn du aber mit RTC beschäftigt bist, willst du nicht unterbrochen
werden ?
Wenn so, INTs sperren und wieder freigeben.
Oder gleich wieder aus der ISR raus, falls du gerade beim RTC Verkehr
bist ?
Wenn so, eine Art von RTC_Flag setzen, beim ISR-Eintritt prüfen.
Oder habe ich da etwas falsch verstanden ?
Wie ich das sehe, kann man Status nicht abfragen, wenn man
vorher nichts gesendet hat, also ist nichts mit while schleife.
Die andere Möglichkeit, auf Bus Idle zu warten ist bißchen kompliziert
weil der Clock eben nicht 50/50 sein muß, sondern kann beliebig lange
bzw. kurze High/Low Zeiten haben, solange die Mindestzeiten eingehalten
werden. Und die sind sogar bei 100KHz nur 4us. Da ist mit Wartezeiten
von mindestens 10ms zu rechnen, nur um sicher zu sein, daß nichts auf
dem Bus läuft. Ob das die Lösung ist, die du suchst, bezweifle ich.
Aber am besten erklärst du nochmal genau was du vermeiden willst.
Marc Vesely schrieb:> Mal sehen, ob ich das richtig verstanden habe:> Du fragst deine Tasten in der Timer ISR ab ?
genau, damit mir kein Tastendruck entgeht
> Wenn du aber mit RTC beschäftigt bist, willst du nicht unterbrochen> werden ?
nein, unterbrochen schon aber dann in der Timer ISR eben kein I2C Tasten
abfragen
> Wenn so, INTs sperren und wieder freigeben.
jain, mache ich ja schon
> Oder gleich wieder aus der ISR raus, falls du gerade beim RTC Verkehr> bist ?
nö alles andere muss ja in der ISR fertig gemacht werden, ausser in dem
Moment die Tasten, die dürfen auch mal für 10ms ungefragt bleiben,
werden also in der ISR übersprungen.
Die einzige Gefahr die bleibt das immer zufällig, die I2C Tastenabfrage
im Timer synchron auf RTC Abfrage im main loop folgt, was dann zu keiner
Tastenabfrage führen würde, aber das verhindere ich im Moment damit das
ich das Flag für LCD update (wo die RTC Abfrage erfolgt) in der ISR
setze also bestimme ob ich in der ISR Tasten abfragen mag oder nicht und
diese sequenziell erfolgen.
Ablauf,
10ms Timerinterrupt
1
if(lcd_time_update)
2
lcd_time_update--;
3
else
4
{lcd_time_update=33;
5
_i2c_busy=1;
6
}
7
// hier folgt noch was ......
8
// ......
9
// hier gehts weiter ......
10
if(_i2c_key)
11
{if(!_i2c_busy)
12
{if(_i2c_key=='A')
13
{if(!i2c_start(PCF8574A_0+I2C_READ))//; // set device address and write mode
_i2c_busy=0;// gibt i2c auch für Tastatur im IRQ wieder frei
8
}
> Wenn so, eine Art von RTC_Flag setzen, beim ISR-Eintritt prüfen.
ich denke das mache ich ja
> Oder habe ich da etwas falsch verstanden ?
nö
> Aber am besten erklärst du nochmal genau was du vermeiden willst.
ich glaube habe ich erklärt
es sieht momentan so aus als wenn es prima läuft, kann keinen Absturz
mehr provozieren.
Simon S. schrieb:> Unter Linux gibt es das Tool i2cdetect, welches genau das macht> was du> willst. Es benutzt zwei verschiedene Methoden (schreiben & lesen), die> je nach zu scannender Adresse benutzt werden (weil die jeweils eine oder> andere Methode bei manchen Chips Probleme bereiten kann).>> Hier der Code zum Scannen (in C):> https://github.com/groeck/i2c-tools/blob/master/tools/i2cdetect.c#L58> Von den zwei geschachtelten for-schleifen nicht verwirren lassen, das> kommt daher dass die Ausgabe in 16 Spalten erfolgt:
Also dieser hier
Ohne jetzt den Ganzen Thread zu lesen,
I²C Devices geben sich mit einem ACK/NACK zu erkennen wenn sie
angesprochen werden und existieren / nicht existieren.
Der Buspirate nutzt dies um nach gültigen I²C Adressen zu suchen.
Im Hackaday Forum ist der Quellcode dazu verfügbar.