Datum: 12.10.2005 23:06
Ein einfaches Beispiel für einen TWI / I2C Master und Slave.
Es werden 2 Daten-Bytes an den Slave gesendet und anschließend zwei
Daten-Bytes vom Slave empfangen.
Es ist kein fertiges Projekt, aber es hilft hoffentlich,
die Grundmechanismen schneller zu erkennen.
z.B: - Initialisierung
- Adressvergabe
- Interrupt-Handling
- mögliche Error-Routinen
- TWSR / TWCR - Auswertung
Die LEDs vom MASTER zeigen den Zustand der Datenübertragung
(z.B. erfolgreicher START) an und
die LEDs vom SLAVE, welcher TWSR Zustand anliegt, wenn der
TWI-Interrupt aufgerufen wird.
Absichtlich habe ich alle Vorgänge stark durch Warteschleifen und eine
sehr niedrige SCL Frequenz gebremst, damit man besser nachvollziehen
kann, wann was und wo passiert.
Bernhard
Datum: 18.10.2005 20:38
Hallo, finde ich echt ne super sache das du das mal online gestellt hast, werde es sofort mal ausprobieren. Eine Frage hätte ich jedoch noch mit was für einem programm hast du den Plan gezeichnet?
Datum: 21.10.2005 12:22
@Thorran Microlovic >finde ich echt ne super sache das du das mal online gestellt hast, Danke, ich hoffe, dass dieses kleine Beispiel bei den Grundlagen etwas weiter hilft. >mit was für einem programm hast du den Plan gezeichnet? mit sPLAN 4.0, ist ein sehr einfaches und leicht zu bedienendes Programm mit vielen interessanten Spezialfunktionen.
Datum: 04.01.2006 15:28
Hey super ! Danke das du das Programm online gestellt hast. Möchte das selbe Programm in C-realisieren ! Nun habe ich von Assembler nicht so den Plan! Kann mir jemanden einen Tipp geben?
Datum: 21.01.2006 15:56
Hallo.. ich bin begeistert - genau das habe ich schon lange gesucht. Jetzt habe ich begonnen, das ganze für mein eigenes Programm abzuändern, und bin da auf ein Problem gestossen. Es gibt da 2 Sachen die ich nicht verstehe. Das ist die Abfrage des TW_INT_FLAG. WANN und von WEM wird es gesetzt oder gelöscht? Die andere Sache ist der Check des Status-Registers (TWSR) - dieses Register hat sehr unterschiedliche Werte. Ich möchte gern wissen, wie sich die einzelnen Werte zusammensetzen? Also der Wert im Register addiert mit 0xF8 ergibt einmal 0x08 oder 0x18 oder 0x40 usw. Könnte man das mal zum besseren Verständnis in einer Tabelle darstellen? Gruss Uwe
Datum: 22.01.2006 20:31
@Uwe Ortmann (Schwede) >Das ist die Abfrage des TW_INT_FLAG. >WANN und von WEM wird es gesetzt oder gelöscht? Gesetzt wird es, ganz allgemein ausgedrückt, wenn ein Ereignis am TWI registriert wird. z.B. -eine bestimmte Aktion (zB. Start) durchgeführt wurde -wenn ein Slave von einem Master angesprochen wird -ein Zeichen vom Master gesendet wurde -ein "Error" auftrat Gelöscht wird es, in dem es auf "1" gesetzt wird >Die andere Sache ist der Check des Status-Registers (TWSR) - dieses >Register hat sehr unterschiedliche Werte. Ich möchte gern wissen, wie >sich die einzelnen Werte zusammensetzen? Also der Wert im Register >addiert mit 0xF8 ergibt einmal 0x08 oder 0x18 oder 0x40 usw. Der Wert des Registers wird nicht mit 0xF8 addiert, sondern die untersten 3Bit auf 0 gesetzt (2xVorteiler und 1xReserviertes-Bit), sie werden sozusagen ausgeblendet. Die Werte und die Bedeutungen findest Du ab Seite 177 im Datenblatt. Anmekung: Für viele Anwendungen empfielt es sich, wenn man nach einem INT-Flag-Interrupt prüft, warum dieses INT-Flag gesetzt wurde. Ich hoffe, ich habe Dir etwas weiter helfen können? Demnächst werde ich hier ein sehr interessantes "RS232-TWI-Interface" veröffentlichen, dort sind die einzelnen Funktionen detaillierter angewendet worden. Gruß Bernhard
Datum: 22.01.2006 22:52
RS232-TWI-Interface: http://www.mikrocontroller.net/forum/read-4-291891.html
Datum: 28.01.2006 18:50
Hallo... erstmal Danke für die Tipps, haben mir sehr viel geholfen. Allerdings machen mir noch 2 Sachen "Kopfschmerzen". Ein kleines Problem: Ich takte meinen mega8 mit 16MHz - das macht dann pro Zyklus 60 ns. Wie baut man am besten eine Zählschleife auf, um eine Pause von 6 ms zu bekommen? Das grössere Problem: Ich möchte einen externen Interrupt an Int0 auswerten (also ein Unterprogramm starten). Ich bekomme das einfach nicht hin. Könnte ich ein wenig Hilfe bekommen? Gruss Uwe
Datum: 30.01.2006 09:59
@UWE >Wie baut man am besten eine Zählschleife auf, um eine Pause von 6 ms >zu bekommen? Du hast es schon richtig formuliert, mit einer Zählschleife, bei 16MHz Takt vergehen 0.0625µs pro Takt, d.h. Du müsstest den µC mit 96.000 Takten mit sich selbst beschäftigen, um eine Pause von 6ms zu erzeugen. Schau mal bitte nach unter: http://www.mikrocontroller.net/forum/read-4-57760.html# >Ich möchte einen externen Interrupt an Int0 auswerten (also ein >Unterprogramm starten). Vor langer Zeit habe ich hier mal einen kleinen Beitrag dazu geschrieben: http://www.mikrocontroller.net/forum/read-4-156657.html Vielleicht hilft es Dir etwas weiter? Bernhard
Datum: 07.02.2006 18:23
Hallo... nachträglich noch vielen Dank, hat mir weitergeholfen. Bei einer Sache muss ich allerdings noch mal nachfragen, damit ich da nichts falsch verstehe. Im Programm ganz oben ist der Vorteiler für das TWI mit 0, 4, 16 und 64 angegeben. Ist die 64 der grösst mögliche Teilungsfaktor? Denn wenn ich meinen Mega8 mit vollen 16MHz takte dann hätte ich auf dem TWI noch 250 KHz - also deutlich zu viel. Da wäre es wohl besser ich takte den Controller mit 1MHz. Da komme ich auf ca. 15KHz, was für eine längere Busleitung von Vorteil ist. Habe ich das so richtig verstanden? Gruss Uwe
Datum: 07.02.2006 21:38
@UWE >Ist die 64 der grösst mögliche Teilungsfaktor? >Da wäre es wohl besser ich takte den Controller mit 1MHz Ja das ist er und zusätzlich kannst Du auch die Bitrate ändern, um die SCL-Frequenz zu verändern, aber sie sollte größer als 11 sein, da es ansonsten zu Problemen bei der Busverbindung kommen kann. Ich stell Euch mal eine Excel-Tabelle zur Verfügung, womit man die SCL-Frequenz berechnen kann. Bernhard
Datum: 14.02.2006 16:25
Hallo,
kämpfe gerade mit TWI und bin dan hierauf gestoßen.
Da ist mir was aufgefallen: Die Berechnung der TWI-Bitrate
funktioniert
laut Atmel-Datenblättern so:
CPU Clock frequency
SCL frequency = ----------------------------
16 + 2(TWBR) x 4 ^ TWPS
In dem Excel-Sheet steht aber:
=Fcpu/(16+(2*TWBR)*TWPS)
Also, wenn ich die Frequenz für zwei gleich hoch getaktete Controller
berechne wird das vielleicht gehen, aber bei verschiedenen Frequenzen?
Oder übersehe ich was ganz entscheidendes?
Datum: 22.03.2006 00:16
@Ingo >In dem Excel-Sheet steht aber: > =Fcpu/(16+(2*TWBR)*TWPS) >Also, wenn ich die Frequenz für zwei gleich hoch getaktete Controller >berechne wird das vielleicht gehen, aber bei verschiedenen >Frequenzen? Oder übersehe ich was ganz entscheidendes? Du hast Recht, hab's auch gerade gesehen. In der euen Excel-Tabelle habe ich meinen Berechnungs-Fehler behoben. Danke für den Hinweis. Bernhard
Datum: 27.03.2006 13:56
@Mareike >Möchte das selbe Programm in C-realisieren ! Nun habe ich von >Assembler nicht so den Plan! Kann mir jemanden einen Tipp geben? ...wo drückt denn der Schuh ?
Datum: 01.04.2006 13:30
Hätte da eine Frage: Aus der Slave.asm: "TWSI_TW_SR_DATA_ACK: ; x80 10000000 (die vorher adressierten (SLA+W) Daten wurden empfangen; ACK wurde zurückgesendet cbi PORTB,4 in DATA, TWDR ; DATA rjmp TWSI_w" Ich will über TWI dem Slave einfach Daten zusenden. Seh ich das recht das ich an obiger Stelle die Empfangenen Datennn auswerten kann? Also sagen wir mal ich sende vom Master 0xFA an den Slave, und an der stelle wird dies empfangen? Und kann ich dann einfach alle LED ausgaben Auskommentieren oder ist noch mher nötig? Der Slave braucht auch nichts zurückzusenden, soll nur Daten empfangen.
Datum: 02.04.2006 20:43
@Läubi >Ich will über TWI dem Slave einfach Daten zusenden. >Seh ich das recht das ich an obiger Stelle die Empfangenen Datennn >auswerten kann? >Also sagen wir mal ich sende vom Master 0xFA an den Slave, und an der >stelle wird dies empfangen? Ja das ist korrekt, das empfangene Byte vom Master liegt nun im "DATA" zur weiteren Verarbeitung bereit >Und kann ich dann einfach alle LED ausgaben Auskommentieren oder ist >noch mher nötig? Der Slave braucht auch nichts zurückzusenden, soll >nur Daten empfangen. Die LEDs müssen nicht unbedingt sein, sie dienen nur dazu, zu zeigen, welchen Wert gerade das "TWSR" - Register gehabt hat. Bernhard
Datum: 29.10.2006 20:28
Hallo! Ich weiß dass ich einen ziemlich alten, aber nützlichen Beitrag hier entstaube. Ich habe dazu mal eine Frage: Ich brauche für einen Aufbau den I2C Bus. Ich habe mir mal dieses Beispiel heruntergeladen und ausprobiert. Es funktioniert, nur eben sehr langsam (ist ja auch oben gesagt). Also habe ich mir gedacht: Unnötige Wait-Befehele wegfallen lassen und die Prescaler und Bitrate-Werte so einrichten, dass die Übertragung recht schnell gehen müsste. Anhand der LEDs in den I2C-Leitungen kann man erkennen, dass die Datenübertragung recht schnell läuft (nur ganz kurzes aufblinken). Dennoch ist nach der Übertragung noch eine recht lange Pause, ehe die nächste Übertragung (neues Aufblinken) stattfindet. Hat jemand eine Idee, woran das liegen könnte? Vielen Dank schonmal für eure Hilfe!
Datum: 29.10.2006 20:34
Hallo Martin,
>Dennoch ist nach der Übertragung noch eine recht lange Pause
Ich vermute, dass noch irgendwo ein rcall wait_xxx sein unwesen treibt.
Entferne doch mal spaßenshalber komplett die wait Routinen ?
Gruß
Bernhard
Datum: 29.10.2006 21:02
Gesagt...getan...und eine äußerst verblüffende Antwort: Es gab in der Master-datei 2 wait-Zugriffe: - der erste nach der Initialisierung, den hatte ich vorher da gelassen weil der ja nur einmal durchlaufen wird und nicht stört. - der zweite im Abschnitt "TWI_ERROR". Das verwundert mich sehr, weil ich daraus schließe, dass nach jeder Übertraung anscheinend auch ein Fehler auftritt. Darf das sein? Ich meine es läuft jetzt schnell, also so wie gewünscht, aber es ist doch irgendwie ein komisches Gefühl zu wissen dass da immer ein Fehler drin ist. Oder ist das normal so?
Datum: 29.10.2006 21:08
>dass nach jeder Übertraung anscheinend auch ein Fehler auftritt. Darf das >sein ?
Nein, das darf natürlich nicht sein.
Also, Ursache suchen.
Vielleicht SCL-Takt zu hoch? Adresse falsch? usw...
Vielleicht gibts im Slave noch ein wait, so das das Antwort-Bit nicht
bereitgestellt wird?
Datum: 29.10.2006 21:22
Hm da habe ich sicher was zu suchen, weil ich im Grunde genommen deine möglichen Fehlerquellen ausschließen kann: SCL-Takt: Habe mit Bitrate 255 und Prescaler 64 bis zu Bitrate 11 und Prescaler 1 allerlei Tests gemacht, also bei 255/64 kann er ja nicht mehr zu hoch sein^^. Adresse kann nicht falsch sein, da der IC dann ja gar nicht angesprochen würde. Anhand von LEDs erkennt man ja dass er angesprochen wird, nur eben auch dass er wegen der langen Pause die Fehler-Routine aufruft. Im Slave ist kein Wait mehr vorhanden. Nunja ein Glück geht es ja schonmal jetzt sehr schnell - wofür ich sehr dankbar bin - der Fehler wird sich wohl im Laufe der Zeit und mit einer noch genaueren Vertiefung in den Bus hoffentlich finden.
Datum: 17.06.2007 23:14
Hallo alle zusammen, ich bin gerade auf der Suche nach I2C-Beiträgen auf diesen Artikel gestoßen. Oben ist dieses klasse Assembler-Programm gepostet. Leider habe ich von Assembler fast gar keine Ahnung und beschäftige mich gerade mit C für eine einfache Sende-Empfangs-Routine zwischen zwei AVR. Das Ding läuft leider noch nicht und langsam gehen mir die Ideen aus. 1. Frage: Hat schon einmal jemand den i2c.h Header in CodeVisionAVR benutzt? Nachdem mein selbst geschriebenes Programm Probleme macht, dachte ich versuche ich den mal zu verwenden. Hat da jemand zufällig ein kurzes Codebeispiel? Bei mir hakt es nämlich noch, der Slave versteht aus irgendeinem Grund nicht, dass er angesprochen wird... 2. Frage: Existiert ein diesem Assembler-Programm ähnliches C-Programm? Für eine C-Anfängerin wie mich wäre das nämlich echt hilfreich, da es ewig dauert, bis man ein laufendes Programm gebastelt bekommt (mit Datasheets, Atmel-Beispielen für andere Anwendungen, etc.)... Danke und viele Grüße!!! Xine.
Datum: 18.06.2007 00:08
Hi Xine, beschäftige mich auch grade mit TWI/I2C in C. Habe es mit der Procyon avrlib zum Laufen bekommen (Tastatur und Display). Schick mir doch mal genauere Angaben - welche Slaves willst du ansteuern, wie ist dein Aufbau, etc. Ich kann Dir dann meine Codebeispiele schicken. seventh_son@gmx.de
Datum: 03.12.2007 09:56
Ich suche im Forum seit Stunden nach so einem Beispiel in C ( =>negativ :-( ) Hat jemand vielleicht das Beispiel hier in C übersetzt? Kann jemand ähnliches Beispiel in C geben? Gruß Siem
Datum: 29.12.2007 01:27
@siem: was suchst DU denn genau?
Datum: 04.01.2008 22:04
@siem: Ich habe heute sowas hier in Codesammlung gestellt. Gruss Manni
Antwort schreiben
Die Angabe einer Email-Adresse ist freiwillig. Wenn Sie automatisch per Email über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.
Wichtige Regeln - erst lesen, dann posten!
- Suchfunktion und Betreffsuche benutzen - vielleicht gibt es schon einen ähnlichen Beitrag
- Aussagekräftigen Betreff wählen
- Im Betreff angeben um welchen Controllertyp es geht (AVR, PIC, ...)
- Groß- und Kleinschreibung verwenden
- Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang
- JPEG-Dateien (.jpg) nur für Fotos und Scans verwenden
- Schaltpläne, Screenshots usw. als PNG oder GIF anhängen
Formatierung (mehr Informationen...)
- [c]C-Code[/c]
- [avrasm]AVR-Assembler-Code[/avrasm]
- [pre]vorformatierter Text (z.B. Code in anderen Sprachen)[/pre]
- [math]Formel in LaTeX-Syntax[/math]
- [[Titel]] - Link zu Artikel