Hi, ich lese mich gerade in diesen Artikel ein: http://www.mikrocontroller.net/articles/AVR_TWI Unten sind 2 AN angezogen: AVR311 und AVR315 In den AN steht etwas von c-libs für Slave und Master. Doch wo bekomme ich diese her? Gruß, DS
Hi >In den AN steht etwas von c-libs für Slave und Master. Doch wo bekomme >ich diese her? ATMEL WEbseite. http://www.atmel.com/products/microcontrollers/avr/megaavr.aspx?tab=documents MfG Spess
eine gute Seite ist auch http://www.engineersgarage.com/embedded/avr-microcontroller-projects/atmega32-twi-two-wire-interface
Hi, hatte imemr nur die ANs gefunden, jetzt aber - danke! War nun auch hier: Beitrag "AVR TWI Master und Slave Funtionen in C" unterwegs. Hat jemand Erfahrungen mit dem Code von Atmel? @Christoph B. Schaue ich mir an. Gruß, DS
> Hat jemand Erfahrungen mit dem Code von Atmel? Ja, ich hab mir den vor Jahren auch gegriffen, um TWI zu machen. Ist für IAR geschrieben, kann man aber leicht für avr-gcc umstellen und er funktioniert. Fehlerhandling nur ansatzweise vorhanden. Der Code arbeitet Interrupt-gesteuert, was wiederum zur Folge hat, daß man sich in die ISR nicht beliebig Debug-Ausgaben reinbasteln kann. Ich hab das für mich damals so gelöst, daß ich zum Debugging in der ISR mit jedem Aufruf den Wert von TWSR und TWCR in ein Array geschrieben habe, um hinterher in Ruhe zu analysieren, was denn da so abgegangen ist. Du benötigtst dann den Beispielcode für TWI-Master und -Slave. Vergiss die Pullups an SDA und SCL nicht und fang erstmal mit einer niedrigen Übertragungsrate an. Du brauchst weiterhin zwei AVRs zum Testen: Einen Master und einen Slave. Ich habe damals den Code für TWI-Master und TWI-Slave aus Bequemlichkeit in einen Topf geschmissen, d.h. nur ein Projekt im AVR-Studio und Master bzw. Slave dann über EEPROM konfiguriert. Macht das Ganze TWI-Geraffel noch komplexer, aber du hast eben nur ein Hexfile, was du auf die AVR flashen musst. Alternatives Vorgehen: Du besorgst dir ein TWI- oder I2C-Teil, von dem du weißt, daß und wie es funktioniert und bastelst auf dem AVR nur das entsprechende Gegenstück. Forschungsintensiver und spannender ist aber alle Mal die Aktion mit selbstgemachtem TWI-Master und -Slave. Viel Erfolg.
...ich sehe das auch schon, das kann noch was werden... Ich wollte eigentlich nicht viel forschen, nur nutzen... Geht das ganze denn auch ohne Interrupts? Habe hier Zeitscheiben von 1ms und brauche keine hohen Datenraten, ich möchte nur gelegentlich ein Steuerbyte von einem Drehencoder übertragen. Momentan zudem nur vom Slave zum Master, naja ein ACK gibt es da ja, so wie ich verstanden habe... DS
Hardware ist schon fertig, mir fehlt nur noch die TWI Verbindung... ACHTUNG GROSSER THREAD Beitrag "Re: Zeigt her eure Kunstwerke (2)" Steller - TWI - Steuerung - 10V - Leuchtstoffröhre fertig i.a. fertig fertig fertig Gruß, DS
Wenn der Leuchtsoffröhrendimmer der Master ist, dann fragt der also aktiv den Steller ab, welchen Wert er gerade hat? D.h. solange der Dimmer nicht fragt, kann auch der Steller nicht antworten. Ich würde den Steller zum Master machen, damit er sofort, wenn an ihm gedreht wird, dem Dimmer den neuen Wert weitergeben kann, .d.h. Steller=Master, Dimmer=Slave. Aber das nur nebenbei. Wenn der Steller nun doch der Slave sein muss, dann spricht nichts dagegen, den Slave-Beispielcode von Atmel zu nehmen, auch wenn er Interruptgesteuert ist. Die für den Steller relevante Funktion ist
1 | TWI_Start_Transceiver_With_Data(&temp, 1); |
Diese Funktion macht den Slave "scharf", damit er antworten kann, wenn ein Master ihn fragt. Die immer mit dem aktuellen Stellerwert bestückt werden muss, damit der Slave antworten kann, wenn der Master fragt, s. TWI_slave.c aus der AppNote AVR311. TWI-Slave ohne Interrupts halte ich für keine gute Idee, weil der Slave dann ständig aktiv gucken muss, ob der Master was von ihm will. Genau aus diesem Grund erfand die Evolution die Interrupts. Mit google findest du mit sicherheit noch andere TWI-Slave-Implementierungen, aber -egal welche- jede muss von dir an deine spezielle Anwendung angepasst werden. Daher würde ich ruhig die Implementierung von Atmel nehmen, die ist klein, ausreichend generisch und die funktioniert
Hi, ich habe soeben die Funktionen aus diesem Thread Beitrag "AVR TWI Master und Slave Funtionen in C" eingebunden, lief auf Anhieb. ABer schön ist was anderes denke ich. >>weil der Slave dann ständig aktiv gucken muss... Genau so läuft es momentan. Der Slave pollt. >>Daher würde ich ruhig die Implementierung von Atmel nehmen Werde ich auch ausprobieren. >> .d.h. Steller=Master, Dimmer=Slave. Aber das nur nebenbei. Wäre denkbar. >>ob der Master was von ihm will ist ok, ich versuche immer Interrupts zu vermeiden, wenn es geht. Das meiste bekomme ich mit meinen Zeitscheiben hin. Wie ist es denn Prinzipiell bei TWI? Damit eine Information von einem Slave zum Master kommt, muss der Master immer anfragen, oder kann der SLave auch aktiv werden? Wenn ich also 127 SLaves habe, mit 127 Stellknöpfen, dann müsste ich die ständig alle abfragen!? Wäre es möglich das Prinzip zu ändern, und nur die Daten von den Slaves zu übertragen die Änderungen haben um den Bus zu entlasten. Ansonsten hätte ich eine Verlangsamung des Bussystems proportional zur Anzahl seiner Teilnehmer...da der Master immer meht abfragen muss. Kollisionen, Broadkast? Danke schonmal, DS
>Wie ist es denn Prinzipiell bei TWI? Damit eine Information von einem >Slave zum Master kommt, muss der Master immer anfragen, oder kann der >SLave auch aktiv werden? Der Slave wird nie von alleine aktiv. >Wenn ich also 127 SLaves habe, mit 127 Stellknöpfen, dann müsste ich die >ständig alle abfragen!? Ja. >Wäre es möglich das Prinzip zu ändern, und nur die Daten von den Slaves >zu übertragen die Änderungen haben Möglich ist alles. Nur hast du dir wohl den falschen Bus dafür ausgesucht.
>Wie ist es denn Prinzipiell bei TWI? Damit eine Information von einem >Slave zum Master kommt, muss der Master immer anfragen, oder kann der >SLave auch aktiv werden? Nein die Rollen sind klar definiert: Wie im echten Leben darf der Slave nur aktiv werden, wenn der Master das wünscht. Jeder Busteilnehmer kann aber sein Verhalten jederzeit ändern und selbst den Master machen. Kann man machen, macht aber alles noch komplizierter, weil bei mehreren potentiellen Mastern die Master dann wieder auf verlorene Bus-Arbitration reagieren müssen, später noch mal versuchen, usw. Einfacher: 1 Master + viele Slaves. >Wäre es möglich das Prinzip zu ändern, und nur die Daten von den Slaves >zu übertragen die Änderungen haben um den Bus zu entlasten. Ansonsten >hätte ich eine Verlangsamung des Bussystems proportional zur Anzahl >seiner Teilnehmer...da der Master immer meht abfragen muss. Kollisionen, > Broadcast Wie gesagt, jeder Busteilnehmer kann den Master mimen, muss aber dann, wenn den Kampf um den Bus verloren hat, diesen wieder freigeben und später nochmal versuchen. Ist komplizierter zu implementieren und führt zu Totzeiten. Einfacher: Ein Master, Rest Slaves. Vorteil: Keine Buskollisionen und keine Totzeiten, weil nur ein Master die Spielregeln bestimmt und der kann quasi ohne Pause alle Slaves abfragen: Protokoll-Overhead ist auch sehr gering: Die Anfrage vom Master an einen Slave ist man gerade 9 oder Bit lang, dh. bei 100kHz SCL dauert das weniger als 100µs. Lass es mit der Antwort vom Slave 400µs dauern, dann reicht das für 2500 Abfragen an einen Slave pro Sekunde. Ansonsten hast du immer noch die Option SCL zu Lasten der max. Leitungslänge hochzudrehen.
>>Kann man machen, macht aber alles noch komplizierter ok, klar á la CSMA CD oder CA... >>Ansonsten hast du immer noch die Option SCL zu Lasten der max. Leitungslänge hochzudrehen. da es hier nicht um einen Hausbus geht, wäre das kein Problem. Aber es geht ja zudem auch nicht mal um eine Zeitkritische Anwenung o.ä... ist alles Kindergarten, mir gings nur um das Prinzip... Ich schaue gerade mal in den Code von Manni Beitrag "Re: 2 Atmega168 per TWI verbinden" welchen ich mal eingebaut habe, läuft auf Anhieb. Nun sehe ich das: { TWDR = byte; TWCR = (1<<TWINT)|(1<<TWEN)|(1<<TWEA); while (!(TWCR & (1<<TWINT))); } warum macht man soetwas (while). Ich werde es also anpassen und zu einer vernünftigen state machine machen müssen... Wenn nun also 8 Byte gesendet werden, wartet der Controller auf jedes Byte in dieser Schleife... das ist doch Grütze. Was mich bei TWI auch noch interessiert. Wie läuft das prinzipiell mit der Adresse, was ist wenn mal ein Byte flöten geht, dann verschiebt sich doch alles und das erste Byte aus dem Datenrahmen wird zur Adresse? Gibts einen Sync o.ä.? Gruß, DS
ok, Adresse sitzt in TWAR...trotzdem hatte ich schon mal den Zustand das Master und Slave nicht zusammengefunden haben... warum auch immer...
1 | {
|
2 | TWDR = byte; |
3 | TWCR = (1<<TWINT)|(1<<TWEN)|(1<<TWEA); |
4 | while (!(TWCR & (1<<TWINT))); |
5 | }
|
>warum macht man soetwas (while). Ich werde es also anpassen und zu einer >vernünftigen state machine machen müssen... Ein Funktionsprinzip des dort verwendeten Code heißt: Wenn ich eine TWI-Funktion aufrufe, dann kann ich immer davon ausgehen, daß die letzte TWI-Aktion abgeschlossen ist. Schreiben einer 1 ins TWINT-Bit löscht das Bit ( hat Atmel so definiert ) und die While-Schleife wartet drauf, daß die TWI-Operation fertig ist (was durch das erneute Setzen des TWINT-Bit) signalisiert wird. Das ist halt der Nachteil, wenn man aktiv wartet und keine Interruptgesteuerten Routinen verwendet. > Was mich bei TWI auch noch interessiert. Wie läuft das prinzipiell mit > der Adresse, was ist wenn mal ein Byte flöten geht, dann verschiebt sich > doch alles und das erste Byte aus dem Datenrahmen wird zur Adresse? Atmel Manual 22.4: Es wird Aufwand betrieben um sicherzustellen, daß nur ein Master sendet. Wenn Daten verlorengehen, dann die ganze Sequenz, weil sich alle Teilnehmer auf die Start-Sequenz synchronisieren. Außerdem gibt es nach jedem Byte ein ACK vom Slave. Damit weiß der Master daß das Byte korrket angekommen ist. Wenn dir das als Sicherheit nicht reicht, dann musst du per SW halt noch einen Quittungsmechanismus implementierten. Kann man machen, muß man aber nicht, solange kein Leben davon abhängt.
Referenz: http://www.atmel.com/Images/doc2545.pdf >>wenn man aktiv wartet und keine Interruptgesteuerten Routinen verwendet. Wenn ich die Verbindung zum Master trenne, dann steht der Slave. Das kann ja nicht richtig sein. Im Main ist es so implementiert: for (i=0;i<8;i++) { TWIS_Write (j++); } TWIS_Stop (); Wie schon geschrieben, bleibt einem nichts anderes übrig als selbst was zu stricken. 22.5 dort ist ein Blockschaltplan, aber noch sehr grob. Ich meine ich habe irgendwo noch mal etwas detailierteres gesehen. ALso eine Übersicht in der man ausgangs und eingangs shift reg sieht, wenn es denn bei twi überhaupt 2 getrennte Register gibt. Naja, da immer eine Adresse als erstes kommt, erkennt die Arbitration bereits beim schreiben der Adresse ob es noch weitergehen darf, richtig!? Es kommt also nie soweit das 2 Teilnehmer ob nun Master oder Slave (bei entsprechender Implementierung) gleichzeitig Daten schreiben. Das heißt beim Daten Schreiben muss nicht zurückgelesen werden was geschrieben wurde, wird sicher auch nicht gemacht, oder? Ich habe bereits oben im Artikel danach gesucht wie die Start Marke überhaupt aussieht, ist es wirklich nur das fallen von SDA bevor SCL fällt, und STOP wirklich nur das spätere Hochziehen von SDA oder ist es hier das längere hoch bleiben des SCL? TWINT Flag muss gesetzt werden um es zurückzuseten. Ist es richtig das man eigentlich immer über dieses Bit geht um die grundsätzliche Kommunikation zu regeln ob nun Interruptgesteuert oder nicht? TWEA Flag setzt man im single Master Systemen nur beim Slave!? richtig, oder? TWCR:TWIE Welches Bit setzt man um den TWI Interrupt zu aktivieren, ich hätte erwartet das dies Bit für TW Interrupt Enable steht. Ich finde die Beschreibung im Atmel DB recht gewöhnungsbedürftig, da die Bits nicht einzeln erklärt sind... Bei den Atmel Beispielen ist es auch so, das dort gleich riesen Abhandlungen, case fälle abgefangen werden und auch noch Taster abgefragt und lampen angesteuert, das ist viel zu viel. TWSR gibts dazu eigentlich nur diese riesentabellen? Man sieht das Register also immer als ganzes? Nun stecke ich doch mitten drin... Gruß, DS PS.: Ich habe es selten gesehen das man so eine einfache Steuerung zu kompliziert beschreibt...das geht mir allerdings mit den Atmel Timern genauso.
Hi >Ich finde die >Beschreibung im Atmel DB recht gewöhnungsbedürftig, da die Bits nicht >einzeln erklärt sind... Schon mal im Datenblatt unter 22.9 Register description nachgesehen? Da wird jedes Bit erklärt. MfG Spess
das bringt Klarheit... Gibt es bei dem TWI IF eigentlich 2 Register für "in" und "out" - interessiert mich nur der vollständigkeit halber... DS
>Gibt es bei dem TWI IF eigentlich 2 Register für "in" und "out" - >interessiert mich nur der vollständigkeit halber... Es gibt nur ein TWDR für Lese- und Schreiboperationen. Aber Atmel wäre nicht Atmel, wenn sie dafür nicht etwas erfunden hätten: Das TWWC-Bit im TWCR. Hilft nicht wirklich. >Wenn ich die Verbindung zum Master trenne, dann steht der Slave. Das >kann ja nicht richtig sein. Bist du sicher? Eigentlich sollte in jedem Fall nach 9 Bits ein Status mit gesetztem TWINT-Bit zurückgegeben werden, enweder mit Fehlerstatus oder auch nicht. >Wie schon geschrieben, bleibt einem nichts anderes übrig als selbst was >zu stricken. Das sind genau die 20% Progammcode, die 80% der Zeit fressen und aus einem Showcase eine (fast) fehlerfreie und robuste Anwendung machen. >Das heißt beim Daten Schreiben muss nicht zurückgelesen werden was >geschrieben wurde, wird sicher auch nicht gemacht, oder? Nein >Ich habe bereits oben im Artikel danach gesucht wie die Start Marke >überhaupt aussieht, ist es wirklich nur das fallen von SDA bevor SCL >fällt, und STOP wirklich nur das spätere Hochziehen von SDA oder ist es >hier das längere hoch bleiben des SCL? s. 22.3.2 : Start und Stop sind entsprechende Flnakenwechsel von SDA bei SCL=High. Musst du dich aber nicht drum kümmern, das macht die TWI-Hardware.
>>TWWC-Bit ok, wird gesetzt wenn man ins register schreibt wenn TWINT low ist... >>Bist du sicher? kommt vor, ist ja auch klar, ich habe ja das Beispiel von Manni ohne Interrups am Haken, nun wenn ich zufällig trenne während der Slave auf eine Anfrage vom Master antwortet, befindet er sich in der While Schleife die so lange läuft wie das TWINT nicht gesetzt ist, oder? Wenn aber der Masterclock fehlt kommt der Slave nie dazu das das TWINT gesetzt wird, da er seine Restbits nicht los wird...oder!? *******************************************************/ void TWIS_Write (uint8_t byte) { TWDR = byte; TWCR = (1<<TWINT)|(1<<TWEN)|(1<<TWEA); while (!(TWCR & (1<<TWINT))); } >>eine (fast) fehlerfreie und robuste Anwendung machen YES! so ists wohl. Ich würde ja gerne zumindest sicherstellen das die Kommunikation auf jeden Fall wieder anläuft wenn man sie wieder verbindet (Master - Slave) habe ja nicht mehr. Ich bin gerade im Slave am Umstricken und hier angekommen: uint8_t TWIS_ReadAck (void) uint8_t TWIS_ReadNack (void) /******************************************************* Public Function: TWIS_ReadAck Purpose: Read a byte from the master and request next byte Input Parameter: None Return Value: uint8_t - uint8_t Read byte *******************************************************/ uint8_t TWIS_ReadAck (void) { TWCR = (1<<TWINT)|(1<<TWEN)|(1<<TWEA); while (!(TWCR & (1<<TWINT))); return TWDR; } /******************************************************* Public Function: TWIS_ReadNack Purpose: Read the last byte from the master Input Parameter: None Return Value: uint8_t - uint8_t Read byte *******************************************************/ uint8_t TWIS_ReadNack (void) { TWCR = (1<<TWINT)|(1<<TWEN); while (!(TWCR & (1<<TWINT))); return TWDR; } A)ReadNack wird aufgerufen wenn das letzte Byte einer Übertragung vom Master zum Slave gesendet wird, es gibt nur einen unterschied: TWEA wird nicht gesetzt. Also wird das letzte Byte vom Slave nicht quittiert!? Ist das richig? B)Es steht zudem nirgens geschrieben das man es für jedes empfangene Byte erneut setzen muss, oder? Das ist doch nur ein Schalter wie TWEN auch. Die muss man doch nicht bei jedem Byte neu einschalten...oder verstehe ich das falsch? 22.9.2 So ist der Aufruf im Main: case TWIS_ReadBytes: for (i=0;i<1;i++) { byte[i] = TWIS_ReadAck (); } byte[1] = TWIS_ReadNack (); TWIS_Stop (); break; Vielen viele Dank bis hierher. DS
DS schrieb: > TWEA wird nicht gesetzt. Also wird das letzte Byte vom Slave nicht > quittiert!? Ist das richig? > > B)Es steht zudem nirgens geschrieben das man es für jedes empfangene > Byte erneut setzen muss, oder? Das ist doch nur ein Schalter wie TWEN > auch. Die muss man doch nicht bei jedem Byte neu einschalten...oder > verstehe ich das falsch? 22.9.2 Dieses ACK musst du eher als "Bereit für nächstes Byte" interpretieren. D.h. Solange ein Teilnehmer mit ACK bestätigt heißt das "ich kann weiter Senden/Empfangen" oder anders rum: NACK heißt: Ich kann nicht mehr empfangen/ich will nicht weiter senden. Im Falle eines NACK muss der andere Teilnehmer auch seine Sendung/Empfang einstellen und den Bus freigeben. Also wenn du soll willst, ist TWEA das Flag für "weitermachen" Google mal nach I2C Specification, da wird das besser erklärt als im Atmel-Manual.
Hi, danke für die Hinweise. Das muss ich dann ggf mal machen. Ich habe meine Datenstrecke nun eigentlich fast komplett. Ich habe zur Zeit das Problem das ich bei meiner bidirektionalen Datenstrecke nach dem Programmstart ein Problem mit der Übertragung vom Master zum Slave bekomme. Zur zeit habe ich das so angelegt, das es alle 500ms eine Aktion auf dem Bus gibt. Der Master fragt abwechselnd lesen und schreiben beim Slave an - eigentlich nichts wildes. Die Übertragung vom Slave zum Master, also wenn der Master lesend anfragt funktioniert tadellos. Der andere Weg geht nur 1x dann kommt der Master Write immer mit einer 0x28 zurück am ende der Übertragung. Es geht nur 1x wenn zuvor kein Master Read war ich also das Programm mit einem Master Write starten lasse. Sobald 1x ein Master Read war, geht das Master write nicht mehr. Wenn ich das Master Read ganz weg lasse dann geht das Master write tadellos, wie das Master read das eh immer geht... nun heißt 0x28 nach dem letzten Master Write byte: #define TWI_MTX_DATA_ACK 0x28 // Data byte has been tramsmitted and ACK received #define TWI_MTX_DATA_NACK 0x30 // Data byte has been tramsmitted and NACK received das ein ACK vom Slave kam. Wenn ich das Master Read weg lasse, kommt er mit 0x28 zurück und die Strecke läuft wie gesagt.... Ich stecke in der Klemme... DS
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.