Hallo,
ich möchte mit dem ATtiny841 als I2C-Slave benutzen.
Dazu habe ich schon intensiv bei Google und Co. gesucht, bin aber nicht
fündig geworde. Einige I2C-Slave Beispiele konnte finden, die sind aber
für den ATtiny841 nicht geeignet.
Deshalb meine Frage:
Hat jemand ein simples Beispiel, Aplication Note oder Lib für den
ATtiny841/441 in C/GCC, um diesen als I2C-Slave zu betreiben?
Das Datenblatt hatte ich bereits gelesen, hilft mir aber nicht weiter,
da dort kein Beispiel enthalten ist. Die trockene Beschreibung der
Register und dessen Flags hat mir leider kein Licht aufgehen lassen, wie
ich das in C realisieren kann.
Ich habe konkret nach einen Beispiel in C gefragt, weil genau das mir
weiter helfen würde.
Ich Beschreibe mal das was ich mit den Tiny machen möchten etwas
detaillierter.
Der Tiny soll als Slave an einen I2C-Bus hängen.
Wenn er vom Master mit seiner 7-Bit Adresse ein Befehls Byte empfängt,
antwortet er mit 4 Bytes.
Ist eigendlich nichts kompliziertes, aber wenn man es zum ersten mal
macht, ist es erstmal doch ein wenig schwierig.
Ja, dem ATtiny841 hat Atmel wieder einen völlig anderen I2C-Controller
verpaßt. Wär ja sonst langweilig.
Wenns keine App-Note für den gibt, siehts schlecht aus.
Die ATtiny841/441 unterscheiden sich beim I2C/TWI-Bus von den anderen
Tinys, die Register unterscheiden sich aber erheblich und nicht nur von
der Bezeichnung her. Die 841/441 haben wohl ausschließlich einen
Hardware I2C-Slave Bus.
Ich habe das besagte Beispiel (AVR311
http://www.atmel.com/images/AVR311.zip) natürlich auch schon angesehen,
es läßt sich aber nicht so auf die ATtiny841/441 übertragen. Ich habe
dieses Beispiel sogar schon versucht mit Hilfe des Datenblatts zu
migrieren. Das scheitert aber daran das die 841/441 von der Steuerung
her anders sind.
Peter Dannegger schrieb:> Ja, dem ATtiny841 hat Atmel wieder einen völlig anderen I2C-Controller> verpaßt. Wär ja sonst langweilig.>> Wenns keine App-Note für den gibt, siehts schlecht aus.
Auf der Seite gibt es einiges mit I2C. Hatte nur das mit dem Slave
gepostet, weil die Frage danach kam.
Die hier schon probiert?
http://www.jtronics.de/avr-projekte/library-i2c-twi-slave-usi.html
Die ging bei mir auf Anhieb, allerdings mit nem anderen Tiny als Deinem,
aber vielleicht kannst Du sie ja passend machen, denn wenn der ATtiny841
die selbe Art von USI-Schnittstelle hat wie die ganzen anderen
unterstützten Controller (was ich vermute) wäre das der optimale
Ausgangspunkt.
Ja, funktoniert leider nicht steht aber auch
Zitat:
Unterstützt werden bisher folgende Controller:
ATtiny2313, ATtiny25, ATtiny45, ATtiny85, ATtiny26, ATtiny261,
ATtiny461, ATtiny861, ATmega165, ATmega325, ATmega3250, ATmega645,
ATmega6450, ATmega329, ATmega3290, ATmega169,ATtiny24, ATtiny44,
ATtiny88
Bei einen ATMega hab ich diese Lib auch schon benutzt, hat auch ohne
probleme geklappt.
Die tiny 441/881 sind wohl nicht kompatibel und werden auch nicht
explizit unterstützt.
Sehe gerade daß der 841 eine "richtige" I²C Hardware eingebaut hat,
genauso wie die Megas. Dann müsste es doch relativ einfach sein das
notfalls zu Fuß hinzubekommen, evtl auch mit Inspiration der
entsprechenden libs für irgendeinen Mega?
Ich habe jetzt mal mit Hilfe einiger Libs und Datenblatt diese
Funktionsweise hergeleitet. Leider ist irgendwo noch der Wurm trin.
Sieht vieleicht jemand, wo der Fehler sein könnte?
Ich habe einen Master Mikcrocontroller der das Byte 0x01 senden und vier
Bytes läd. Ich erhalte nicht 0x01 0x02 0x03 0x04 sondern 0xFF 0xFF 0xFF
0xFF.
Da an diesen Master noch ein weiterer I2C-Sensor Angeschlossen ist, der
auch funktioniert. Denke ich das der Master korrekt arbeitet.
Ich habe leider kein Oszi, sonst hätte ich mir die Pegel angesehen.
Oha, du brauchst wenigstens (oder besser noch) ein Logic Analyzer, sonst
wird das schwierig. Wie wäre es damit:
Beitrag "10 Euro Logikanalyzer"
Hilfreich wäre es noch wenn Du die genaue Abfolge, die Du per Master
sendest noch einmal aufschreiben könntest. Mit "Senden" und "Laden" kann
man als Außenstehender nicht viel anfangen. Also z.B. so
I2C-Start, Adr. 01, I2C-Restart, usw...
Zepp schrieb:> Ich habe einen Master Mikcrocontroller der das Byte 0x01 senden und vier> Bytes läd. Ich erhalte nicht 0x01 0x02 0x03 0x04 sondern 0xFF 0xFF 0xFF> 0xFF.> Da an diesen Master noch ein weiterer I2C-Sensor Angeschlossen ist, der> auch funktioniert. Denke ich das der Master korrekt arbeitet.> Ich habe leider kein Oszi, sonst hätte ich mir die Pegel angesehen.
Ich würde mir an deiner Stelle mal an den Tiny das Oszi des kleinen
Mannes ankabeln: ein paar LED.
Denn im Tiny stocherst du im Nebel und das muss sich ändern.
Du willst zb wissen, ob der Interrupt überhaupt ausgelöst wird. Eine LED
kann dir das verraten. Du willst wissen, ob du einen Dateninterrupt
kriegst. Wieder: Eine LED kann dir das verraten.
Ja, ich weiß. Es ist mühsam. Aber wenn man nichts anderes zum Debuggen
hat, dann muss das eben reichen.
Da hat Karl Heinz absolut recht. Hast Du vielleicht sonstige
Debug-Möglichkeiten, z.B. AVR Dragon mit Single-Wire Debug? Oder ist das
zum 841 noch nicht kompatibel?
Karl Heinz schrieb:> Ich würde mir an deiner Stelle mal an den Tiny das Oszi des kleinen> Mannes ankabeln: ein paar LED.>> Denn im Tiny stocherst du im Nebel und das muss sich ändern.> Du willst zb wissen, ob der Interrupt überhaupt ausgelöst wird. Eine LED> kann dir das verraten. Du willst wissen, ob du einen Dateninterrupt> kriegst. Wieder: Eine LED kann dir das verraten.>> Ja, ich weiß. Es ist mühsam. Aber wenn man nichts anderes zum Debuggen> hat, dann muss das eben reichen.
Gute Idee, aber leider sind schon alle Pins für die eigendliche Aufgabe
Sensoren belegt. Der Tiny hat ja nur wenige Pins.
Harald schrieb:> Da hat Karl Heinz absolut recht. Hast Du vielleicht sonstige> Debug-Möglichkeiten, z.B. AVR Dragon mit Single-Wire Debug? Oder ist das> zum 841 noch nicht kompatibel?
Zur Zeit habe ich nur den AVR ISP MKII, ich lege mir aber bald einen
Dragon zu.
Ich werde mir mal von einen Bekannten ein Oszi leihen gehen.
Harald schrieb:> Oha, du brauchst wenigstens (oder besser noch) ein Logic Analyzer, sonst> wird das schwierig. Wie wäre es damit:>> Beitrag "10 Euro Logikanalyzer">> Hilfreich wäre es noch wenn Du die genaue Abfolge, die Du per Master> sendest noch einmal aufschreiben könntest. Mit "Senden" und "Laden" kann> man als Außenstehender nicht viel anfangen. Also z.B. so>> I2C-Start, Adr. 01, I2C-Restart, usw...
Der Logikanalyzer sieht für den Preis wirklich sehr gut aus.
Mach das mal mit der LED berichte, ob Du überhaupt in den Interrupt
kommst. Und hast Du mal mit einem anderen Teilnehmer getestet, ob Dein
Master überhaupt korrekt arbeitet?
Harald schrieb:> Mach das mal mit der LED berichte, ob Du überhaupt in den Interrupt> kommst. Und hast Du mal mit einem anderen Teilnehmer getestet, ob Dein> Master überhaupt korrekt arbeitet?
Der Master arbeitet, ich habe da noch einen Temperatur Sensor und der
liefert korrekte Werte. Ich werde mir ein Ozi organisieren und irgenwie
eine LED tran basteln.
Zepp schrieb:> Gute Idee, aber leider sind schon alle Pins für die eigendliche Aufgabe> Sensoren belegt. Der Tiny hat ja nur wenige Pins.
Tja.
Du hast 2 Möglichkeiten.
Entweder du verschaffst dir eine Möglichkeit, wie du dem Tiny bei der
Arbeit zusehen kannst um rauszufinden was da abgeht.
Oder du stellst dich auf den Standpunkt "dich trifft keine Schuld, du
tust nichts und es geht eben nicht".
Nichts gegen ein Oszi. Aber was wirst du am Bus sehen? das der Tiny
keinen Acknowledge bringt. Das kann ich dir auch so sagen. Dazu brauchst
du kein Oszi.
Karl Heinz schrieb:> Zepp schrieb:>>> Gute Idee, aber leider sind schon alle Pins für die eigendliche Aufgabe>> Sensoren belegt. Der Tiny hat ja nur wenige Pins.>> Tja.> Du hast 2 Möglichkeiten.>> Entweder du verschaffst dir eine Möglichkeit, wie du dem Tiny bei der> Arbeit zusehen kannst um rauszufinden was da abgeht.> Oder du stellst dich auf den Standpunkt "dich trifft keine Schuld, du> tust nichts und es geht eben nicht".>> Nichts gegen ein Oszi. Aber was wirst du am Bus sehen? das der Tiny> keinen Acknowledge bringt. Das kann ich dir auch so sagen. Dazu brauchst> du kein Oszi.
Mein Problem dabei war halt, das ist schon alles fertig auf einer
Platine aufgelötet. Ich werde jetzt einen der Sensoren wieder heruter
löten, um an dessen Pads ein Paar LEDs tran machen können.
Ich war natürlich erstmal ein wenig gehemmt, da wieder Bauteile heruter
zu löten. Aber da hab ich wohl keine andere Wahl.
Ich habe es jetzt geschafft zwei LEDs anzubringen.
In der Interrupt Funktion sollte jetzt LED1 beim empfangen des Befehls
Byte eingeschaltet werden und LED2 beim senden der 4 Antwort Bytes.
Mein Master hat ein LCD-Bildschirm und Tatsatur, deshalb kann ich per
Tastendruck steuern wann der Master eine Anfrage zum Slave sendet.
Das Ergebnis ist LED2 leuchtet und LED1 nicht.
d.h das Befehls Byte (im Code ##1##) wurde nicht erkannt, aber warum?
Das Problem habe ich jetzt gelöst, der Master war nur ein bischen zu
schnell.
Ich habe beim Master, die Übertragunggeschwindigkeit ein bischen
reduziert und daraufhin klappt jetzt die Kommunikation zwischen Master
und Slave.
Ich danke allen, für die Hilfe und Tipps.
Das könnte sogar als Muster Beispiel für den ATtiny441/841 taugen,
ist aufs nötigste beschrängt und deshalb auch gut überschaubar.
Hallo Zepp,
Auch Dir ein frohes neues Jahr!
Danke für den Code, für dieses neue I2C Modul ist die Anzahl an
verfügbarem Code ja noch recht dünn.
Hast Du die Frequenz gesenkt oder die Zeit zwischen den Bytes erhöht?
Was hattest Du vorher und was nachher? Falls die Frequenz viel zu hoch
war könnten ja ein rein elektrisches Problem die Ursache gewesen sein.
Sollte der Slave den Master nicht eigentlich selbst auf das gerade eben
Nötige herunterbremsen können? Bei der lib für die anderen ATTiny
funktioniert das bei mir, da kann ich 400kHz takten und dann schön das
Wirken des Clock-Stretching auf dem Oszilloskop beobachten.
Bernd K. schrieb:> Sollte der Slave den Master nicht eigentlich selbst auf das gerade> eben> Nötige herunterbremsen können? Bei der lib für die anderen ATTiny> funktioniert das bei mir, da kann ich 400kHz takten und dann schön das> Wirken des Clock-Stretching auf dem Oszilloskop beobachten.
Mein Master hat eine Software I2C Schnittstelle, der Slave hingegen eine
Hardware I2C-Schnittstelle.
Ich gehe davon aus das dieses Beispiel noch Verbesserungspotenzial hat,
es ist aber auf jeden Fall schon mal eine funktionierende Grundlage.
Im Datenblatt ist z.B. beschieben, dass man via Flag zwischen Ack/Nack
umschalten kann. Register TWSCRB (TWI Slave Control Register B) Flag
TWAA (TWI Acknowledge Action). Ich habe dieses Flag nicht benutzt, da
bei mir keine Probleme daraus entstanden sind. Wenn man aber zwei
Hardware I2C-Schnittstellen hat, könnte dieses möglicherweise
erforderlich sein.
Wobei die Stop-Condition das problem mit dem fehlenden Nack eigendlich
beheben sollte.
Was mich noch etwas stutzig macht ist die Lösung mit der reinen
Zeitverzögerung zwischen den Bytes. Ob nun 2µs oder 20µs sollte
normalerweise keine Rolle spielen, so schnell ist der Controller ja
allemal. Genauere Analyse geht wahrscheinlich nur per Scope bzw. LA.
In den nächsten Wochen brauche ich ebenfalls eine I2C Implementation auf
einem ATTiny 841. Ich werde berichten.
Harald A. schrieb:> Was mich noch etwas stutzig macht ist die Lösung mit der reinen> Zeitverzögerung zwischen den Bytes. Ob nun 2µs oder 20µs sollte> normalerweise keine Rolle spielen, so schnell ist der Controller ja> allemal. Genauere Analyse geht wahrscheinlich nur per Scope bzw. LA.> In den nächsten Wochen brauche ich ebenfalls eine I2C Implementation auf> einem ATTiny 841. Ich werde berichten.
Das könnte auch irgendwo am Software I2C des Masters liegen. Mit einen
Hardware I2C-Master hätte man da sicher keine probleme. Das Bauteil ist
bei mir in SMD und es wurde leider nicht daran gedacht ein Paar Pads
einzufügen, damit man mal am I2C Bus mit nen Oszi schauen kann. Ich
hatte ein Oszi da, aber habe es dann leider doch nicht benutz, weil es
zu knifflich war mit den SMD Bauteilen. Jetzt habe ich das Oszi schon
wieder abgegeben. Wegen der Geschwindigkeit, beide Micocontroller
(Msster/Slave) haben einen 14 Mhz Quwarz.
Hiermal mal ein Auszug vom Master, und was ich da geändert habe, ist nur
der Wert in der Funktion I2CM_Delay().
Vorher habe ich 0xFFFFFFFF empfangen und nach der Änderung den
erwarteten Testwert.
Zepp schrieb:> Mein Master hat eine Software I2C Schnittstelle
Wenn Du den Quellcode des Masters hast, würde ich doch besser das
Rücklesen der SCL-Leitung einbauen.
Die darf dann natürlich nicht mehr als push/pull konfiguriert sein,
sondern als open-drain (wie ja SDA auch).
Peter Dannegger schrieb:> Zepp schrieb:>> Mein Master hat eine Software I2C Schnittstelle>> Wenn Du den Quellcode des Masters hast, würde ich doch besser das> Rücklesen der SCL-Leitung einbauen.> Die darf dann natürlich nicht mehr als push/pull konfiguriert sein,> sondern als open-drain (wie ja SDA auch).
Wie sieht denn Dein SCL_HI() Makro aus?
Hoffentlich nicht
1
DDRx&=~SCL_BIT;
sondern stattdessen so:
1
DDRx&=~SCL_BIT;
2
while(!(PINx&SCL_BIT));// wait for slave to release SCL (clock stretching!)
[Edit] Sorry, ging an falschen Adressaten, Frage bleibt aber bestehen.
Bernd K. schrieb:> Wie sieht denn Dein SCL_HI() Makro aus?>> Hoffentlich nichtDDRx &= ~SCL_BIT;>> sondern stattdessen so:DDRx &= ~SCL_BIT;> while (!(PINx & SCL_BIT)); // wait for slave to release SCL (clock> stretching!)>> [Edit] Sorry, ging an falschen Adressaten, Frage bleibt aber bestehen.
Hallo Bernd K.,
der Master ist nicht von mir, ich habe den Quellcode dazu so bekommen.
Den werde ich noch überarbeiten müssen. Der aktuelle Master Code scheint
auf die bestehnden Slave und deren Geschwindigkeit angepasst zu sein,
das ist natürlich kein richtiges I2C.
Die Kommunikationsprobleme, sind wohl genau darauf zurück zu führen.
Obiges basiert auf der Annahme dass konsequenterweise SCLPIN das
input-Register für diesen Pin ist wenn der Autor dieses Codes halbwegs
konsequent war in seiner Namensgebung, notfalls entsprechend anpassen.
Wenn der Master die SCL-Leitung loslässt dann MUSS er warten bis sie
auch tatsächlich auf high geht, denn ein Slave kann jederzeit selbst
diese Leitung auf low ziehen um den Master zu bremsen, jederzeit und so
lange er will. Der Master muss an diesem Punkt innehalten und darf auf
gar keinen Fall weitermachen bevor die Leitung auf high geht.