Hallo!
Hier ein funktionierendes Beispiel für einen I2C-Slave mit Hilfe des
USIs. Läuft auf attiny26 und attiny2313.
Vielleicht interessiert es ja jemanden...
Gruß
Axel Gartner
PS: Siehe auch: http://www.mikrocontroller.net/articles/USI
Hallo Alex!
Schön das du die so viel mühe gemacht hast. Das gleiche was du hier
gepostet hast, bschäftigt mich schon ein paar Wochen. Also vielen
Dank!
Jetzt wollte ich das Programm mal testen und compilieren .
Benutze das AVR Studio.....mit GCC!
Nun meine Frage:
Du linkst in den Programm zu keiner header datei oder ähnliches....!
Bei kompilieren bekomme ich fehler,
../main2.c:63: error: `PORT_USI_SCL' undeclared (first use in this
function)
und noch viele andere....!
´Falls du doch auf andere datein links......wäre es super wenn du diese
zur verfügung stellen könntest.
DANK IM VORRAUS
Dear Benno!
@Axel,
wenn man bestimmte Defines verlang, gehört es zum guten Ton, bei fehlen
dieser Defines mit #error einen entsprechenden Hinweis auszugeben.
Nach Monaten oder Jahren weißt Du sonst selbst nicht mehr, welche
Defines für welches Projekt mal benötigt wurden.
#if !defined(MODEL)
#error Modell nicht definiert!
#endif
Peter
Wunderbar das hat geklappt....!
Wenn ich jetzt mit einem Master folgendes sende
START
ADRESSE (0x20)
R/W
dann sollte doch der Slave den BUS auf LOW ziehen richtig?
Der slave zieht einmal beim Erkennen der Startbedingung und einmal beim
16-ten SCL Flankenwechsel die SCL Leitung runter. Nachdem der jeweilige
Interrupt abgearbeitet wurde, wird die SCL wieder freigegeben.
Axel
Hallo zusammen,
cih habe versucht, den Code auf meinem ATTiny26 zum Laufen zu bekommen.
Die Start-Condition erkennt der Controller auch noch und springt auch in
die ISR, arbeitet diese ab und springt wieder zurück. Allerdings bleiben
dann SCL und SDA low, was ja eigentlich nicht sein dürfte, oder? PullUps
sind überall drin. Als I2C-Master verwende ich gerade einen
RS232/I2C-Adapter der Firma IB-Hoch. Kann es ein, dass ich hier einfach
keinen Takt zur Verfügung habe und den selbst vom Slave aus generieren
sollte? Denn in diesem Falle kann es ja durch die Einstellung
USI_CONTROL |= (1<<USIWM1) | (1<<USIWM0) | (1<<USICS1);
(externer Clock) gar nicht gehen. Oder verstehe ich da was total
falsch? Wer hilft mir mit dieser Geschichte auf die Sprünge, denn ich
sehe gerade bei mir einfach den Fehler nicht....!
Vielen Dank mal soweit!
Dennis
Hi zusammen,
ich bin im Moment auch daran, einen ATtiny als I2C-Slave zu
programmieren, allerdings einen ATtiny45. Ich habe die defines
geändert, sodass die PINS und PORTS stimmen.
Allerdings weiss ich nicht ganz, wie ich das jetzt genau mit meinem
Programm verbinden kann. Ich möchte, wenn die Verbindung hergestellt
ist, irgendwelche Daten, die in einer Variabel gespeichert sind,
zurücksenden.
Wo genau kann ich so etwas denn in den Code einfügen?
Herzlichen Dank schon im Voraus,
Benedikt K.
Hallo,
habe versuch den Slave auf Tiny45 zu portieren (nur Pins verändert).
Wenn ISR ausgelöst wird, sollte eine LED angehen, aber nicht mal START
Condition wird erkannt :-o Nebenbei benutze ich auch die PWMs, ist aber
wohl egal.
Die ersten Zeilen habe ich so geändert:
/* Device dependant defines */
#define DDR_USI DDRB
#define PORT_USI PORTB
#define PIN_USI PINB
#define PORT_USI_SDA PORTB0
#define PORT_USI_SCL PORTB2
soll ja richtig sein, oder?
Jetzt schlage ich mich den ganzen Tag damit rum und sehe den Wald vor
lauter Bäumen nicht und bin kurz dran den ganzen Kram in Software zu
implementieren. Weis jemand Rat? Hat jemand vielleicht auch Probleme
damit gehabt und es auch nicht ging?
Als Master habe ich AVR Mega 8, auf dem Oszi ist Start Condition
wunderbar zusehen und die Implementierund des Masters funktioniert mit
anderen Sachen...
Mh...
Help
Gruß
Kest
Vielleicht nützt das ja jemandem. Ich hatte das mal geschrieben und
getestet (auf Tiny2313), es ist aber nicht produktiv im Einsatz, mag
also Macken haben. Orientiert sich auch an Atmels AN, arbeitet aber
Message-orientiert.
Hallo !
Beschäftige mich gerade mit dem Code von Axel Gartner ...
versuche das für codvision umzusetzen
meine frage ist nach dem die Startbedingung erkannt wurde und
erfolgreich das Adressbyte inklusive R oder W Bit eingelesen wurde, muß
doch der slave generell das acknow.Bit setzen oder???
d.h. SDA als Ausgang und auf low ziehen.
oder langt es den Pin nur als Ausgang zu schalten?
DDR_USI |= (1<<PORT_USI_SDA);
USI_STATUS = 0x0e;// reload counter for ACK, (SCL) high and back low
bzw. suche die stelle an der das Acknowlege (SDA->Low) gesetzt wird.
Vielleicht kann mir jemand einen Tip geben oder sagen ob ich falsch
liege!
Vielen dank!
Hallo,
ist zwar schon ein älterer Beitrag, aber für mich doch sehr aktuell :)
Ich beabsichtige gerade die Umsetzung bei einem Tiny261, dass das USI
zum I2C-Slave wird. Sendet halt keine ACK. Die Interruptroutine vom
Codevision-Wizard will auch net :)
Wurde das Problem schon mal gelöst für einen Tiny.
Wäre dankbar für Tipps und natürlich auch nen Bsp.-Code :)
Grüße
In der Tat. Alter Thread. Aber manche Threads wollen einfach nicht
sterben ... :)
Also. Dank A.K.'s Code habe ich jetzt mal was gesehen auf meinem
I2C-Bus.
Ich verwende einen ATtiny45 als Slave und den I2C-Tester aus dem
"ATM18-Projekt" als Master. Wenn ich jetzt mit dem (famosen) I2C-Sniff
von Peda auf dem Bus lausche, sehe ich, dass Bits verloren gehen, wenn
der Slave sendet. Ein anderer Slave (mit Hardware-I2C) geht problemlos,
das vom Master gesendete kommt auch an. Hat jemand einen Tip?
Mit dem DSO nachgemessen fällt mir auf, dass die Datenbits beim
"Master-Write" etwas nach den Clock-Bits enden (was mir ansich richtig
erscheint). Beim "Master-Read" (was ja wie erwähnt nicht ganz klappt)
enden sie aber schon in der frühen fallenden Flanke vom Clock-Bit.
Könnten meine Probleme damit etwas zu tun haben?
Ist jemand hier weiter?
Und gibt es eine funktionierende CodeVision-Portierung?
Grüße,
Christoph
Hallo...
hier findet ihr eine ausführlice Bibliothek für ein I2C / TWI Interface
mit dem AVR USI.
http://www.jtronics.de/elektronik-avr/lib-i2ctwi-mit-usi-interface.html
Die Biblitothek ermöglicht eine I2C/TWI Kommunikation über das USI
Interface von Atmel. Der verwendete Controller wird dabei als Slave in
dem Bussystem verwendet. Neben Controllern der Reihe ATTiny, wie dem
ATTiny2313, werden auch eine Reihe von anderen Controllern mit USI
Interface unterstützt.
Die Bibliothek ist so programmiert, dass der Slave wie ein I2C-Speicher
(I2C-Epprom) funktioniert.
unterstützt werden bisher folgende Controller:
ATtiny2313, ATtiny25, ATtiny45, ATtiny85, ATtiny26, ATtiny261,
ATtiny461, ATtiny861, ATmega165, ATmega325, ATmega3250, ATmega645,
ATmega6450, ATmega329, ATmega3290, ATmega169
Grüße Martin
http://www.jtronics.de
Info...
ich habe die datei nicht angehängt, da sie in Zunkunft noch weiter von
mir ausgbeaut wird. Damit jeder immer die neuste Version bekommt sollte
er die Lib von meiner Seite laden.
Genau so was hab ich gesucht!
Und im gegensatz zu allen anderen Codeschnipseln funktionierte die
Bibliothek gleich beim ersten Versuch.
Vielen Dank der Richard
Hallo, Ich hoffe das hier jemand ein offenes Ohr für mich hat. Ich hab
mir auch die Lib von Martin gezogen, doch ich kann auf keine Weise den
Attiny ansprechen. Der Test des Master-Codes mit einem externen EEPROM
funktioniert wunderbar, doch wenn ich den Attiny verwende, dann bleibt
der Master hängen. Vllt. könntet ihr mal über den Code schauen, ich hab
wahrscheinlich Tomaten auf den Augen, sitz auch schon seit 9 an der
ganzen sache :(
MfG
also
1.nimmst du überall die delays raus, so was macht man nicht, da der
controller in der zeit nur warten und die anderen aufgaben nicht machen
kann.
2. schreib die Adressen und Befehle bei TWI/I2C lieber binär, ist viel
übersichtlicher. Du erkennst eher Muster und meist hat jede Bit nummer
bei einem Befehl ihre Aufgabe.
3.so sollte das aussehen
Moin :D
@ Martin
Danke das du dir die Sachen mal angesehen hast, aber selbst mit deinem
Codeschnipsel funktioniert nix, da bleibt er mir bei Slaveadresse senden
hängen und ich bin mir eigentlich fast sicher das es am Slave liegt.
Kannst du dir das mal anschauen ?! Aber so viel kann man da ja ne falsch
machen, wahrscheinlich bin ich einfach nur zu doof dazu.
MfG
So habs grad nochmal aufgebaut atmega8 mit attiny2313
hab es erst mit dem internen quarz des attiny getestet, geht nicht.
hab einen quarz dran gemacht ... geht.
Der internen quarz der controller ist also zu ungenau.
Ist nix neues, steht ja schon ganz oft im forum.
Die Programme poste ich dir dann noch.
gruß martin
stop zurück, mit internem 8Mhz geht es auch... also jetzt gehts!
Warum es vorher nicht ging, keine ahnung.
hier die datei für den ATtiny2313 Slave bei 8Mhz
Unterstützt werden bisher folgende Controller:
ATtiny2313, ATtiny25, ATtiny45, ATtiny85, ATtiny26, ATtiny261,
ATtiny461, ATtiny861, ATmega165, ATmega325, ATmega3250, ATmega645,
ATmega6450, ATmega329, ATmega3290, ATmega169
deinen Controller musst du da mal noch selber implementieren ...
stell dann bitte das neue file hier hoch.
Hallo,
vielen Dank für die super schnelle Antwort.
Martin J. schrieb:> Unterstützt werden bisher folgende Controller:>> ... ATtiny25, ATtiny45, ATtiny85
Ich möchte das für attiny45 ja nutzen. Verstehe ich hier etwas falsch ?
kann man hiermit auch einen LM75 Temp. Sensor auslesen?
Oder geht das nur als Master?
Meine Hardware soll in etwa so aussehen:
LM75-->usi Attiny slave-->twi atmega master
Deine Struktur geht so nicht.
Der LM75 wird auch über I2C/TWI angesprochen, von daher kannst du den
auch gleich mit dem Mater auslesen.
Der Attiny hat außerdem nur einen Hardware TWI, bzw. nur ein USI
Interface.
Deine Skizze ist somit nur mit einem Software TWI umsetzbar.
Grüße Martin
Martin J. schrieb:> hier die korrigierte Version
Hallo Martin,
ich versuche momentan die Tiny45-Version zum laufen zu bekommen.
MASTER: ATMega1284P
SLAVES: PCF8563 RTC, DS2482-100 1-Wire Master, ATTiny45 (in EEPROM
Version) als DCF77 Controller
ATTiny45 -> 1MHz interner Takt aus 8MHz RC-Oszillator
Der Tiny funktioniert als DCF77 Slave anstandslos, synchronisiert ohne
Probleme und die Daten stimmen.
Die Uhr und auch der 1Wire Bus funktionieren mit den Treibern für den
ATMega1284 bereits seit mehr als einem Jahr im Dauerbetrieb fehlerfrei.
Sobald der ATTiny mit dabei ist, gibt es sporadische Aussetzer, und die
RTC und der 1Wire Master sind nicht mehr ansprechbar.
Der ATTiny45 meldet sich garnicht, bzw. erkennt seine Adresse nicht (mit
Debugger geprüft). Die empfangenen Werte im USIDR / USIBR entsprechen
nicht den übertragenen Adresswerten. Die empfangenen Adresswerte kommen
im System nicht vor, gehören also definitiv auch nicht zu den anderen
Slaves.
Nach Ausfall der Kommunikation wird per WDT-Reset die Kommunikation
wieder hergestellt, aber der Zyklus beginnt irgendwannn wieder, und
neben dem ATTiny funktionieren die anderen Slaves auch nicht mehr.
FRAGE: hast Du (oder ein anderer im Forum) einen ATTiny45 schon mit
anderen (echten Hardware)Slaves gemeinsam betrieben?
Gruß
Hallo.
klingt interessant was du da machst.
Leider kann ich dir grad nicht helfen.
Ich habe für ein Messsystem 2 Attiny 2313, 2 Atmega644 und 2 Maxim ADCs
an einem I2C Bus Betrieben. Die Attinys arbeiteten mit der hier
vorliegenden Library. Bisher konnte ich keine Fehler bzw. Probleme
finden.
Der Aufbau läuft jetzt schon seit Jahren ind verschiedenen Systemen
zuverlässig.
Momentan habe ich keinen ATTiny45 zu verfügung, sonst hätte ich es auch
mal getestet. VIelleicht kann dir daher jemand anderes helfen.
Grüße Martin
martin schrieb:> Die neuste version hast du aber?> siehe Beiträge weiter oben.>> eine noch neuere Version als die oben findest du hier:> http://www.jtronics.de/avr-projekte/library-i2c/twi-slave-mit-usi-avr
Ja, ich nutze die neueste Library. Ich habe auch bereits die ATTiny
Clock auf 8 MHz gesetzt, um die schnellste IRQ-Verarbeitung zu
ermöglichen. Außerdem nutze ich das USIBR anstatt USIDR um keine
Zeitprobleme bei 400kHz Masterclock zu bekommen. Bisher hat nichts
geholfen. Seltsam, daß der ATTiny die Kommunikation der anderen Slaves
stört .....
Wenn der Fall gelöst ist, melde ich mich wieder!
Grüße
Das wäre super, dann könnte im Fall eines Fehlers die Lib angepasst
werden oder anderen mit gleichem Problem hätten dann schnell eine
Lösung.
noch viel erfolg.
martin schrieb:> .... viel erfolg
Problem gelöst!
Der ATTiny kann trotz 8 MHz Taktfrequenz (ohne Teiler!) offensichtlich
keine 400kHz I2C Clock vertragen. Ich werde mir mal die vom C-Compiler
generierten Interrupt-Routinen anschauen. Im USIDR stehende Daten werden
wahrscheinlich bereits geshiftet, bevor die IRQ-Routine die Daten
einlesen kann. Allerdings bringt die Nutzung des USIBR keine
Verbesserung! Na mal sehen ...
Da es in meine Anwendung kein Problem ist, die I2C-Clock umzuschalten
kann ich ersteinmal weiterarbeiten. Weitere Infos folgen.
Gruß
interessant.
meine erfahrungen waren, dass du bei 16MHz CLock den I2C bis knapp über
900Khz takten kannst, was aber nicht zu empfehlen ist. Der Bus läuft
aber sicher bis zu 800 Khz.
grüße martin
Der Link
http://www.jtronics.de/elektronik-avr/lib-i2ctwi-mit-usi-interface.html
liefert mir eine eigenartige Fehlermeldung mit SeaMonkey 2.6:
>Umleitungsschleife>Limit für Umleitungen dieser URL überschritten. Die angeforderte Seite konnte
nicht geladen werden. Dies könnte von blockierten Cookies verursacht werden.
>Der Verbindungsversuch zur aufgerufenen Adresse wurde abgebrochen. Die >aufgerufene Website leitet die Anfrage so um, dass sie nie beendet werden >kann.>Haben Sie Cookies, die von dieser Website benötigt werden, deaktiviert oder >blockiert?>HINWEIS: Falls das Akzeptieren von Cookies die Probleme mit der aufgerufenen
Adresse nicht behebt, handelt es sich vermutlich um eine Fehlkonfiguration des
Servers und nicht um einen Fehler Ihres Computers.
Habe allerdings keine Cookies blockiert. Mein Browser akzeptiert alle
Cookies für diese Session.
Hallo
http://www.jtronics.de/avr-projekte.html?start=7
Der Link sollte funktionieren.
Ich habe ein anderes Problem:
Der Master ist mittels Hardware TWI auf einem Mega8 realisiert.
Ich schreibe ein Byte auf den controller, und möchte danach die
Übertragung beenden.
Das was passiert ist leider, das der ATTiny 24 mit seiner
USI-Schnittstelle den Bus blockiert, in dem er die SDA Leitung auf masse
behält.
Meine eigene implementierung mit read_nack am slave funktioniert leider
nicht.
der Master läuft mit 8MHz, ebenso der Slave (tiny)
Die gleiche Sache mit Hardware-TWI programmiert läuft einwandfrei.
Ich habe auch so das gefühl, das USI TWI ein deutlich größerer
Software-Aufwand ist als Software TWI
Auch normale i2c eeproms funktionieren problemlos
Nachtrag:
Ich hab es hinbekommen.
Ganz dummer Fehler, ich habe eine Code-Zeile auskommentiert gehabt, und
diese Codezeile hätte nicht auskommentiert werden dürfen.
hallo Martin,
ich habe mir die lib bei http://www.jtronics.de runtergeladen. Das
Problem was ich habe/hatte das ein I2C keinen richtigen ACK ausgeführt
hat bzw. den SCL nicht verzögert hat bis der IRQ dran ist. Bei meiner
Schaltung wird viel mit IRQ gemacht, darum ist nicht immer zeit sofort
auf den IRQ zu reagieren. Die Lib macht das im prinzip richtig (es
werden die richtigen Modes verwendet die auch ein SCL-hold auslösen. Das
können sie aber nur wenn die entsprechenden Bits auch low sind. Laut
Doku wir die SDA nur dann low gesetzt wenn diese auch im Port Low ist.
Durch das setzen des DDR's wird nur der Ausgang duchgeschaltet und das
Portbit an den Ausgang gelegt (attiny x4).
Damit das Funktioniert habe ich folgendes eingefügt:
1
ISR(USI_START_VECTOR)
2
{
3
overflowState=USI_SLAVE_CHECK_ADDRESS;// Set default starting conditions for new TWI package
4
DDR_USI&=~(1<<PORT_USI_SDA);// Set SDA as input
geändert zu
1
ISR(USI_START_VECTOR)
2
{
3
overflowState=USI_SLAVE_CHECK_ADDRESS;// Set default starting conditions for new TWI package
4
PORT_USI|=(1<<PORT_USI_SDA);// Set SDA high
5
DDR_USI&=~(1<<PORT_USI_SDA);// Set SDA as input
6
.....
und folgendes:
1
caseUSI_SLAVE_CHECK_ADDRESS:
2
if(USIDR==0||(USIDR&~1)==slaveAddress)// If adress is either 0 or own address
3
{
4
if(USIDR&0x01)
5
{
6
overflowState=USI_SLAVE_SEND_DATA;// Master Write Data Mode - Slave transmit
7
}
8
else
9
{
10
overflowState=USI_SLAVE_REQUEST_DATA;// Master Read Data Mode - Slave receive
11
buffer_adr=0xFF;// Buffer position undefined
12
}// end if
13
SET_USI_TO_SEND_ACK();
geändert zu:
1
caseUSI_SLAVE_CHECK_ADDRESS:
2
if(USIDR==0||(USIDR&~1)==slaveAddress)// If adress is either 0 or own address
3
{
4
if(USIDR&0x01)
5
{
6
overflowState=USI_SLAVE_SEND_DATA;// Master Write Data Mode - Slave transmit
7
}
8
else
9
{
10
overflowState=USI_SLAVE_REQUEST_DATA;// Master Read Data Mode - Slave receive
11
buffer_adr=0xFF;// Buffer position undefined
12
}// end if
13
PORT_USI&=~(1<<PORT_USI_SDA);// Set SDA high
14
SET_USI_TO_SEND_ACK();
bei mir funktioniert jetzt sowohl der ACK als auch die SCL-Verzögerung.
bye woodym
Hallo.
kannst du noch die Änderung als Datei hochstellen und vielleicht dem
Autor Bescheid geben, damit bei anderen nicht das gleiche passiert.
Grüße Tobi
hallo,
nach vielem Testen muß ich meine Änderungen wieder revidieren.
Bevor ich die Änderungen gemacht hatte, gab es kein ACK. Nach den
Änderungen war das dann perfekt.
Weil ich noch weitere Probleme versuche zu finden, habe ich die
Änderungen wieder rückgängig gemacht. Und siehe da, jetzt geht es auch
ohne diese Änderungen.
Das sind dann immer Situationen die einen verzweifeln lassen.
Was nun? Muß das nun oder nicht?
Noch habe ich das Prob das ab 200kHz die Daten nicht immer sauber
ankommen. Wobei es scheinbar kein Prob mit der geschwindigkeit zu sein
scheint, viel mehr mit dem Abstand zwischen den Protokollen.
Jetzt versuch ich erst mal zu verifizieren ob immer dann wenn es nicht
geht vielleicht ein andere IRQ ansteht.
Wenn die Lib richtig funktioniert, dann dürfte das jedoch keine Rolle
spielen weil der SCL beim Start und zum ACK so lange runter gehalten
wird.
Was seltsam ist, das nach einem Start sofort die Clocks kommen. ein
zweites Telegramm danach hat dann die verzögerung die ich aufgrund des
IRQ's erwarten würde.
bye woodym
Ja das sind die schönsten Fehler.
Ich bin schon gespannt was nun als Fazit da raus kommt.
Vor kurzem hatte ich auch so ein Problem mit dem I2C des Xmegas.
Nach ewigem Suchen hat es am Ende dann endlich funktioniert.
Der Fehler lag aber am Slave, dieser war konnte einfach nicht bei dem
Tempo mithalten.
Viel Erfolg noch bei deiner Suche
hallo tobi,
mein fazit... es funktioniert auch ihne die änderungen.
Warum es vorher nur mit den Änderungen funktionierte, kann ich nicht
sagen. Was verblüffend ist, das diesr kleine attiny doch so flott ist.
Mein Problem hatte nichts mit der Geschwindigkeit zu tun sondern mit
einem Positionsbuffer. Kurz umrissen was es werden soll/ist:
Ein kleines Board mit l293 (ja ich weiß, sehr betagt aber dafür sehr
unkomplizert) das einen kleinen Stepper antreiben soll. Mit auf dem
Board ein kleiner Attiny der im I2c-Mode positionen für den Stepper
entgegen nehmen kann oder im 2. mode einfach mit CLK und DIR
angesprochen werden kann. Da das ja nicht abendfüllend ist, kann per
Software auch der Stepper im Microschritt betrieben werden (4Step, 8Step
und 16Step). Und mit dieser Option (und der damit verbundenen
Rampenansteuerung) ist der Attiny schon etwas ausgelastet. Aber genau
das richtige um kleine Stepper ohne viel aufwand von Außen ansteuern zu
können.
Nun zum Fehler den ich hatte: wenn eine Position per I2C übertragen
wurde und der Stepper diese angefahren hat, sollte man eine weitere
Position schon übermitteln können damit es zu keinem 'Stottern' kommt.
Der Fehler war nun das das Locking zwischen IRQ-I2C Positionsübermittung
und Positionsabarbeitung nicht geklappt hatte.
Das habe ich schlicht weg umgangen indem ich einen Ringbuffer mit 32
Positionen eingebaut habe der einfach zu Locken ist (mit cli/sei). Der
I2C schreibt im IRQ rein und die Positionierung holt zwischen Cli und
Sei aus dem Buffer raus.
Jetzt muß nur noch das Optionale 'Fahre beim einschaltren die
Homeposition an) eingebaut werden und dann geht das ;-)
bye woodym
Hallo zusammen,
habe auf einem ATTiny2313 die USI-TWI Slave
http://www.jtronics.de/avr-projekte/library-i2c-twi-slave-usi.html zum
Laufen gebracht.
Soweit - sogut! Hat schön funktioniert, kann den 2313 über Raspberry PI
wunderbar ansteuern und auch abfragen.
Der 2313 ist bei mit 8 Mhz intern getaktet - kein CKDIV8 gesetzt.
Wenn ich nun zusätzlich den Timer0 im CTC Modus aktiviere, kann ich vom
Raspberri Pi nicht mehr den Slave ansprechen. Irgendetwas im Timing
scheint sich auf dem I2C Bus zu verändern.
Dabei arbeit in die Timer0 - Interrupt Routine (8bit) nur noch den
Befehl "uint8_t Zaehler++" ab.
Nun meine Frage zur Theorie: Eigentlich dachte ich, dass die Timer (bis
auf den Interrupt) keine Prozessor Zeit beanspruchen.
In der Interrupt Routine steht ja auch nur ein minimalistischer Befehl.
Der Interrupt und dieser Befehl können doch nicht so zeitkritisch sein
???
Kann mich da mal bitte ein Wissender aufklären, in welchen Konflikt ich
reinlaufe, bzw. wie ich die Thematik in den Griff kriege?
Sind TWI-Slave Impelementierungen auf einem Atmel so sensibel ?
Muss ich die Interrupts gegeneinander verriegeln, oder macht der
Prozessor dies eigenständig?
Danke im voraus!
Hallo Hendrik,
55 (DEZ) im Timer0 CompareRegister und Vorteiler 1:1 bedeutet:
alle 6,8 us einen Interrupt (1/8MHz * 55).
In der IRQ-Routine passiert ja noch (etwas) mehr als nur die Addition.
Der Interrupt hat eine höhere Priorität als die USI IRQ's, so dass für
das sensible Timing in der ACK/NAK Phase eventuell Probleme enstehen
können.
Soweit ich mich erinnere werden in der USI-Lib die IRQ Routinen nicht
als kritische Bereiche (CLI;SEI) höher priorisiert.
Teste das doch mal mit 255 = 31 us oder einfach mit einem höheren
Vorteiler.
Oder sperre die T0 IRQ's zum Test innerhalb der USI Interruptroutinen.
Gruß
Hallo Reiner,
habe mal den Gegentest gemacht:
1. Teiler auf 1024
2. OCR0A auf 250
3. Alle Abfragen in der Main Routine auskommentiert
4. Timer ISRs in den USI ISR Routinen gesperrt!!!
NO! geht definitiv nicht.
Gegentest ohne Timer ISR: Funzt!
Ich habe folgende Beobachtungen gemacht (mit Logicport)
Das ganze käuft unter 3,3 Volt (stabilisiert). Verändere ich den Trigger
Level im LogicPort von 0,5 Volt auf 1,2 Volt, liegen die interpretierten
Adressen (im LogicPort) schon mal daneben (anstelle x21 wird x42
interpretiert).
Das stellt für mich die I2C Schnittstelle des Raspberry PI mal
grundsätzlich hinsichtlich Robustheit (Flankensteilheit ?) in Frage -
Linux ist ja auch kein Echtzeitsystem - haben mir ja schon viele gesagt!
Ausserdem scheint mir die USI-Slave Implementierung bei 8Mhz in einem
2313 ebenfalls nicht so robust - oder positiv gesagt, filigran zu sein.
Habe noch einmal den Gegentest ohne Timer ISR gemacht - funzt.
Das Oszilloskop zeigt mir als Zeitdifferenz zwischen ACK und NAK ca. 3
-4 usec an. Das ist natürlich bedenklich wenig, wennn Interrupts
irgendeine Reaktion verhindern sollten. Nun ist ja ein ATTiny2313 ja
auch nicht ein "Präzsionsinstrument..." Schade um die bisher
investierte Zeit.
Einen letzten Versuch werde ich demnächts noch machen, indem ich einen
externen Quarz mit 16 Mhz anschliesse. Mal schaun, was passiert.
Gerüchteweise soll ja der interne weniger stabil sein - und doppelte
Taktfrquenz hilft vielleicht.
Ansonsten werde ich (sollte kein systematischer Fehler vorliegen) wohl
auf asynchrone Kommunikation umsteigen.
Danke im voraus (falls jemanden noch etwas einfallen sollte)
Hendrik L. schrieb:> Die entsprechenden ISR Slave Routinen sind bekannt
Nein.
Es hat keiner Lust, Deinen Code zusammen suchen zu müssen.
Weißt Du nicht, was ein "Dateianhang" ist und wie man ein Zip aus allen
nötigen *.c, *.h erzeugt?
Peter
Hallo Hendrik,
Du wirst ein Timing-Problem haben.
Wenn die Timer-ISR alle 55 Takte aufgerufen wird, dann bleibt dem
Programm keine Zeit noch andere Dinge zu tun.
Schau Dir mal das Assembler-Listing der ISR an.
Selbst wenn die Routine so klitzeklein aussieht, benötigt sie vermutlich
so an die 40-50 Takte für alle die push und pop Aktionen.
mögliche Abhilfe:
1. Maximalen CPU-Takt (20MHz)
2. ISR in Assembler schreiben
3. PWM-Takt reduzieren
Michael S.
Hallo Hendrik,
beim RasPI ist die Hardware I2C Schnittstelle schon o.k. ! Ich habe die
mit verschiedenen Slaves ohne Probleme im Betrieb. Es liegt wohl eher am
ATtiny. Die USI-Implementation macht bei mir bis 100 kHz keine Probleme,
danach treten sporadisch auf dem I2C-Bus Probleme auf (andere Slaves
'hängen' und blockieren den BUS), was auf Probleme mit dem USI Timing
deuten. Ist halt nur eine Notlösung.
Bei anderen ATMEL Typen mit Hardware I2C habe ich noch nie irgendwelche
Probleme bis 400 kHz gesehen!
Es gibt allerdings auch 14/20 Pin MCUs welche bis zu 1 MHz Clock als
Slave vertragen ;-) (mit 8 MHz interner Clock) Dazu gibts dann noch frei
einstellbare IRQ Prioritäten! Du solltest Dir eine MCU passend zur
Aufgabe suchen!
Gruß
Reiner Geiger schrieb:> das sensible Timing in der ACK/NAK Phase eventuell Probleme enstehen> können.
Nein.
Beim I2C ist nichts sensibel, alle Takte können beliebig lang sein. Der
I2C synchronisiert sich immer auf den langsamsten Teilnehmer.
Das ist ein riesen Vorteil gegenüber SPI, es können keine Daten verloren
gehen.
Natürlich muß der Slave das Clock Stretching einschalten und der Master
zum I2C-Standard konform sein, d.h. das SCL abfragen, bis es wieder high
ist.
Genau deshalb ist nämlich auch SCL open-drain und nicht nur SDA.
Peter
Hallo Reiner Geiger,
das Timing (bezogen auf den TWI-Takt) ist - im Gegensatz zur Seriellen
Schnittstelle - bei TWI völlig unkritisch:
Der SCL-Takt bzw. genaugenommen der Flankenwechsel dirigiert das
Konzert.
Das Timing (bezogen auf den Takt der CPU) ist das Problem.
Wenn der CPU nicht genügend Takte zur Abarbeitung ihres Jobs eingeräumt
werden (und dann womöglich gelegentlich noch ein Timer seine
Aufmerksamkeit fordert), dann kommt das System natürlich ins Humpeln.
Die USI-TWI-Routinen sind relativ lang, entsprechend lang ist auch die
Dauer der Bearbeitung - umsolänger, je niedriger der CPU-Takt.
Michael S.
Hallo Peter,
stimmt genau!
Leider wird bei der USI Implementation von I2C einiges mit Software
erledigt; das funktioniert eben nur mit passenden Kombinationen von I2C
Takt und MCU-Takt. Das gleiche Problem findet man ebenfalls wenn durch
Leitungskapazitäten eine kleine Verzögerung eintritt und das
Clock-Stretching knapp vom Master verpasst wird. Dann hilft nur eine
kleinere I2C taktrate. Deswegen gibt es mit der USI-Implementierung ab
100 kHz Probleme mit manchen Slaves ( z.B. ds2482-100 ).
Gruß
Peter Dannegger schrieb:> Hendrik L. schrieb:>> Die entsprechenden ISR Slave Routinen sind bekannt>> Nein.> Es hat keiner Lust, Deinen Code zusammen suchen zu müssen.> Weißt Du nicht, was ein "Dateianhang" ist und wie man ein Zip aus allen> nötigen *.c, *.h erzeugt?>>> Peter
Hallo Peter,
Der Rest ist gar nicht MEIN Code - sondern der von
http://www.jtronics.de/avr-projekte/library-i2c-twi-slave.html. Habe ich
oben schon gesagt.
Andere *.c und *.h Files (von mir) gibt es nicht, nur die jtronics!
In den jtronics Dateien habe ich auch nichts verändert - ich stelle
diesen Code auch nicht in Frage, ist er doch in allen relevanten Foren
empfohlen.
Gehe also davon aus, dass in den Basics die Lösung nicht zu suchen ist -
wenn, liegt der "Fehler" darin, dass die Timer0 ISR irgendwie das
Timing zu Lasten der USI ISR verändert - was ich aber nicht verstehe!
Ich habe zwischenzeitlich sogar auch den Code aus der Timer0 ISR
komplett entfernt!
ISR (TIMER0_COMPA_vect)
{
// PWM ++;
}
Ändert gar nichts! Nur wenn ich alles
// TCCR0A = (1<<WGM01); // CTC Modus
// TCCR0B |= (1<<CS02) | (1<<CS00); // Prescaler 1024
// OCR0A = 250;
// TIMSK |= (1<<OCIE0A);
auskommentiert habe, funzt die Kommunikation SICHER.
Zwischendurch bei eingeschaltetem Timer0 und ISR sporadisch ... - je
nach Kombination von PreScaler und OCRA0 - aber nicht zuverlässig, mal
ja mal
nein!
Mit Abschlußwiderständen 10kOhm habe ich auch schon gespielt - bringt
nichts.
Ein anderer Tiny 2313 - bringt nichts - Gegencheck - verhält sich
genauso.
Ein Check mit einem PCF 8574AP hat unter allen Betriebszuständen eine
saubere Adressierbarkeit mit dem Raspberry Pi ergeben.
Ich denke, ein ATTiny2313 mit 8 Mhz ist grenzwertg für eine 400 khz TWI-
Slave Software Implementierung - wobei ich mir das Phänomen "geht nicht
in Kombination mit Timer0 ISR" nun bei "leerer ISR" (siehe oben) nicht
mehr erklären - kann (mit meinem bescheidenen Halbwissen - in aller
Demut - daher meine Fragestellung an die Experten!).
Weiß jemand evtl., ob ich (und wie) den SCL Takt an der Raspberry PI I2C
Schnittstelle auf sagen wir mal 100 Khz runter bekomme ? 10khz würden
mir auch schon reichen!
Danke!
Hendrik L. schrieb:> Ein Check mit einem PCF 8574AP hat unter allen Betriebszuständen eine> saubere Adressierbarkeit mit dem Raspberry Pi ergeben.
Der PCF8574 ist kein MC, d.h. SCL ist nur Eingang, da auf dem PCF8574
kein Programm läuft und somit auf nichts gewartet werden muß.
Wenn der Raspberry Pi das Clock-Stretching nicht beachtet, ist das der
Grund, warum ein dummmer I2C-Chip funktioniert, aber ein MC nicht.
In diesem Fall braucht man für den Raspberry Pi einfach nur eine korrekt
implementierte I2C-Lib, damit man auch MCs als I2C-Slave ansprechen
kann.
Peter
Reiner Geiger schrieb:> Hendrik L. schrieb:>>>> Weiß jemand evtl., ob ich (und wie) den SCL Takt an der Raspberry PI I2C>> Schnittstelle auf sagen wir mal 100 Khz runter bekomme ? 10khz würden>> mir auch schon reichen!>>>> Danke!>> http://doc.byvac.com/index.php5?title=RPI_I2C>> ;-)
Hallo Reiner,
vielsten Dank - da steht es ja - RPI hat kein Clock Stretching!
Werde berichten!
Vielen Dank!
Soooo ...!
Nachdem ich wie angeregt die TWI Taktrate des RPI von 400 kHz auf ca. 66
kHz (gemessen) verringert habe, läuft die Koppelung nun stabil.
Es hatte zwar noch einige Hänger gegeben, aber aus irgendwelchen Gründen
läuft das System JETZT stabil (ohne Hänger). Irgendwie schon etwas
mysteriös.
Die PWM Addition und den restlichen Code habe ich wieder aktiviert, der
Prescaler ist nun ausgeschaltet - immer noch alles stabil!
Etliche Stunden investiert - ganz schön nervend.
Vielen Dank für Eure Hilfe!
Gruß
Nach 4 Stunden Weiterentwickung meines Programms und damit verbundenem
Testing unter allen "Betriebszuständen":
Kein einziger Ausfall mehr, selbst bei Erweiterung des Programm Codes in
der ISR-Timer0!
Damit ist für mich diese Master-Slave-Codierung robust. Dank an den
Ersteller des Programms.
Guten Rutsch an Alle!
Hallo zusammen,
leider funzt die obige Lösung 1 der I2C Bus Verlangsammung nur bei der
256 MB Raspberry Pi Variante (Version 1.0).
Bei der 512 MB Version (2.0) wurde die GPIO Belegung neu festgelegt,
I2C-0 wurde von der Stiftleiste genommen, stattdessen wurde I2C-1 dort
herausgeführt.
Die "schnelle Lösung" (Register Patch) funzt aber nur beim I2C-0, der
nun nicht mehr einfach über die Stiftleiste zugänglich ist.
Habe darum die in der Lösung 2 empfohlenen "Ersatz- I2C Routinen" neu
installiert - nach dieser Anleitung
http://doc.byvac.com/index.php5?title=RPI_I2C#Devices_requiring_Option1_or_2.
Sie hat zudem den Vorteil, dass man auf jede beliebige Pin Paarung einen
I2C Bus beim Raspberry Pi legen kann (also auch mehrere).
War nicht ganz einfach - aber wenn man der Anweisung exakt folgt, klappt
alles wunderbar.
Damit kann man im Master jede Busgeschwindigkeit einstellen. Und der
ATTINY2313 als Slave antwortet bei niedriger Geschwindigkeit wunderbar!
Gruß
Ist zwar schon älter, aber egal.
Ich versuche auch einen ATMega mit einem ATTiny4313 per TWI zu
verbinden. der ATMega sendet alle 100ms ein Signal (dabei geht er über
alle 40 Slaves, ob vorhanden oder nicht).
Sobald ich die Karte von dem Attiny einstecke, sind beide Datenleitungen
(SCL und SDA) auf 5V und der ATMega hängt sich auf. Woran kann das
liegen, bzw. was habt ihr besonderes eingestellt?
Lösen konnte ich das leider nicht (Attiny I2C mit USI war einfach nicht
stabil als Slave [Master: Atmega]). Habe aufgegeben und statt eines Tiny
einen Atmega mit TWI als Slave genommen.
Der Vollständigkeit halber:
bezüglich der jtronics library
(http://www.jtronics.de/avr-projekte/library-i2c-twi-slave-usi.html
Webseite verweist auf diesen Thread hier). Bei mir (und noch mindestens
einem anderen, zum Beispiel hier:
http://forum.arduino.cc/index.php?topic=160147.0 welcher eine Library
benutzt die ihrerseits auf der oben erwähnten usiTwiSlave library
aufbaut und das selbe Symptom zeigt) ist das Problem aufgetreten daß der
Slave nur mit Adressen < 64 zuverlässig funktionierte, insbesondere wenn
andere Interrupts auf dem Slave mit im Spiel waren und das clock
stretching direkt nach der Startbedingung erforderlich wurde.
Der Grund war die falsche Erkennung der Startbedingung: Direkt nach der
Startbedingung legt der Master das höchste Adressbit (im Falle von
Adressen zwischen 64 und 127 wäre das eine 1) auf SDA, gibt SCL frei und
wartet darauf dass der Slave ebenfalls SCL freigibt.
Der Slave muss nun im ISR(USI_START_VECTOR) ermitteln ob eine Start-
oder eine Stopbedingung vorliegt.
usiTwiSlave.c verwendet dazu irrtümlicherweise diese Zeile code
1
if(!(PIN_USI&(1<<PIN_USI_SDA)))
Und das kann nicht zuverlässig funktionieren, SDA ist zu diesem
Zeitpunkt undefiniert und wenn die Slave-Adresse > 63 ist dann ist die
Wahrscheinlichkeit hoch dass zu diesem Zeitpunkt SDA bereits high ist,
insbesondere wenn der Interrupt verzögert ausgelöst wird und der Slave
daher schon eine Weile auf der Taktleitung steht.
Der folgende Patch sollte das Problem beheben (bei mir tut er es,
seither rennt der Slave auf dem Tiny zuverlässig mit 400kHz ohne
jegliche Aussetzer):
Hallo,
ich möchte etliche ATTiny85 mit diesem Code nutzen.
Ich habe den letzten Beitrag mit dem Patch gelesen und habe daraufhin
von der jtronics Seite die V1.3 der Lib runtergeladen.
In dieser Version ist der Patch ja noch nicht implementiert.
Gibt es Bestätigungen oder Einwände bezüglich des Patches?
Hat es außer dem Entwickler des Patches jemand so am laufen?
Vielen Dank für Feedback...
MfG Dennis
Hallo,
dann einfach patch mit in den Code einbauen und fertig.
Daher wird auch auf diesen Thread hier verwiesen, damit man die neuste
Erkenntnisse selber ändern kann.
Grüße Martin
Dennis K. schrieb:> ...> Gibt es Bestätigungen oder Einwände bezüglich des Patches?> Hat es außer dem Entwickler des Patches jemand so am laufen?
Ja, und läuft mit allen Adressen ...
Ist eine Erweiterung auf 10bit interessant, wobei aber die Addresse
falsch
herum it, z.B. addr 0x250 => 0b1110IO0 0x50 -> 0xf4 0x50 => 0x50f4
als macro:
#define addr10bit(x) ((((x)&0xff)<<8|((x)&(0x300))>>7|0xf0)
Ich hätte gerne einen TWI-slave auf dem Tiny88 und bin nicht in der Lage
das selbst zu programmieren.
Die lib von jtronics scheint genau das zu sein was ich brauche, das
Eeprom-Imitat.
Das steht dann auch
/*######################################################################
########
Name : USI TWI Slave driver - I2C/TWI-EEPROM
Version : 1.3 - Stable
autor : Martin Junghans jtronics@gmx.de
page : www.jtronics.de
License : GNU General Public License
Update : 09.09.2011 - ATtiny24, ATtiny44, ATtiny88
allerdings geht es dann für den Tiny88 nicht weiter. Ich denke mal das
ist ein Schreibfehler und sollte heisse Tiny84?
Die SDA/SCL-Pins anzupassen ist ja kein Problem. Woran ich scheitere
sind die Interrupt-Vektoren. Der Tiny88 hat nur einen (Int20, TWI). Das
Beispiel benutzt aber 2 (USI_START und USI_OVERFLOW).
Das heisst wahrscheinlich, dass es ohne grössere "Umbauten" nicht geht?
Andere Baustelle. In diesem Thread geht es um AVR Controller ohne
halbwegs echtem I2C-Modul, bei dem das ziemlich bitweise über USI
implementiert wird. Der Tiny88 hat aber ein echtes I2C-Modul (aka TWI),
das nicht mit dem USI der anderen Tinys verwandt ist, sondern mit den
Megas wie Mega8 und Nachfolgern.