mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik AVR Studio - TWI-Register können nicht gelesen/geschrieben werden


Autor: L. K. (ladde)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

habe folgendes Problem bei meinen ersten Versuchen mit TWI / I²C:
Benutzte AVR Studio (aktuellste Version) und kann nicht auf die 
TWI-Register (TWBR, TWSR, TWCR, TWDR) mit in / out zugreifen; der 
Assembler gibt immer den Fehler "Operand out of range" aus.
µC ist ein ATMega644P-20PU.

Habe die Assembler Routinen aus einem altem Thread 
(Beitrag "AVR-TWI-ASM EEPROM Ansteuerung") von Bastler (Gast) für mich 
ein wenig angepasst, hier meine Datei twi-routines.asm:
;
; Two-Wire-Interface Routinen
;


;Initialisierung
twi_init:
  ldi temp1, 0x32    
  out TWBR, temp1
  ldi temp1, 0x01    
  out TWSR, temp1


; Start senden

twi_start:
  ldi temp1,(1<<TWINT)|(1<<TWSTA)|(1<<TWEN)
  out TWCR,temp1    ;Start Condition senden
twi100:
  in temp1,TWCR    ;Status holen
  sbrs temp1,TWINT  ;Kommando ausgeführt?
  rjmp twi100    ;nein -> warten
  ret


; TWI Write
; Zu sendendes Byte in temp1

twi_write:
  out TWDR,temp1    ;Byte in Ausgaberegister
  ldi temp1,(1<<TWINT)|(1<<TWEN)
  out TWCR,temp1    ;Byte senden
  rjmp twi100    ;Warten bis ausgeführt


; TWI Read mit Ack.
; Empfangenes Byte in temp1

twi_read:
  ldi temp1,(1<<TWINT)|(1<<TWEA)|(1<<TWEN)
  out TWCR,temp1    ;Flags setzen
twi200:
  in temp1,TWCR    ;Status holen
  sbrs temp1,TWINT  ;Kommando ausgeführt?
  rjmp twi200    ;nein -> warten
  in temp1,TWDR    ;Daten sind da
  ret


; TWI Read ohne Ack.
; Empfangenes Byte in temp1

twi_readna:
  ldi temp1,(1<<TWINT)|(1<<TWEN)|(0<<TWEA)
  out TWCR,temp1    ;Flags setzen
twi201:
  in temp1,TWCR    ;Status holen
  sbrs temp1,TWINT  ;Kommando ausgeführt?
  rjmp twi201    ;nein -> warten
  in temp1,TWDR    ;Daten sind da
  ret


; TWI Stop Condition

twi_stop:
  ldi temp1,(1<<TWINT)|(1<<TWSTO)|(1<<TWEN)
  out TWCR,temp1    ;Stop Condition senden
  rjmp twi100    ;Warten bis ausgeführt
Der Assembler meckert z.B. bei "out TWBR, temp1" mit folgendem Text:
error: Operand 1 out of range: 0xb8

0xb8 stimmt mit der Position von TWBR aus m644Pdef.inc überein.

Mach ich einen Fehler oder AVR Studio?

Autor: L. K. (ladde)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Edit: Habe gerade die Lösung des Problems gefunden (glaube ich 
zumindest).

>Alle Register, deren SRAM-Adresse größer ist als 0x3f(->SREG), können
>nicht mehr mit  den ASM-Befehlen IN und OUT angesprochen werden und
>haben folglich keine IO-Adresse.

Also muss ich anscheinend mit LDS und STS statt IN / OUT auf die 
Register zugreifen; mal sehen, ob das funktioniert.

Autor: spess53 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi


>Der Assembler meckert z.B. bei "out TWBR, temp1" mit folgendem Text:
>error: Operand 1 out of range: 0xb8

Du must 'sts TWBR, temp1' benutzen. Und beim Lesen 'lds ....'. Die 
Register sind mit 'in/out' nicht erreichbar.

MfG Spess

Autor: L. K. (ladde)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
danke für die Antwort.
Der Assembler meckert jetzt nicht mehr, aber der Buszugriff scheint noch 
nicht richtig zu funktionieren.
Ich habe einen DS1337 (RTC) an den AVR gehängt und versuche erstmal, 
dessen Statusregister auszulesen:

rcall twi_init     ; TWI Initialisieren

rcall twi_start    ; Start-Condition setzen

ldi temp1, 0xD0    ; Schreibzugriff auf DS1337 (Adresse ist 1101000)
rcall twi_write

ldi temp1, 0x0E    ; Statusregister anwählen
rcall twi_write

rcall twi_start    ; Repeated Start

ldi temp1, 0xD1    ; DS1337 lesen
rcall twi_write

rcall twi_readna   ; Statusregister lesen (kein ACK, da nur ein Byte gelesen werden soll)

rcall twi_stop     ; Transfer beenden
Das Programm hängt beim ersten twi_read. Das Interrupt-Flag im 
Control-Register wird nicht gesetzt; bis auf das TWI Enable Bit sind 
alle Werte des Registers 0, SCL steht auf LOW-Pegel.
Habe schon diverse Busgeschwindigkeiten durchprobiert, aber ohne Erfolg.
Kann es sein, dass der DS1337 nicht reagiert (kein ACK sendet)?
Wie kann ich feststellen, ob er überhaupt aktiv ist und am Bus horcht?

Danke+Gruß
Ladde

Autor: spess53 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi

>Das Programm hängt beim ersten twi_read.

Und wo ist das in deinem Programmteil?

MfG Spess

Autor: L. K. (ladde)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Upps, verschrieben...
Sollte twi_write heißen.
Das Programm hängt also im ersten twi_write fest:
rcall twi_init     ; TWI Initialisieren

rcall twi_start    ; Start-Condition setzen

ldi temp1, 0xD0    ; Schreibzugriff auf DS1337 (Adresse ist 1101000)
rcall twi_write

Autor: gtf (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo  Ladde,
schau mal die Beispiele aus der Codesammlung an, mir konnten die 
weiterhelfen.
Beitrag "TWI / I2C einf. MASTER SLAVE Beispiel(Assembler) ATmega8"

Autor: L. K. (ladde)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo gtf,
da hatte ich schonmal flüchtig drüber geguckt, fand das ganze aber etwas 
unübersichtlich und hatte deshalb die Routinen von Bastler aus 
Beitrag "AVR-TWI-ASM EEPROM Ansteuerung" verwendet. Laut dem DS1337 
Datenblatt http://datasheets.maxim-ic.com/en/ds/DS1337-DS1337C.pdf 
sollten sich die Register ja einfach lesen lassen (Seite 13/14).
Das Problem scheint aber grundlegender zu sein. Ich erhalte genau den 
gleichen Fehler (Programm hängt, da TWCR = 0x04) wenn die RTC gar nicht 
am Bus hängt.
Werde mir morgen nochmal deinen Link und etwas TWI-Grundlagen angucken, 
hoffentlich komme ich dann auf den Fehler.

Gute Nacht
Ladde

Autor: L. K. (ladde)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Mal ne andere Frage: Da das Code-Beispiel im Datenblatt offsichtlich 
fehlerhaft ist (Registerzugriff mit in / out), könnte man Atmel ja mal 
darauf hinweisen. Weiß da wer ne Email-Adresse / Formular?

Autor: MWS (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Da das Code-Beispiel im Datenblatt offsichtlich fehlerhaft ist...

Das Code-Beispiel ist nicht fehlerhaft, nur benutzt Du einen AVR Typ, 
dessen TWI Register oberhalb des IO Bereiches bis 0x3F liegen, In/Out 
ist laut Instruction Set nur bis 0x3F zulässig.

Bei anderen Typen, beispielsweise ATM32 liegen die TWI Register dagegen 
bei 0x20-23.

Da musst Du schon selber mitdenken, das Instruction Set genau lesen und 
das Code-Beispiel halt entsprechend anpassen.

> könnte man Atmel ja mal darauf hinweisen.
Dann mach das mal, dann haben die bei Atmel gleich ein wenig Spass :D

Autor: L. K. (ladde)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Mir ist schon klar, dass Atmel den Code wohl nur einmal für alle 
Controller(familien) geschrieben hat, und dass er für viele korrekt ist. 
Das ändert aber nichts daran, dass der Code, der im Datenblatt für diese 
Controllerfamilie steht fehlerhaft ist.
Im gleichen Datenblatt steht ja auch die Registerübersicht mit der 
entsprechenden Adresse im SRAM-Bereich.

Wenn man sich am Datenblatt orientiert (wie oft hört bzw. liest man 
schließlich "steht doch im Datenblatt"), werden einem hier echte 
Stolpersteine in den Weg gelegt.

Habe mich mal über das Technical Support Formular an Atmel gewandt, mal 
sehen, ob die darauf reagieren.

Grüße
Ladde

Autor: MWS (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Wenn man sich am Datenblatt orientiert (wie oft hört bzw. liest man
> schließlich "steht doch im Datenblatt"), werden einem hier echte
> Stolpersteine in den Weg gelegt.

Das ist ein typischer Anfängerfehler, jeder der sich nur ein wenig in 
die Materie eingearbeitet hat und mit Assembler arbeitet, weis was er zu 
tun hat.

Programmieren ist nicht copy/paste und hat etwas mit Mitdenken zu tun, 
also In/Out Befehl anschauen, Adresse des TWI Interfaces anschauen und 
feststellen, daß es so nicht geht. Wenn Dir das zuviel ist, nimm eine 
Hochsprache, da sucht der Compiler die passenden Befehle für Dich raus.

Zumindest ich denke nicht, daß Atmel jeden kleinen Pups für den 
Programmierer erledigen, also Standardbeispiele auf die jeweiligen 
Controller anpassen muss.

Solche Kleinigkeiten kann man vom Programmierer erwarten.

Autor: L. K. (ladde)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Das ist ein typischer Anfängerfehler, jeder der sich nur ein wenig in
>die Materie eingearbeitet hat und mit Assembler arbeitet, weis was er zu
>tun hat.

Es mag pedantisch sein, aber gerade als Anfänger erwarte ich doch 
konsitente Informationen im Datenblatt als wichtigste 
Informationsquelle.
Für zukünfitge Projekte weiß ich jetzt, wo der Fehler lag und wie ich 
auf Register korrekt zugreife, habe hier ja schnell die passenden Infos 
bekommen.

>Programmieren ist nicht copy/paste und hat etwas mit Mitdenken zu tun,
>also In/Out Befehl anschauen, Adresse des TWI Interfaces anschauen und
>feststellen, daß es so nicht geht. Wenn Dir das zuviel ist, nimm eine
>Hochsprache, da sucht der Compiler die passenden Befehle für Dich raus.

Ich hatte ja auch gar nicht den Code aus dem Datenblatt kopiert, sondern 
die Routinen, die ich an anderer Stelle im Forum gefunden hatte, 
nachvollzogen und an mein Projekt angepasst. Da dabei ein Fehler auftrat 
habe ich eben zunächst mit dem Datenblatt abgeeglichen. Da ich anhand 
des TWI-Abschnittes den Fehler nicht klären konnte, habe ich hier im 
Forum gepostet und gesucht.
Ich denke daher, dass dein Kommentar, der mangelnden Einssatz 
meinerseits nahelegt, unangebracht ist.

>Zumindest ich denke nicht, daß Atmel jeden kleinen Pups für den
>Programmierer erledigen, also Standardbeispiele auf die jeweiligen
>Controller anpassen muss.

Es geht mir - wie beschrieben - nicht darum, fertige Code-Segmente von 
Atmel zu bekommen ("jeden kleinen Pups") sondern darum, dass die 
Dokumentation möglichst keine Fehler enthält (eben auch kleine).
Mag pedantisch erscheinen, aber wenn schon ein Code-Beispiel dabei ist, 
dann sollte es meiner Meinung nach auch in sich stimmig sein.

Grüße
Ladde

Autor: MWS (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Ich denke daher, dass dein Kommentar, der mangelnden Einssatz
> meinerseits nahelegt, unangebracht ist.

Da ist nix unangebracht, Du hast Deine Hausfagaben einfach nicht gut 
genug gemacht, denn Du kannst Beides nachschauen, im Instruction Set Pdf 
findest Du:
OUT A,Rr 0 ... 0 ≤ A ≤ 63
A steht für den I/O Adressbereich

Im ATM644 DB:
(0xBD) TWAMR
(0xBC) TWCR
(0xBB) TWDR
(0xBA) TWAR
(0xB9) TWSR
(0xB8) TWBR

Dann solltest Du noch verstanden haben daß ≤ 63 die dezimale Notation 
für 0x3F ist und schon hast Du alle benötigte Information. Du bist doch 
auch in der Lage ein "2-wire Serial Interface", wie im ATM644 DB 
angegeben, als "I2C" zu identifizieren, warum so borniert hier ?

Kann's nicht eher sein, daß Dich der gemachte Fehler aufgrund eigener 
mangelnder Kenntnisse so aufregt, so daß Du nun einen Schuldigen für 
Deine Unkenntnis suchst ?

Nochmal: Ich persönlich erwarte, daß ein Programmierer solch einfache 
Dinge selbst anzupassen versteht. Wenn bereits so 'ne Kleinigkeit Dir 
Probleme bereitet, so daß Du nach dem Support rufen musst, dann wird das 
noch eine ziemlich interessante Programmiererkarriere :D

Autor: gtf (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@ ladde,
Ist nichts neues, das mal im Datenblatt was fehlt. Atmels AVR 
Datenblätter find ich sogar sehr gut beschrieben. Schau doch mal ins DS 
von RFM12 :- )
Oder guck mal ein XMEGA Datenblatt an, da gibt’s gar keine Beispiele. 
Und die Registernamen haben’s auch in sich.

Geheimtipp:
;******************************************
AVR315: Using the TWI module as I2C master
        Alternative für Slave
AVR311: Using the TWI module as I2C slave
;******************************************
Du musst nur die Programmablaufpläne in Code umsetzen, und schon 
schwingt deine Mühle.
Ich find’s in der Regel einfacher aus einem PAP ein Source zu erstellen, 
statt den Source von jemanden nachzuvollziehen.

Bis meine IIC- Kommunikation lief, hatte ich mehr wie 2 Wochen an 
Datenblättern und Spezifikationen rumstudiert.

Viel spaß

Autor: Steffen H. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@MWS

Bist du ein Rechtsverdreher? Die beziehen sich auch immer auf 
Unterparagraphen die dann wieder irgendwelche neuen Verweise bringt. Ich 
muss hier Ladde Recht geben. Wenn man schon ein Beispiel bringt, muss es 
auch zum Controller/Datasheet passen!

Und aus so mancher Kleinigkeit wurden schon mal Tage zur Fehlersuche. 
Und nur weil man davon ausgeht, dass ein Datasheet informieren sollte 
und nicht verwirren..

Autor: MWS (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Steffen H.,

> Bist du ein Rechtsverdreher? Die beziehen sich auch immer auf
> Unterparagraphen die dann wieder irgendwelche neuen Verweise bringt.

Nein, ganz sicher nicht. Mein Argument ist, wer sich mit µC's 
erfolgreich auseinandersetzen will, muss flexibel sein und das eine oder 
andere Problem durch Nachdenken und auch Lernen der Basics zu 
umschiffen.

> ...wurden schon mal Tage zur Fehlersuche.

Wenn ein Programmierer mit der eindeutigen Fehlermeldung "Operand 1 out 
of range: 0xb8" Tage sucht, dann sollte über eine weniger hirnintensive 
Tätigkeit nachgedacht werden.

Und ich rechtfertige nicht, daß Atmel ein Beispiel reinschreibt, das 
wahrscheinlich das Standardbeispiel in allen Datenblättern ist, ich 
halte es lediglich für einen verzeihlichen Umstand, da es den Ablauf des 
TWI ausreichend erklärt.

Jeder mittelmäßig begabte Programmierer sollte dieses Beispiel anpassen 
können. Dazu muss sich besagter Programmierer aber erst einmal 
ausreichend mit der Materie beschäftigen, was der TE offensichtlich 
nicht getan hat.

Seine Hausaufgaben nicht machen, dafür aber Erbsen zählen und sich 
sofort beschweren ist so eine richtig deutsche Eigenschaft, dafür sind 
wir berühmt in aller Welt :D

Autor: L. K. (ladde)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
MWS schrieb:
>Jeder mittelmäßig begabte Programmierer sollte dieses Beispiel anpassen
>können. Dazu muss sich besagter Programmierer aber erst einmal
>ausreichend mit der Materie beschäftigen, was der TE offensichtlich
>nicht getan hat.

> Seine Hausaufgaben nicht machen, dafür aber Erbsen zählen und sich
> sofort beschweren ist so eine richtig deutsche Eigenschaft, dafür sind
> wir berühmt in aller Welt :D

Jetzt verdrehst du aber das passierte. Nachdem der Fehler auftauchte 
habe ich selbstständig nach der Lösung gesucht und sie gefunden (siehe 
zweiter Post in diesem Topic). Und Atmel auf den Fehler / die 
Ungenauigkeit (nenne es, wie du magst) hinzuweisen, damit in Zukunft 
Ungereimtheiten vermieden werden können, ist meiner Meinung nach kein 
meckern sondern ein gut gemeinter Verbesserungsvorschlag.

@gtf
Danke für die Hinweise. Habe inzwischen reichlich Informationen zu TWI / 
I²C (unter anderem die von dir genannten App-Notes) und werde mal sehen, 
wie weit ich damit komme.

Danke + Gruß
Ladde

Autor: ... ... (docean) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
programmiere in C mit WinAVR und alle Probleme sind wech...

duckundwech

Autor: MWS (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
L. K. (ladde),

ich hab' mich eher gewundert, wie solch ein, imho Pippifax, überhaupt 
den Weg in's Forum findet.

Denn selbst wenn man noch nie mit "größeren" µC's gearbeitet hat deren 
IO über 0x3F hinausgeht, und solch eine eindeutige Meldung bekommt, dann 
schaut man halt den Befehl nach, merkt der geht nur bis 0x3F, das muss 
anders adressiert werden und gut ist's, im Hirn ab dann abgehakt.

Es ist immer noch meine Meinung, daß der Fall hier absolut geringfügig 
ist und ganz sicher keinen Fehlerreport wert.

Aber schaun wir mal, vielleicht bekommst Du Antwort, Dear Sir, many 
thanks for the report of this dangergous bug, we immediately corrected 
it and rewrote all our 32000 datasheets...

Oder Du bekommst 'nen Tiny zum selber zusammenstecken als kleines 
Dankeschön ;-)

Autor: L. K. (ladde)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
So, der Bus läuft endlich!!
Auch wenns für mich etwas beschämend ist hier der Fehler:
Habe mich heute intensiv mit Datenblättern, App-Notes, Literatur usw. 
beschäftigt, konnte dabei aber keinen Fehler in den Routinen finden.
Als ich die TWI-Frequenz soweit wie irgendmöglich reduziert hatte 
(Prescaler 3, Bitrate-Register 255, CKDIV8-Fuse gesetzt) und nur START 
gesendet hatte, fiel mir auf, dass der die LED am SDA-Pullup verdächtig 
lange flackert.
Eignetlich dürfte sie ja nur einmal (sehr) kurz aufleuchten. Habe aber 
das "ret" für twi_init vergessen (siehe Ursprungspost), so dass schon 
beim Init ein Start gesendet wird. Das nächste Start verursacht deshalb 
einen Fehler und die weiteren Buszugriffe schlagen natürlich auch fehl.

Tja, nächstes Mal den eigenen Quelltext nochmal aufmerksam von Anfang 
bis Ende lesen, dann bleibt einem ne Menge Ärger erspart.

Grüße
Lasse

PS: Wenn ich von Atmel ne Nachricht bekomme, werde ich diese hier 
posten.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.