Moin moin,
ich befasse mich momentan mit dem TWI bus des ATMEGA32A, ich hab das
Datenblatt schon durch und auch den Forum Artikel, wirklich verstanden
habe ich es allerdings nicht.
Ich hab mir ne Libary hier aus dem Forum genommen und bin den Code Zeile
für zeile durchgegangen und habe versucht zu verstehen...
Dabei sind einige Fragen aufgekommen die Ich euch gerne Stellen würde.
Der Code Funktioniert an sich, (ich arbeite zur Zeit nur am Slave) Der
Master ist ein ARduino Mega2560 dort habe ich den Code Fix auf 50
gelegt, allerdings bekomme ich manchmal nahezu abwechselnd 100 oder 50,
bzw grade habe ich ihn auf 20 gelegt, manchmal bekomme ich 20, dann 40
und hin und wieder 100?! irgendwas liegt also noch nicht ganz grade...
Meine ganzen Verständnis Frqagen habe ich als Kommentar reingemacht...
Ich hoffe ihr könnt mir etwas helfen damit der "Knoten" platzt
Liebe Grüße und schonmal danke im Vorraus
Martin
So hier erstmal der Arduino Code
1
#include <Wire.h>
2
3
void setup()
4
{
5
Wire.begin();
6
}
7
8
byte x = 20;
9
10
void loop()
11
{
12
Wire.beginTransmission(50); // transmit to device #4
Martin Kathke schrieb:> // also in TWIS_ResonseType steht nun der Wert des TWSR> Registers,> // wenn ich es Richtig verstanden habe, sind die ersten 7 Bit> dort die Adresse,> // TWIS_ReadByte wurde ja mit 0x60 definiert, was Binär 1100> 000 heißt,> // Warum hab ich nur 7 Bit?! stimmt meine heximal rechner> nicht?> // aber ok die 2te eins sagt er soll lesen?! warum macht man> nicht einfach nur 01?
Hm, zitieren scheint hier ein wenig komisch zu sein, aber egal.
Doch doch, deine Hexadezimal Rechnung stimmt. Allerdings sagt die zweite
eins nicht dass er lesen soll. Soweit ich das richtig im Kopf habe sind
die ersten 7 Bits die Adresse, das achte Bit dann entweder eine 0 oder
1, welche jeweils aussagt ob gelesen oder geschrieben wird.
Martin Kathke schrieb:> // ansich war ich bisher der meinung wir übertragen Bit für Bit
Jain. In dem Sinne überträgt man immer nur Bit für Bit, allerdings sind
die meisten I2C Librarys so geschrieben dass man direkt ein Byte an die
Sendefunktion übertragen kann.
Martin Kathke schrieb:> Binär also 1010 1000 warum sind das jetzt 8 Bit? aber ich nehme mal an> es geht wieder nur um die 0 an zweiter stelle?!
Nein.
Bei TWI ist es üblich dass das erste Byte 7 Adressbits enthält und ein
Bit das Information dafüber leifert ob gelesen oder geschrieben wird.
Sämtliche Daten die danach folgen können als vollständige Bytes gewertet
werden, sprich, es werden in der Tat 8 Bits mit Informationen
übertragen.
Martin Kathke schrieb:> // Muss ich ihm nicht hier gleich aufm 9ten Bit auch sogan Hallo! ich> bin da (ACK) ?
Im das ACK musst du dich in der Regel nicht kümmern.
Martin Kathke schrieb:> WEnn ich das Richtig verstehe ist TWINT ja ein Interrupt, was so ähnlich> wie eine Clock ist.
Uff, nein. Interrupt mit einem Clock zu vergleichen ist falsch. Du musst
dir das so vorstellen:
Die meisten Programme sind Prozedual Programmiert. Sprich, der genaue
Ablauf vom Programm ist definiert (von oben nach unten).
Nehmen wir mal an, du hast noch irgendwelche Delays eingebaut und ein
kompletter Programmdurchlauf dauert mehrere Sekunden. In dieser Zeit
kann dein TWI Slave tausende von Bytes senden, welche beim uC komplett
verloren gingen. Da helfen nun die Interrupts.
Interrupts sind Programmunterbrechnungen. Sie werden durch bestimmte
Ereignisse ausgelösst (Beispielsweise dem Empfang eines Bytes per TWI).
Ist das der fall, dann springt der uC an eine definierte Stelle im
Programm, der ISR (interrupt Service Routine). Dies ist ein Programmteil
den du selbst schreiben kannst und der jedesmal aufgerufen wird, wenn
irgend ein Ereigniss einen Interrupt auslöst. Ist dieser Programmteil
durchlaufen, so geht der Controller wieder an den Punkt den Programms
zurück, indem er unterbrochen wurde.
Ein solcher Interrupt kann von diversen Quellen ausgelöst werden. Im
Grunde genommen ist es also nichts anderes als eine Art Unterbrechnung
des Hauptprogramms. Ohne Interrupts würde sogut wie kein Programm
funktionieren. Für eine etwas bessere Erklärung, Google sonst mal
danach. Da findet man tolle Erklärungen.
Auf die anderen deiner Fragen will ich nicht zusehr eingehen, da ich
eher mit PIC's als mit Atmel Arbeite und mich somit nicht sonderlich mit
den ganzen Registern usw. auskenne. Desweiteren möchte ich anmerken dass
ich mir bei meinen Antworten nicht zu 100 % sicher bin, allerdings denke
ich, so falsch sind sie nicht. Vielleicht korrigiert mich ja der ein
oder andere noch an einem Punkt.
Trotzdem hoffe ich, dass ich dir bereits ein bisschen helfen konnte.
Gruss
Martin Kathke schrieb:> // TWIS_ReadByte wurde ja mit 0x60 definiert, was Binär 1100 000 heißt,> // Warum hab ich nur 7 Bit?! stimmt meine heximal rechner nicht?> // aber ok die 2te eins sagt er soll lesen?! warum macht man> nicht einfach nur 01?
Weil die führende Null ausgeblendet wurde = 0xb0110 0000
Martin Kathke schrieb:> // selbes spiel wie oben, TWISlave_WriteBytes ist als 0xA8 definiert> // Binär also 1010 1000 warum sind das jetzt 8 Bit? aber ich> nehme mal an es geht wieder nur um die 0 an zweiter stelle?!
Ich glaube du hast die Reihenfolge der bits falsch verstanden
| bit7 | bit6 | bit5 | bit4 | bit3 | bit2 | bit1 | bit0 |
| ADRESSE | R/W |
San Lue schrieb:> Doch doch, deine Hexadezimal Rechnung stimmt. Allerdings sagt die zweite> eins nicht dass er lesen soll. Soweit ich das richtig im Kopf habe sind> die ersten 7 Bits die Adresse, das achte Bit dann entweder eine 0 oder> 1, welche jeweils aussagt ob gelesen oder geschrieben wird.Marc Vesely schrieb:> Ich glaube du hast die Reihenfolge der bits falsch verstanden>> | bit7 | bit6 | bit5 | bit4 | bit3 | bit2 | bit1 | bit0 |> | ADRESSE | R/W |
Danke, ja da habe ich falsch herum gedacht
aber warum vergleicht man dann nicht nur das 8te bit?
Wenn ich das jetzt richtig verstanden habe liegt ja dann im TWSR die
adresse + das lese / schreibe bit. Wenn dieser wert aus dem TWSR dann
mit einem fixen Wert verglichen wird, müsste der Fixe wert doch
eigentlich auch die Adresse enthalten?! sonst kann es ja eigentlich
nicht zu einer übereinstimmung kommen?!
San Lue schrieb:> Im das ACK musst du dich in der Regel nicht kümmern.
Ok, aber nur in diesem Fall oder? also beim ansprechen vom master an den
Slave richtig?
San Lue schrieb:> Uff, nein. Interrupt mit einem Clock zu vergleichen ist falsch. Du musst> dir das so vorstellen:
Danke für deine ausführliche erklärung wie ein Interrupt funktioniert,
das hatte ich allerdings schon verstanden, ich versteh nur diesen Bezug
auf das I²C nicht so ganz..
Momentan stell ich mir das so vor:
User löscht den twint, und gibt der hardware befehle wenn die hardware
die befehle durch hat setzt sie wieder den twint und man weiß das man
nun fortfahren kann...
Martin Kathke schrieb:> Danke für deine ausführliche erklärung wie ein Interrupt funktioniert,> das hatte ich allerdings schon verstanden
Genau das bezweifle ich ernsthaft, wenn ich folgendes lese:
Martin Kathke schrieb:> User löscht den twint, und gibt der hardware befehle wenn die hardware> die befehle durch hat setzt sie wieder den twint und man weiß das man> nun fortfahren kann...
Du verwechselst warten auf das Flag "twint" ohne Interrupts, und echte
Interrupt-programmierung, wo man sich um das Flag normalerweise gar
nicht kümmert...
Michael Reinelt schrieb:> Du verwechselst warten auf das Flag "twint" ohne Interrupts, und echte> Interrupt-programmierung, wo man sich um das Flag normalerweise gar> nicht kümmert...
Der Code ist doch ohne Interrupts?
Martin Kathke schrieb:> Der Code ist doch ohne Interrupts?
Ja, schon. Was aber vermutlich das problem ist.
Speziell bei TWI werde ich nie verstehen, warum alle zwanghaft
versuchen, das "zu Fuß" auszuprogrammieren. Es geht mit Interrupts echt
viel einfacher, weil einem der Interrupt schon die halbe State Machine
abnimmt (naja, die halbe ist vielleicht etwas optimistisch..)
Es gibt dazu zwei ANs von Atmel, 311 und 315, da ist das eigentlich sehr
gut erklärt.
Auch wenn I2C mit Interrupts anfangs etwas komplex aussieht: hast du das
einmal geblickt, hast du I2C am AVR ein für allemal begriffen. Wenn man
das dann noch sauber in eine "Library" (sprich: ein .c und .h-File)
packt, ist das einbinden von I2C in ein weiteres projekt eine Frage von
wenigen minuten.
Michael Reinelt schrieb:> Es gibt dazu zwei ANs von Atmel, 311 und 315, da ist das eigentlich sehr> gut erklärt.
würde ich mir sehr gerne anschauen,
Müsstest du mir aber bitte mal sagen was Ans bedeuted^^
ANs 311 Atmel führt bei google nämlich ins nichts :D
Michael Reinelt schrieb:> Speziell bei TWI werde ich nie verstehen, warum alle zwanghaft> versuchen, das "zu Fuß" auszuprogrammieren.
Software I2C ist bei vielen Leuten beliebt da sich so erstens jeder
Pegelwechsel im Debuggingmodus ganz einfach anzeigen lässt.
Ein zweiter "Vorteil" ist, dass die Pins frei wählbar sind.
Bin da aber der gleichen Meinung wie du, lieber Hardware Interface
benutzen, wenn es schon zur Verfügung steht.
Martin Kathke schrieb:> Michael Reinelt schrieb:>> Es gibt dazu zwei ANs von Atmel, 311 und 315, da ist das eigentlich sehr>> gut erklärt.>> würde ich mir sehr gerne anschauen,> Müsstest du mir aber bitte mal sagen was Ans bedeuted^^> ANs 311 Atmel führt bei google nämlich ins nichts :D
AN steht für "Application Note"
AVR311 und AVR315 findet Herr Google mit Sicherheit...
Michael Reinelt schrieb:> hast du das> einmal geblickt, hast du I2C am AVR ein für allemal begriffen.
genau das ist mein Problem, ich blicks noch nicht...
Michael Reinelt schrieb:> AN steht für "Application Note">> AVR311 und AVR315 findet Herr Google mit Sicherheit...
alles klar,
ja das da nen avr vorgehört war mir nicht ganz klar,
habs mit atmel probiert^^
ich werds mir mal durchlesen hoffentlich blick ichs dann!
Martin Kathke schrieb:> ich werds mir mal durchlesen hoffentlich blick ichs dann!
Habe dir meine Library drangehängt, allerdings sind die Routinen
zur Fehler- und Statusbehandlung nicht dabei - das ist ja
Anwenderspezifisch, aber du kannst das Prinzip erkennen - Dabla
durchlesen, entsprechend der Statusmeldung bestimmte Aktion vornehmen.
In der Library habe ich eine Bremse für defekte Chips eingebaut weil
der Status gepollt wird, keine ISR.
Und hier ein Beispiel wie du Daten aus DS1307 (RTC) auslesen kannst
;* Y-Reg ist Zeiger auf Parameter Stack
;* Y + 0 = Wieviele Bytes man einlesen will
;* Y + 1 = Startadresse im DS1307
;* Die gelesenen Bytes befinden sich im I2C_Buffer
DataFromDS1307:
rcall DoI2CStart
ldi r17, C_DS1307_w ;* DS1307 adresa
rcall I2cwbyte
ldd r17, Y+1 ;* Adresse
rcall I2cwbyte
rcall I2cstart
ldi r17, C_DS1307_r
rcall I2cwbyte
rcall DoI2CRead
ret
DoI2CStart: ldi zl, low(I2C_Buff)
ldi zh, high(I2C_Buff)
sts I2C_BuffPos, zl
sts I2C_BuffPos+1, zh
rcall I2cstart
ret
DoI2CRead: ldd r24, Y+0 ;* Wieviel
andi r24, 0x3F ;* Fur alle Fälle...
cpi r24, 0x02
brlo I2C_NACK ;* Wenn es nur 1 Byte ist, NACK senden und das
war's
dec r24
std Y+0, r24
rcall I2C_ACK ;* Byte einlesen, ACK senden ( für nächstes
Byte )
rjmp DoI2CRead
I2C_ACK: rcall I2crbyte_ACK
I2C_A1: lds xl, I2C_BuffPos ;* Zeiger auf momentane Position
lds xh, I2C_BuffPos+1
st X+, r17 ;* Empfangenes Byte schreiben
sts I2C_BuffPos, xl
sts I2C_BuffPos+1, xh ;* Neue Position merken
ret
I2C_NACK:
rcall I2crbyte_NACK
rcall I2C_A1
rcall I2cstop
ret
P.S. In der i2c_Lib habe ich in 'I2cstop' das prüfen auf TWINT
rausgeschmissen, kann natürlich wieder reingeschmissen werden...
P.P.S. Status bearbeitung fur Slave habe ich nicht, weil ich meine
chips nie als Slaven laufen lasse...
Marc Vesely schrieb:> Habe dir meine Library drangehängt
Danke dir,
ich kann nur Assembler leider nicht lesen, ich hab erst vor 2 Monaten
mit C und Microcontrollern angefangen, wenn ich die Zeit hab werd ich
das aber auch mal lernen... ;)
Martin Kathke schrieb:> Wenn ich das jetzt richtig verstanden habe liegt ja dann im TWSR die> adresse + das lese / schreibe bit. Wenn dieser wert aus dem TWSR dann> mit einem fixen Wert verglichen wird, müsste der Fixe wert doch> eigentlich auch die Adresse enthalten?! sonst kann es ja eigentlich> nicht zu einer übereinstimmung kommen?!
kann mir jmd das vielleicht noch beantworten?
Martin Kathke schrieb:> Martin Kathke schrieb:>> Wenn ich das jetzt richtig verstanden habe liegt ja dann im TWSR die>> adresse + das lese / schreibe bit. Wenn dieser wert aus dem TWSR dann>> mit einem fixen Wert verglichen wird, müsste der Fixe wert doch>> eigentlich auch die Adresse enthalten?! sonst kann es ja eigentlich>> nicht zu einer übereinstimmung kommen?!>> kann mir jmd das vielleicht noch beantworten?
Nein, weil Deine Annahme falsch ist.
Das TWSR ist das TWI Status Register. Da steht die Adresse nicht drin
(vgl. ATMEGA32A(L) DS (2503Q-AVR-02/11), Seite 178).
Wenn Du das TWAR Register meinst, da steht zwar die Slave Adresse in den
Bits 8..1 aber die hast DU als Programmierer da rein geschrieben, damit
der Baustein im Slave-Betrieb sich angesprochen fühlt.
Mit Bit 0 dieses Register enablest Du dann noch ggf. die "general call
address", d.h. der Baustein reagiert im Slave-Betrieb zusätzlich (!) auf
die I2C Adresse 0.
Grüße
Andreas
P.S.: RTFDS ;-)
A.
Martin Kathke schrieb:>> Wenn ich das jetzt richtig verstanden habe liegt ja dann im TWSR die>> adresse + das lese / schreibe bit. Wenn dieser wert aus dem TWSR dann>> mit einem fixen Wert verglichen wird, müsste der Fixe wert doch>> eigentlich auch die Adresse enthalten?! sonst kann es ja eigentlich>> nicht zu einer übereinstimmung kommen?!>> kann mir jmd das vielleicht noch beantworten?
Die Adresse steht im TWAR (falls du Slave bist), als Master sendest du
die Adresse des gewünschten Slave mit dem ersten byte (General Call
lassen wir mal außen vor), TWAR wird im Master-Betrieb nicht verwendet.
TWSR ist das Status Register, dazu gibts im Datenblatt eine wunderschöne
Tabelle was die einzelnen Werte bedeuten. Adresse findest du da drinnen
jedenfalls keine.
ich fürchte aber ich versteh deine Frage nicht wirklich :-)
Michael Reinelt schrieb:> TWSR ist das Status Register, dazu gibts im Datenblatt eine wunderschöne> Tabelle was die einzelnen Werte bedeuten. Adresse findest du da drinnen> jedenfalls keine.
Die habe ich grade entdeckt und werde die jetzt mal schritt für schritt
durchgehen, vielleicht bringt das ja endlich licht ins dunkle...
Ich melde mich nochmal
Grüße
und Danke euch ;)
Verstehe ich diese definierung richtig?
• Bit 3 – TWWC: TWI Write Collision Flag
The TWWC bit is set when attempting to write to the TWI Data Register –
TWDR when TWINT is low. This flag is
cleared by writing the TWDR Register when TWINT is high.
Kleiner auszug ausm Forum Artikel:
. TWDR kann nur aktualisiert werden, wenn TWINT gesetzt ist, andernfalls
kommt es zu einem Fehler, TWWC (TWI Write Collision Bit) wird gesetzt.
Um die Daten zu senden, muss TWINT erneut gelöscht werden.
Also Wenn ich etwas in TWDR Register schreiben möchte, muss ich zuerst
TWINT clearen, danach das TWWC Bit setzen und dann ins TWDR Register
schreiben,
Abschließend nochmal TWINT clearen, jetzt sollte er die Daten ins TWDR
Register übernommen haben und das TWWC Bit löscht sich durch das
abschließende TWINT clearen, richtig?
Dadurch das ich endlich die Register erklärung entdeckt habe, versteh
ich das ganze solangsam, (daran hats halt größtenteils gehackt, aber
wieder was gelernt im Datenblatt weiter runterscrollen hilft...^^)
Hat jmd eine simple Libary für TWI mit Interrupts die ich mir anschauen
könnte und durchgehen kann?
Die von Atmel hab ich mir bereits angeschaut aber die sind meinem
Programmierstil weit vorraus wodurch ich da ordentlich ausgebremst werde
um zu verstehen was da überhaupt passiert...^^
Daher wäre es super wenn jmd was für mich in C hätte ;)
Martin Kathke schrieb:> Hat jmd eine simple Libary für TWI mit Interrupts die ich mir anschauen> könnte und durchgehen kann?
Noch einfacher ?
Wohl kaum.
Sehe das mal so:
Was deine jetzige Library macht, ist polling, also Abfrage aus dem
Programm heraus. Wenn du mit der Operation fertig bist, prüfst du
TWSR register auf Status der Operation.
Mit ISR ist alles dasselbe, nur prüfst du TWSR am Anfang der ISR auf
Status, damit du überhaupt weisst, warum du in ISR gelandet bist.
TWI und SPI sind sehr einfach und übersichtlich, auch kann TWI mit
400KHz relativ schnell sein - kaum jemand arbeitet da mit ISR.
Da du aber unbedingt im Slave-Modus arbeiten willst, mag ISR die
bessere Lösung sein. Da es sich aber um 2 MEGAS handelt, ist SPI
viel besser für so etwas - schneller, nach dem Erkennungs Byte sogar
doppelt so schnell wie alles andere das auf die selbe Geschwindigkeit
deklariert ist.
Marc Vesely schrieb:> Da es sich aber um 2 MEGAS handelt
Das ist nur vorüber gehend, später sind es 1 master mega und 4 slaves,
aber danke dirwas du geschrieben hast, hat das ganze schon recht klar
gemacht