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


von L. K. (ladde)


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:
1
;
2
; Two-Wire-Interface Routinen
3
;
4
5
6
;Initialisierung
7
twi_init:
8
  ldi temp1, 0x32    
9
  out TWBR, temp1
10
  ldi temp1, 0x01    
11
  out TWSR, temp1
12
13
14
; Start senden
15
16
twi_start:
17
  ldi temp1,(1<<TWINT)|(1<<TWSTA)|(1<<TWEN)
18
  out TWCR,temp1    ;Start Condition senden
19
twi100:
20
  in temp1,TWCR    ;Status holen
21
  sbrs temp1,TWINT  ;Kommando ausgeführt?
22
  rjmp twi100    ;nein -> warten
23
  ret
24
25
26
; TWI Write
27
; Zu sendendes Byte in temp1
28
29
twi_write:
30
  out TWDR,temp1    ;Byte in Ausgaberegister
31
  ldi temp1,(1<<TWINT)|(1<<TWEN)
32
  out TWCR,temp1    ;Byte senden
33
  rjmp twi100    ;Warten bis ausgeführt
34
35
36
; TWI Read mit Ack.
37
; Empfangenes Byte in temp1
38
39
twi_read:
40
  ldi temp1,(1<<TWINT)|(1<<TWEA)|(1<<TWEN)
41
  out TWCR,temp1    ;Flags setzen
42
twi200:
43
  in temp1,TWCR    ;Status holen
44
  sbrs temp1,TWINT  ;Kommando ausgeführt?
45
  rjmp twi200    ;nein -> warten
46
  in temp1,TWDR    ;Daten sind da
47
  ret
48
49
50
; TWI Read ohne Ack.
51
; Empfangenes Byte in temp1
52
53
twi_readna:
54
  ldi temp1,(1<<TWINT)|(1<<TWEN)|(0<<TWEA)
55
  out TWCR,temp1    ;Flags setzen
56
twi201:
57
  in temp1,TWCR    ;Status holen
58
  sbrs temp1,TWINT  ;Kommando ausgeführt?
59
  rjmp twi201    ;nein -> warten
60
  in temp1,TWDR    ;Daten sind da
61
  ret
62
63
64
; TWI Stop Condition
65
66
twi_stop:
67
  ldi temp1,(1<<TWINT)|(1<<TWSTO)|(1<<TWEN)
68
  out TWCR,temp1    ;Stop Condition senden
69
  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?

von L. K. (ladde)


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.

von spess53 (Gast)


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

von L. K. (ladde)


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:
1
rcall twi_init     ; TWI Initialisieren
2
3
rcall twi_start    ; Start-Condition setzen
4
5
ldi temp1, 0xD0    ; Schreibzugriff auf DS1337 (Adresse ist 1101000)
6
rcall twi_write
7
8
ldi temp1, 0x0E    ; Statusregister anwählen
9
rcall twi_write
10
11
rcall twi_start    ; Repeated Start
12
13
ldi temp1, 0xD1    ; DS1337 lesen
14
rcall twi_write
15
16
rcall twi_readna   ; Statusregister lesen (kein ACK, da nur ein Byte gelesen werden soll)
17
18
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

von spess53 (Gast)


Lesenswert?

Hi

>Das Programm hängt beim ersten twi_read.

Und wo ist das in deinem Programmteil?

MfG Spess

von L. K. (ladde)


Lesenswert?

Upps, verschrieben...
Sollte twi_write heißen.
Das Programm hängt also im ersten twi_write fest:
1
rcall twi_init     ; TWI Initialisieren
2
3
rcall twi_start    ; Start-Condition setzen
4
5
ldi temp1, 0xD0    ; Schreibzugriff auf DS1337 (Adresse ist 1101000)
6
rcall twi_write

von gtf (Gast)


Lesenswert?

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

von L. K. (ladde)


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

von L. K. (ladde)


Angehängte Dateien:

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?

von MWS (Gast)


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

von L. K. (ladde)


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

von MWS (Gast)


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.

von L. K. (ladde)


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

von MWS (Gast)


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

von gtf (Gast)


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ß

von Steffen H. (Gast)


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..

von MWS (Gast)


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

von L. K. (ladde)


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

von ... .. (docean) Benutzerseite


Lesenswert?

programmiere in C mit WinAVR und alle Probleme sind wech...

duckundwech

von MWS (Gast)


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 ;-)

von L. K. (ladde)


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.

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.