I2C Verständnisfrage Im Unterforum Microcontroller - Beschreibung: Hardware - Software - Ideen - Projekte
Autor |
I2C Verständnisfrage Suche nach: i2c (581) |
|
|
|
|
BID = 959919
RoyalRIDEr Gerade angekommen
Beiträge: 6
|
|
Hey,
Ich hab mich jetzt mit dem I2C Protokoll beschäftigt, da ich es für die Übertragung zwischen Arduinos brauche (Arduino weil einfach handhabbar und ich kaum Erfahrung habe). Dabei tut sich mir jedoch eine Frage auf:
Wenn der Master Daten vom Slave haben möchte, sendet er ja das Startsignal und dann gleich die Adresse usw.. Wie macht man das aber mit einem Slave, der gerade beschäftigt ist? Der bekommt doch garnichts vom Startsignal mit. Ich hab gelesen, dass wenn der Slave das Startsignal bekommt und auch seine Adresse genannt wird, er den Clock auf 0 zieht, sein Zeug fertig macht, den Takt wieder frei gibt und dann an der Leitung horcht. Aber gerade dafür muss er ja das Startsignal schon mitbekommen haben.
Eine Lösung die mir dazu eingefallen ist: Man macht eine dritte Verbindung zwischen Master und Slave die ebenfalls über nen Widerstand an VCC angebunden ist und wenn der Master was will, zieht er die Leitung auf 0V. Die Arduinos haben so eine AttachInterrupt Funktion. Damit könnte man wenn diese dritte Leitung auf 0 liegt den Chip dazu zwingen mit seiner Arbeit aufzuhören um an den I2C Leitungen zu horchen. Aber das muss doch auch ohne diese dritte Leitung gehen, oder?
Freundliche Grüße, RoyalRIDEr |
|
BID = 959924
perl Ehrenmitglied
Beiträge: 11110,1 Wohnort: Rheinbach
|
|
Schlimmstenfalls muß man einen Power-On-Reset machen, wenn auch dies nicht hilft:
Zitat :
| 3.1.16 Bus clear
In the unlikely event where the clock (SCL) is stuck LOW, the preferential procedure is to
reset the bus using the HW reset signal if your I2C devices have HW reset inputs. If the
I2C devices do not have HW reset inputs, cycle power to the devices to activate the
mandatory internal Power-On Reset (POR) circuit.
If the data line (SDA) is stuck LOW, the master should send nine clock pulses. The device
that held the bus LOW should release it sometime within those nine clocks. If not, then
use the HW reset or cycle power to clear the bus |
http://www.nxp.com/documents/user_manual/UM10204.pdf
Ich habe mich allerdings mit IIC-Bus kaum beschäftigt. |
|
BID = 959925
der mit den kurzen Armen Urgestein
Beiträge: 17434
|
Du musst noch viel lernen Die Abfrage des I2C erfolgt in einer Interuptschleife.
_________________
Tippfehler sind vom Umtausch ausgeschlossen.
Arbeiten an Verteilern gehören in fachkundige Hände!
Sei Dir immer bewusst, dass von Deiner Arbeit das Leben und die Gesundheit anderer abhängen!
|
BID = 959937
DonComi Inventar
Beiträge: 8605 Wohnort: Amerika
|
@Bernd:
Kann sie, muss aber nicht!
Bei Arduino weis man nie so genau...
Ansonsten super, wie du dich über Anfänger lustig machst. Du kannst mir dafür ja mal erklären, was eine Interruptschleife ist ...
Theoretisch hat Bernd aber recht:
Du richtest einen Arduino als Slave ein.
Nach jedem I²C-Ereignis kann die I²C-Hardware einen Interrupt auslösen, der bei entsprechend konfiguriertem AVR dann auch ausgeführt wird und du sofort reagieren kannst.
Meines Wissens kann man sogar einstellen, dass die I²C-Hardware die Taktleitung solange blockiert (clock stretching), bis die I²C-Hardware vom Steuerprogramm des Slaves bedient wird. Da liegt aber das Problem: wenn z.B. die Interrupts temporär abgeschaltet sind und aus irgendeinem Grund nicht wieder reaktiviert werden, dann ist der Bus blockiert. Und wenn dann zusätzlich der Master alles synchron macht (also solange wartet, bis die I²C-Aktion abgeschlossen wurde), dann stürzt das System Master<-I²C->Slave komplett ab.
Also, Zustandsmaschinen auf beiden Seiten, die durch ein I²C-Ereignis getriggert werden. Um zu entscheiden, was als nächstes passieren soll (Zustandsübergang) kann das I²C-Statusregister sehr hilfreich sein.
Typischerweise kann das z.B. so aussehen: der Master adressiert den Slave mit dessen Lese-Adresse, dieser schickt (vorher einrichten!) ein ACK.
Sobald der Slave das ACK gesendet hat (passiert durch die eingerichtete Hardware selbstständig), bekommst du beim Slave ein Interrupt. Du liest das Statusregister aus und erhälst "kürzlich mit eigener Read-Adresse adressiert, ACK gesendet". Die Reaktion kann dann sein, dass du Daten lädst, die dann in der folgenden Transaktion rausgetaktet werden. Du bekommst am Ende halt auch mit, dass der Master ein Stop gesendet hat usw.
(Typischerweise adressiert man meistens immer zuerst den Slave mit der Schreibadresse, übergibt noch ein paar Daten (z.B. Adressen, Register oder einfach Dummybytes), sendet dann ein sog. Repeated start (zweite Startbedingung ohne vorherige Stoppbedingung) gefolgt von der Leseadresse, ist aber fürs Beispiel egal ;))
Ob und wie das mit Arduino funktioniert, kann ich dir nicht sagen.
Die dem urspr. Arduino zugrundeliegenden AVRs können das aber fast alle, und das in reiner Hardware. wie die Arduino-libs das abbilden, weis ich nicht.
_________________
[ Diese Nachricht wurde geändert von: DonComi am 29 Apr 2015 2:34 ]
[ Diese Nachricht wurde geändert von: DonComi am 29 Apr 2015 2:36 ]
|
BID = 959951
RoyalRIDEr Gerade angekommen
Beiträge: 6
|
Zitat :
| Schlimmstenfalls muß man einen Power-On-Reset machen, wenn auch dies nicht hilft: |
Mir geht es ja nicht um ne verstopfte Leitung... das mit dem "clock stretching" hab ich nur erwähnt um zu zeigen, dass ich mich damit beschäftigt habe, bevor sowas wie "google doch selbst" oder so kommt.
Zitat :
| Du musst noch viel lernen |
Ja, genau deshalb frag ich ja nach
@DonComi
Vielen Dank, das ist genau das, was ich wissen wollte! Ich wusste gar nicht, dass es etwas wie ein I2C Register und extra dafür eine Interrupt Funktion gibt. Und das steht irgendwie auch in keiner allgemeinen Beschreibung.
Ich hab jetzt mal versucht den Vorgang in den Bibliotheken wiederzufinden und hab für den Empfang folgende Methode gefunden:
Code : |
void TwoWire::onReceiveService(uint8_t* inBytes, int numBytes)
{
// don't bother if user hasn't registered a callback
if(!user_onReceive){
return;
}
// don't bother if rx buffer is in use by a master requestFrom() op
// i know this drops data, but it allows for slight stupidity
// meaning, they may not have read all the master requestFrom() data yet
if(rxBufferIndex < rxBufferLength){
return;
}
// copy twi rx buffer into local read buffer
// this enables new reads to happen in parallel
for(uint8_t i = 0; i < numBytes; ++i){
rxBuffer[i] = inBytes[i];
}
// set rx iterator vars
rxBufferIndex = 0;
rxBufferLength = numBytes;
// alert user program
user_onReceive(numBytes);
}
|
|
Das bringt mir aber herzlich wenig, weil ich die Variablen in dieser Datei nicht wiederfinde und 4 Headerdatein eingebunden sind, die man ja komplett durchsuchen müsste. Vermutlich könnte man die Variablennamen auch so verstehen, aber dazu fehlt mir dann das Grundwissen über die genauen Vorgänge bei der Übertragung. Deshalb werd ich das dann später wenn ich die Hardware hab einfach ausprobieren müssen.
Dabei stellt sich mir noch weitere Frage: Kann ich nicht einfach ein Arduino und noch nen baugleichen Controller kaufen, den einen Controller programmieren, rausnehmen und extra verbauen und den anderen auf der Arduino Platine lassen? Weil ich beim Betrieb dann gar keine USB-Verbindung, LED usw. benötige.
|
BID = 960002
DonComi Inventar
Beiträge: 8605 Wohnort: Amerika
|
Hi,
zu dem Code kann ich nichts sagen, da ich mit Arduinos ungern arbeite und das vermeide, wo es nur geht.
Scheint aber sowas wie ein Callback-Handler zu sein und nach meinem Verständnis wird der aufgerufen, sobald Daten einer gewissen Länge empfangen wurden.
Aber: da müsste man in die Dokumentation gucken, die es hoffentlich für die TWI-Klasse gibt (alles andere wäre ekelig).
Zitat :
|
Und das steht irgendwie auch in keiner allgemeinen Beschreibung
|
Doch, schau ins Datenblatt des verwendeten Controllers. Da steht genau das drin und auch viel mehr.
Das Schöne daran ist auch, dass man das alles auf Hardwareebene serviert bekommt und man sicherstellen kann, dass die Hardware genau das tut, was man will, wenn man die Register richtig beschreibt. Keine (undokumentierte,) aufgeblähte Bibliothek sondern einfach nur ein paar Bits, die man setzen muss.
(Ich hab nichts gegen fertige Bibliotheken, aber für das Verständnis ist Hardwareebene besser).
Edit:
Du kannst dir statt dem Arduino auch einen z.B. ATmega88pa kaufen (kost runde 2,50€ oder weniger) und einen USB-Programmer samt Steckboard (oder ein paar Lochrasterkarten).
Das ist alles recht einfach mal eben zusammengesteckt und den ATmega88pa kannst du auch wirklich stecken (DIP-Gehäuse verfügbar).
_________________
[ Diese Nachricht wurde geändert von: DonComi am 30 Apr 2015 1:09 ]
|
|
Zum Ersatzteileshop
Bezeichnungen von Produkten, Abbildungen und Logos , die in diesem Forum oder im Shop verwendet werden, sind Eigentum des entsprechenden Herstellers oder Besitzers. Diese dienen lediglich zur Identifikation!
Impressum
Datenschutz
Copyright © Baldur Brock Fernsehtechnik und Versand Ersatzteile in Heilbronn Deutschland
gerechnet auf die letzten 30 Tage haben wir 19 Beiträge im Durchschnitt pro Tag heute wurden bisher 3 Beiträge verfasst © x sparkkelsputz Besucher : 182421809 Heute : 848 Gestern : 5459 Online : 283 29.11.2024 8:13 6 Besucher in den letzten 60 Sekunden alle 10.00 Sekunden ein neuer Besucher ---- logout ----viewtopic ---- logout ----
|
xcvb
ycvb
0.0252578258514
|