Forum: Mikrocontroller und Digitale Elektronik Immer noch TWI Ärger


von Sirko Pöhlmann (Gast)


Angehängte Dateien:

Lesenswert?

Hallo!
Hatte letztens schon mal gepostet...
Ich kämpfe vergeblich darum meinen Hardware TWI zum Laufen zu bekommen.
Ich verwende einen mega32 auf stk500 und als Slave einen EEPROM 24C64.

Ich hab einen Software TWI mit RTC erfolgreich am laufen, verzweifle
aber seit Tagen am Versuch den HardwareTWI mit dem Speicher zum Laufen
zu bekommen. Ich habe eine Codevorlage, aber es nützt nichts. Das
Programm läuft ohne Hänger durch aber wenn ich was schreibe und
rücklese bleibt das Ausgaberegister leer.
Möglicherweise liegt der Fehler gar nicht im Code sondern irgendwie am
drumherum. Leider reicht mein TWI Verständnis nicht um im größeren
Umfang zusätzliche Abfragen zu implementieren.

Im Hauptprogramm laufen nacheinander die Routinen

rcall H_TWI_WRITE ; EEPROM beschreiben
rcall H_TWI_READ ; vom EEPROM lesen

es gibt neben den Standardvereinbarungen folgende Vereinbarungen:

.equ HSCLP = 0
.equ HSDAP = 1
.equ TWIrd = 1
.equ TWIwr = 0
.equ EEPROM = 174 ; 1010 für EEPROM, 111x für individuelle
Geräteadresse (000 wird schon von der RTC belegt)

Der dazugehörige Code steht im Anhang.

Eventuell kann sich ja mal ein TWI Kenner der Sache erbarmen. Ich
durchblicke das zwar im Prinzip, aber nicht in der Tiefe. DANKE!

von Maddin (Gast)


Lesenswert?

Da die einzelnen Routinen anscheinend laufen,
könnte es ein Timing Fehler sein.

Zwischen einer Stop -> Start condition müssen bei 100kHz Devices
mindestens 4,7µS, und bei 400kHz Devices min 1,3µS liegen.
Das ist die 'Bus free time' (tBUF).

Probier es einfach mal mit einer 5µS Warteschleife zwischen
'rcall H_TWI_WRITE' und 'rcall H_TWI_READ'

Gruß,
Maddin

von Poe (Gast)


Lesenswert?

Hallo!

Ahja, ich hab mal ein kleines "rcall light" Led Flackeren von ein
paar ms dazwischengeschoben um zu sehen das das Programm auch da
durchmaschiert. Nützt aber nichts. Den  EEProm hab ich auch gleich mal
getauscht weil ich halt noch welche habe, war aber auch nicht der
Fehler.

Problem noch wie gehabt.

von Hagen (Gast)


Lesenswert?

Probiere die Deviceaddresse 000 für den EEPROM aus. Bei einigen I2C
EEPROM Herstellern kann man die Deviceadresse NICHT vorgeben, auch wenn
die 3 Pins A0,A1,A2 vorhanden sind. In den Datenblättern dieser
Hersteller gibt es KEINE Hinweise auf dieses Verhalten !!
Ansonsten schau mal hier rein
http://www.mikrocontroller.net/forum/read-4-81256.html , ist zwar für
WinAVR/GCC Assembler, könnte dir aber helfen.

Gruß Hagen

von Poe (Gast)


Lesenswert?

Hallo!

Der variable Teil der Deviceadresse besteht aus drei Pins am IC die auf
GND oder 5V gelegt werden können oder aber auch vom MC addressiert
werden können. Bei mir liegen sie alle auf 5V. Es sollte also ok sein
mit 1010111. das 1010000 kann ich nicht verwenden da nebenan eine RTC
läuft ( die läuft übrigens, im reinen Software TWI, ganz daneben bin
ich also nicht :-) ) die auch 1010 als festes Device hat. Ich habe
gerade mal den IC gegen einen von einem anderen Hersteller getauscht,
hat aber nix gebracht.
Gerade bei EEProms ist die variable Deviceadresse wegen mehr Speicher
doch aber besonders wichtig... hm. nur 000 ... ?
Wenn du trotzdem Bedenken hast ändere ich aber um!

Dein Code hab ich vorhin gerade gesehen, ehrlich gesagt bringt mich der
Mix und die Dichte aber über meine Grenzen. Ich kann so leidlich
Assembler....erkenne daher einige Routinen wieder aber könnte ihn nicht
zum Ausprobieren übernehmen.

Kannst du mal einen Blick auf die Stelle werfen wo in der Leseroutine
nach Anlegen der Adresse die Daten geholt werden? Ist das so koscher?

von Hagen (Gast)


Lesenswert?

Was mir am Source beim Überfliegen auffällt ist

clr r16
ldi r16, xyz

Du löschst r16 und gleich danach setzt du es auf einen Wert. Somit ist
das clr r16 sinnlos, du kannst das entfernen.

Mein Source ist nicht so kompliziert. Er besteht aus zwei Teilen
1.) HW-TWI Code, der die Funktionen fürs TWI implementiert.
Normalerweise kannste den 1 zu 1 übernehmen, musst dabei aber nur beim
i2cRead() und i2cWrite() beachten das die Input/Outputs in r20,r21
liegen.

2.) i2c EEPROM Routinen. Diese sind ein bischen komplizierter da sie
mit ganzen Speicherbereichen arbeiten und das Pageboundary der EEPROMs
berücksichtigt.

Wenn ich am Wochenende Zeit finde schreibe ich den Source mal um so das
er mit AVRStudio funktioniert.

Gruß Hagen

von Hagen (Gast)


Lesenswert?

Achso, Deviceaddress: Ich meinte nicht das du deine Hardware ändern
sollst, sondern wollte dich nur darauf hinweisen das es i2c EEPROMS
gibt die die an den Pins A0..A2 eingestellte Adresse einfach
ignorieren. Diese Chips arbeiten also NUR mit der Subadresse 000.

Gruß Hagen

von Poe (Gast)


Lesenswert?

Hallo!

ja das mit dem

clr r16
ldi r16, xyz

ist natürlich quatsch, ist weg..

Ich hab mal umgestellt auf 000 . Nützt aber nix. ( Also Pins auf GND
gelegt und Adresse auf EEPROM = 0b10100000

Ich will mal noch einen Test gemacht.

Der EEProm ist doch leer, also 0x00. In der Write Routine schreibe ich
ein 0x01,im anschließenden Rückesen bekomme ich aber 0x00.

Wenn ich jetzt zwischen Write und Read oder innerhalb von Read
"manuell" , also per ldi/lds in das TWDR Register schreib ... hmm
,mal sehen..

Ich schaue das ganze auch gerade mal mit nem Speicheroszi durch, hab
aber bisher keinen Fehler gefunden.

würde mich freuen wenn du weiter dran bleibst :-)

Das ist wieder irgendwelcher trivialer Mist, ich spüre es...

von thkais (Gast)


Lesenswert?

Wenn ein EEProm "leer" ist, ist es üblicherweise (nicht immer) mit $FF
gefüllt.
Wozu schickst Du in Deiner Leseroutine "ein leeres Datenpaket" ???
Was, oberflächlich gesehen, richtig erscheint, ist das Setzen der
Adresse und anschließend die repeated Start-Condition mit schreiben der
Device-Adresse und gesetztem R/W-Bit. Schau Dir im Datenblatt nochmal
den "Master Receive Mode" an, ich bin mir jetzt nicht ganz sicher,
aber ich meine, daß nach senden eines SLA+R das erste Datenbyte
automatisch von der TWI-Schnittstelle abgeholt wird. Ich muß in meinen
Sources mal rumkramen, allerdings ist das bei mir schon ein gutes Jahr
her und der Alzheimer knabbert an meinen Gehirnwindungen...
Ruf mal nur die Leseroutine auf, dann kannst Du auf dem Speicheroszi
mehr sehen.

von Sirko Pöhlmann (Gast)


Lesenswert?

Hi.

Wozu schickst Du in Deiner Leseroutine "ein leeres Datenpaket" ???

Ja das frag ich mich auch irgendwie. Das war so in dem Code von
bluemole hier aus dem Forum von dem ich  "abgeschrieben" habe.



Ich hab jetzt mal alles am Speicheroszi durchgesehen. Echt lustig. Es
müßte eigentlich funktionieren.

Sowohl die Lese wie auch die Schreibroutine laufen richtig ab. Laut
Speicheroszi lese ich exakt das ein was ich auch rausschreibe.
Inklusive   dem gesetzten 9 Bit hinten. Ich hab manchmal am Byteende
bei einigen Datenpaketen einen kurzen Peak auf der Datenleitung, aber
der ist nur ganz schmal und sollte nicht  gewertet werden.

Der Hammer ist das - obwohl ich die Adressen und Datenbytes eindeutig
auf dem Oszi sehe - scheinbar überhaupt nicht in das TWDR geschrieben
wird. Wenn ich nähmlich irgendwo im code, sagen wir zwischen der WRITE
und der READ Routine

ldi r16,0b0000011 ;(3)
sts  twdr,r16

einfüge sollte das ja gar nichts bewirken da in der folgenden READ
Routine das TWDR mehrmals für Adresse und Daten benutzt wird.
Am Ende der TWI Routinen, wenn ich das TWDR wieder lese und anzeigen
lasse steht da : TWDR = 3 . Wie zum Teufel ist das möglich??? Das ist
als ob ganz andere Register benutzt würden!

Ich kann dir auch ein Bild vom Oszi schicken wenn das was hilft.

von Uwe (Gast)


Lesenswert?

Hatte bei meinen TWI (Interruptgesteuert) das Problem das die
"Ansprechzeiten" des EEproms zu hoch waren.
Mach mal zwischen den einzelnen Schreib- Leseaufrufen ne Schleife
rein.
Hast Du das Ganze auch mal mit einem kleineren Eeprom (24C16) getestet
?

von Poe (Gast)


Lesenswert?

Schleife ist bereits drin, hat mir Hagen auch schon empfohlen.

Nein, mit ner anderen EEPROM Größe nicht nur mit anderem Hersteller.
Hab  auch schon auf anderem MC laufen lassen mege 323, aber es liegt
offensichtlich nicht am MC..

Laut Oszi ist ja auch alles in Butter ( siehe voeheriges Post...)
by Pö

von Sirko Pöhlmann (Gast)


Lesenswert?

Ök, ich möchte mich bei allen bedanken die mir helfen wollten. Zu guter
letzt hab ich den - trivialen, was sonst - Fehler doch noch selber
gefunden.

In dem ganzen räudigen Datenblatt steht mit keinem Wort unter TWI
nochmal der Hinweis das das TWDR nicht nur ein Register ist sondern ein
PORT. Ergo möchte jener mit IN gelesen werden und nicht mit LDS. Na ja,
ich weiß hätte ich den Code nicht nur abgeschrieben wäre ich eher drauf
gekommen. Jedenfalls fiel der Groschen als ich in der Ausgaberoutine las


OUT TWDR,r16

(mitdemKopfaufdenTischschlag)

by Pö

von thkais (Gast)


Lesenswert?

hmpf - das kenne ich. Solche Fehler können einem wirklich den ganzen Tag
versauen...
Das ist auch der Grund, weshalb ich zunächst selbst versuche, durch die
Hardware durchzusteigen. Oftmals brauche ich genauso lange, die Routinen
von jemand anders zu verstehen, wie sie selbst zu schreiben....
Hauptsache, es funktioniert.

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
Noch kein Account? Hier anmelden.