Forum: Mikrocontroller und Digitale Elektronik USART Atmega48 / Atmega88 / Atmega168 Assembler


von Valentin (Gast)


Lesenswert?

Hallo Forum,
ich versuche gerade mein USART mit einem Atmega88 in Assembler ans 
Laufen zu bringen. Der Empfang läuft bereits. Der Atmega88 sendet leider 
nicht korrekt. Hat jemand ein Beispiel zur Hand?

Meinen Code habe ich dem Usart Artikel entnommen und von Atmega8 nach 
Atmega88 transferiert. Hat wohl nur teilweise geklappt.

Ich hänge ihn unten an, da es relativ lang ist. Den Code habe ich nur 
infomäßig angefügt. Ich benötige nur ein Beispiel und erwarte keine 
Korrektur.

Vielen herzlichsten Dank schon jetzt
Valentin

Ich definiere Makros zum Setzen und Löschen von bits.
1
; ----------------------------------------------------------------
2
; Macro:     setbit 
3
; Function:    Sets a bit in a register
4
; Usage:     setbit Rd, b, Re where 0 <= d <= 31, 
5
;                                         0 <= e <= 31, d not equal e,
6
;                                         0 <= b <= 7
7
; Description: This macro works similar to sbi for registers r0 
8
;              to r31. Note that statement sbr is different since 
9
;         it expects the content as parameter.
10
;              Register Re is used to save the status register 
11
;              (SREG). This macro keeps the
12
;         SREG and the temporary register Re.
13
; Example:     
14
;    setbit  r0, 7, r1   ; sets bit 7 in register r0, 
15
;                                   ; temporary register r1
16
;
17
; ----------------------------------------------------------------
18
MACRO  setbit
19
    push  @2    ; keep temporary register 
20
    in   @2, SREG  ; keep SREG
21
    push  @2
22
    set      ; Set T-flag and 
23
    bld  @0, @1    ; load T at bit @1 in register @0
24
    pop  @2
25
    out  SREG, @2  ; restore SREG
26
    pop  @2    ; restore temporary register
27
.ENDMACRO
28
;
29
; ----------------------------------------------------------------
30
; Macro:     clrbit 
31
; Function:    Clears a bit in a register
32
; Usage:     clrbit Rd, b, Re where 0 <= d <= 31, 
33
;                                         0 <= e <= 31, d not equal e,
34
;                                         0 <= b <= 7
35
; Description: This macro works similar to cbi for registers r0 
36
;              to r31. Note that statement cbr is different 
37
;         since it expects the content as parameter.
38
; Example:     
39
;    clrbit  r0, 7, r1   ; clears bit 7 in register r0
40
;                                   ; temporary register r1
41
; ----------------------------------------------------------------
42
.MACRO  clrbit
43
    push  @2      ; keep temporary register
44
    in   @2, SREG    ; keep SREG 
45
    push  @2
46
    clt        ; Clear T-flag and 
47
    bld  @0, @1      ; load T at bit @1 in register @0
48
    pop  @2
49
    out  SREG, @2    ; restore SREG
50
    pop  @2      ; restore temporary register
51
.ENDMACRO
52
;
Den USART initialisiere ich wie folgt
1
; ----------------------------------------------------------------
2
; Subprogran:  UsartInit
3
; Function:  Initialize USART
4
; Parameters:  none
5
; Return value:  none
6
; Description:  This subprogram is called during initialization
7
; ------------------------------------------------------------------
8
;
9
UsartInit:
10
    pushregs
11
    ;
12
     lds   temp0, UCSR0B    ; TX active
13
    setbit  temp0, TXEN0, temp2
14
     sts   UCSR0B, temp0
15
     lds   temp0, UCSR0B     ; RX aktivate
16
    setbit  temp0, RXEN0, temp2
17
     sts   UCSR0B, temp0
18
    ; set baudrate
19
     ldi   temp0, high( clockmaster/(baudrate*16)-1)
20
     sts   UBRR0H, temp0
21
    ldi   temp0, low( clockmaster/(baudrate*16)-1)   
22
     sts   UBRR0L, temp0
23
    ; USART Interrupt if data receive complete
24
     lds   temp0, UCSR0B       
25
    setbit  temp0, RXCIE0, temp2
26
     sts   UCSR0B, temp0
27
    ; USART Interrupt if send-register empty
28
     lds   temp0, UCSR0B       
29
    setbit  temp0, UDRIE0, temp2
30
     sts   UCSR0B, temp0
31
    ; USART Interrupt bei Sendevorgang beendet
32
     lds   temp0, UCSR0B       
33
    setbit  temp0, TXCIE0, temp2
34
    sts   UCSR0B, temp0
35
    ;
36
      popregs
37
    ret
38
    ;
Und jetzt versuche ich so zu senden
1
; ----------------------------------------------------------------
2
; Subprogran:  USARTSEND 
3
; Function:    sends the data byte given in the temp0 register 
4
;               via USART
5
; Parameters:  temp0 - data byte to be send via USART
6
; Return value:  none
7
; Description:  This subprogram sends the data given in named 
8
;               register temp0 via USART.
9
; ----------------------------------------------------------------
10
;
11
USARTSEND:   
12
    pushregs
13
UDR0EmptyOrNot:
14
    lds  temp1, UCSR0A
15
    sbrs  temp1, UDRE0    ; Loop until UDR0 in UCSR0A is empty
16
    rjmp   UDR0EmptyOrNot
17
    sts   UDR0, temp0
18
    popregs
19
    ret                               
20
                ;

von Stefan E. (sternst)


Lesenswert?

1
MACRO  setbit
2
    push  @2    ; keep temporary register 
3
    in   @2, SREG  ; keep SREG
4
    push  @2
5
    set      ; Set T-flag and 
6
    bld  @0, @1    ; load T at bit @1 in register @0
7
    pop  @2
8
    out  SREG, @2  ; restore SREG
9
    pop  @2    ; restore temporary register
10
.ENDMACRO
11
...
12
     lds   temp0, UCSR0B    ; TX active
13
    setbit  temp0, TXEN0, temp2
14
     sts   UCSR0B, temp0
15
     lds   temp0, UCSR0B     ; RX aktivate
16
    setbit  temp0, RXEN0, temp2
17
     sts   UCSR0B, temp0
18
...
Wow, das ist doch mal ein imposantes "von hinten durch die Brust ins 
Auge". Irgendwie muss das Flash doch voll zu kriegen sein. ;-)

1
   setbit  temp0, RXCIE0, temp2
2
...
3
    setbit  temp0, UDRIE0, temp2
4
...
5
    setbit  temp0, TXCIE0, temp2
Warum aktivierst du alle drei UART-Interrupts? Du versuchst doch 
offensichtlich per Polling zu senden.

von spess53 (Gast)


Lesenswert?

Hi

würde mich mal interessieren wo man solchen Unsinn lernt. Eine UART 
initialisiere ich in Assembler mit maximal 10 Assenblerbefehlen.

MfG Spess

von Reinhard J. (rvj)


Lesenswert?

Hallo,
erst mal Danke für die unmittelbare Antwort.
Deine Bemerkung zu meiner Platzverschwendung verstehe ich. Ich bin 
AVR-Assembler Anfänger und versuche meinen Code für mich lesbarer zu 
gestalten ohne Rücksicht auf den Flash. Ist ja genug da. Sollte ich in 
Schwierigkeiten kommen, kann ich den Code eindampfen. Ich hoffe ich 
benötige dann solche Krücken nicht mehr.
Nun zum USART: Ja ich versuche mit Polling zu senden. Die USART 
Programmierung habe ich noch nicht richtig verstanden und ich hatte 
gehofft wenigstens den Teil mit Beispielen erschlagen zu können. 
Schließlich betrete ich überall Neuland. Habe nun den ganzen Sonntag 
damit verbracht mir einen TTL nach Seriell Wandler zu bauen und den 
USART zu programmieren. Trotz intensiver Suche und Lesen der Atmega88 
Doku gelingt mir das Senden nicht. Übrigens scheinen da Fehler im 
Atmega48  Atmega88  Atmega168 zu sein: Dort werden die out Befehle 
benutzt die aber den Bereich der USART Register gar nicht erreichen 
können. Man braucht offensichtlich sts.
Kann ich bitte ein Beispiel haben um das Senden mit Polling auch zu 
erreichen? Senden tu ich wohl mit Polling wie folgt:
1
; ----------------------------------------------------------------
2
; Subprogran:  USendDivisorsToClient 
3
; Function:  sends the divisors to the client via USART
4
; Parameters:  none
5
; Return value:  none
6
; Description:  This subprogram sends the data in the named  
7
;    registers Div1, Div2, Div3 and Div4 to the client 
8
;    program via USART. The data is wrapped with the 
9
;    UsartStartSignal and the UsartEndSignal.
10
; ----------------------------------------------------------------
11
;
12
USendDivisorsToClient:
13
    pushregs
14
    ;
15
    ldi   temp0, UsartStartSignal
16
    rcall  USARTSEND
17
    mov    temp0, Div1
18
    rcall  USARTSEND
19
    mov    temp0, Div2
20
    rcall  USARTSEND
21
    mov    temp0, Div3
22
    rcall  USARTSEND
23
    mov    temp0, Div4
24
    rcall  USARTSEND
25
    ldi   temp0, UsartEndSignal
26
    rcall  USARTSEND
27
    ;
28
      popregs
29
    ret
30
    ;
Im Anschluss zur Unterhaltung noch zwei Makros, da ich ständig bei push 
und pop das SREG vergessen hatte. Ist als Anfänger einfach 
betriebssicherer.
Nochmals vielen Dank!
Gruß
Valentin
1
 
2
; ----------------------------------------------------------------
3
; Macro:       pushregs 
4
; Function:    Pushes the temporary registers and the SREG onto 
5
;              the stack 
6
; Usage:       pushregs    
7
; Description: This macro pushes the registers temp1, temp2, 
8
;              temp3, temp4 and the status register (SREG) onto 
9
;         the stack. To forget saving some registers on the
10
;         stack or to put the instructions at a wrong place
11
;              is a common source of error. This macro enhances 
12
;              the readability of the source since it summarizes 
13
;         a queue of statements. On the other hand it
14
;         saves all temporary registers on the stack which 
15
;              is in almost all cases not needed and causes 
16
;         overhead.
17
;         Warning: Do not use this macro if parameters are 
18
;                       returned in the temporary registers! 
19
;      Do not use this macro in performance 
20
;                       critical code! Do not forget to make use 
21
;      of macro popregs to restore the registers!
22
; Example:     
23
;         pushregs
24
; ----------------------------------------------------------------
25
.MACRO  pushregs
26
push   temp0     ; save temp0
27
push   temp1          ; save temp1
28
push   temp2          ; save temp2
29
push   temp3          ; save temp3
30
push   temp4          ; save temp4
31
in   temp0, SREG  ; save SREG
32
push   temp0  
33
.ENDMACRO
34
;
35
;
36
; ----------------------------------------------------------------
37
; Macro:       popregs 
38
; Function:    Restores the temporary registers and the SREG from 
39
;              the stack 
40
; Usage:       popregs    
41
; Description: This macro restores the registers temp1, temp2, 
42
;              temp3, temp4 and the status register (SREG) from  
43
;         the stack which had been saved on the stack utilizing
44
;         macro pushregs.
45
;         To forget restoring some registers from the stack 
46
;         or to put the instructions at a wrong place is a 
47
;              common source of error. This macro enhances the 
48
;         readability of the source since it summarizes a 
49
;              queue of statements. On the other hand it restores 
50
;         all temporary registers on the stack which is in 
51
;         almost all cases not needed and causes overhead.
52
;         Warning: Do not use this macro if parameters are 
53
;                       returned in the temporary registers! 
54
;      Do not use this macro in performance 
55
;                       critical code! Do not use this macro if 
56
;      the registers were not saved by pushregs!
57
; Example:     
58
;         popregs
59
; ----------------------------------------------------------------
60
.MACRO  popregs
61
pop  temp0    ; restore SREG,
62
out  SREG, temp0    
63
pop  temp4    ; restore temp4
64
pop  temp3    ; restore temp3
65
pop  temp2    ; restore temp2
66
pop  temp1    ; restore temp1
67
pop  temp0          ; restore temp0
68
.ENDMACRO

von ZuBlödFürTouch (Gast)


Lesenswert?

Ich frag mich nur grad warum das Brimborium beim Setzen und Löschen von 
Bits. Was genau spricht gegen sbr und cbr?

von bitte löschen (Gast)



Lesenswert?

ZuBlödFürTouch schrieb:
> Was genau spricht gegen sbr und cbr?

Es geht halt nicht jeder Befehl mit jedem Register.

Man kann sich Makros schreiben, um das zu umgehen oder man kann sich 
damit arrangieren und Für Operationen, bei denen in einem Register 
einzelne Bits behandelt werden sollen, einfach Register nehmen, mit 
denen das geht.

Da ich (ebenfalls noch nicht so lange dabei) auch noch nicht im Kopf 
habe, welcher Befehl mit welchen Registern geht, habe ich mir ein 
Word-Dokument (Anlage) gemacht, in dem die Register mit den möglichen 
Befehlen tabellarisch aufgelistet sind. Da trage ich bei einem Projekt 
jeweils die Variablen ein, und bekomme so eine Übersicht, welche sehr 
häufig verwendeten Variablen ich in welche Register packen kann und was 
in den SRAM muss.

von Reinhard J. (rvj)


Lesenswert?

Hallo zusammen,
erst mal Danke für die lebhafte Diskussion. Leider finden meine Makros 
mehr Beachtung als meine Frage. Phillip hat völlig recht, mit seiner 
Annahme, dass ich mir mit den Makros einiges Erleichtern will. Danke für 
das Dokument Phillip!
Seid doch bitte so nett und geht auf meine eigentliche Frage ein. Sie 
lautete: Hat jemand ein Beispiel für das Senden von einem Atmega48, 
Atmega88 oder Atmega168 zum PC zur Hand? Das Senden soll wie oben 
erklärt ablaufen. Stefan hat die von mir gewünschte Methode als Polling 
bezeichnet. Empfangen klappt übrigens schon.
Viele Grüße
Reinhard

von spess53 (Gast)


Lesenswert?

Hi

>ZuBlödFürTouch schrieb:
>> Was genau spricht gegen sbr und cbr?

>Es geht halt nicht jeder Befehl mit jedem Register.

Ein kurzer Blick ins Instruction Set sagt jedem, das 'sbr/cbr' auf jedes 
Register anwendbar sind. Also kann man das Macro 'setbit' auf

MACRO  setbit
  sbr @0, 1<<@1
endmacro

eindampfen. Gilt analog für clrbit.

@Reinhard J. (rvj

Du schreibst:

>Nun zum USART: Ja ich versuche mit Polling zu senden.

Warum gibst du dann sämtliche Interrupts der UART frei?

MfG Spess

von Reinhard J. (rvj)


Lesenswert?

Danke für die Antwort.
Die Interrupts gebe ich wohl aus Unkenntnis frei.
Was möchte ich tun?
Ich benutze ein AVR-Net-IO und sende ein Startbyte (0x7E) vom PC zum 
Controller, falls das zweite Byte 0xFE enthält werden vier Register Div1 
bis Div4 vom Controller an den PC zurückgesendet. Ist das nicht der Fall 
werden die Register mit den folgenden vier Bytes die vom PC kommen 
gefüllt.
Wozu das ganze? Ich kann dann die Register setzen und abfragen.
Setzen der Register klappt einwandfrei. Nur weiß ich nicht wie ich das 
mit dem Senden der Register zum PC bewerkstelligen muss. Die 
Dokumentation habe cih leider bis jetzt noch nicht verstanden. Ich hoffe 
mit einem Beispiel durchzublicken.
Viele Grüße
Reinhard

von spess53 (Gast)


Lesenswert?

Hi

Empfängt dein PC überhaupt etwas?

Wenn du Probleme mit der UART hast dann schreibe dir ein kleins 
Testprogramm das nur aus Initialisierung und einer Schleife, die ein 
Zeichen sendet, besteht.

MfG Spess

von Reinhard J. (rvj)


Lesenswert?

Hallo,
ja mein PC empfängt was. Nur leider statt Startsignal (0x7E), Div1, 
Div2, Div3, Div4, Endesignal (0x7F) stehen da sechsmal 0x02. Nutze 
HTerm.exe ein freies Terminal, das wirklich Klasse ist. Der restliche 
Code ist so simpel, dass ich meinen USART verdächtige nicht richtig 
programmiert zu sein. Hast Du ein Beispiel? Das ist das was mir helfen 
würde. Ich habe wirklich vieles probiert bevor ich mich ans Forum 
wendete.
Gruß Reinhard

von spess53 (Gast)


Angehängte Dateien:

Lesenswert?

Hi

Probiere mal das Programm im Anhang. Mit HTerm solltest du 'A' 
empfangen. UBRR muss natürlich angepasst werden.

Welche Taktfrequenz/Baudrate benutzt du?

MfG Spess

von Reinhard J. (rvj)


Lesenswert?

Vielen Dank Spess,
bin jetzt nicht mehr zu Hause und kann es erst morgen Abend 
ausprobieren. Ich habe einen von 18,4320 MHz eingebaut. Die Frequenz und 
baudrate gebe ich so mit
1
.equ clockmaster = 18432000  ; a baud rate quarz for the master 
2
.equ baudrate    = 9600
und schiebe dann den Wert in UBRR0H
1
    ; set baudrate
2
     ldi   temp0, high( clockmaster/(baudrate*16)-1)
3
     sts   UBRR0H, temp0
4
     ldi   temp0, low( clockmaster/(baudrate*16)-1)   
5
     sts   UBRR0L, temp0
Das scheint richtig zu sein denn mit Deiner baudrate errechne ich
(11059200 / (9600 * 16) ) - 1 = 71 = 0x47
Mir fehlt aber
1
     ldi r16,3<<UCSZ00
2
     sts UCSR0C,r16
Ich werde mir das mit Register UCSR0C nochmal durchlesen, testen und 
spätestens Mittwoch berichten. Wenn ich das Handbuch richtig verstehe 
kann ich mir das eigentlich sparen, denn der default im UCSR0C ist 
UCSZ00=1 und UCSZ01=1. Im Register UCSR0B ist der default für UCSZ02=0 
und wir arbeiten darum mit 8-bit character size. Falls Dein code 
funktioniert muss ich den Fehler woanders suchen.
Herzlichsten Dank
Valentin
PS: Ich muss mir das mit den Bitmanipulatoren vergegenwärtigen. Mit 
meiner Makroakrobatik und dem Nacheinander setzen der Bits hatte ich 
mich davor gedrückt. So wie Du das schreibst sieht das deutlich kürzer 
aus. Gibt es da ein Tutorial für die Landbevölkerung?

von bitte löschen (Gast)


Lesenswert?

spess53 schrieb:
> Ein kurzer Blick ins Instruction Set sagt jedem, das 'sbr/cbr' auf jedes
> Register anwendbar sind.

Dann bin ich mal wieder zu deppert, Doku richtig zu lesen.
Da steht:

CBR – Clear Bits in Register
Description:
Clears the specified bits in register Rd. Performs the logical AND 
between the contents of register Rd and the complement
of the constant mask K. The result will be placed in register Rd.
Operation:
(i) Rd ← Rd • ($FF - K)
Syntax: Operands: Program Counter:
(i) CBR Rd,K 16 ≤ d ≤ 31, 0 ≤ K ≤ 255 PC ← PC + 1
16-bit Opcode: (see ANDI with K complemented)

Ich dachte bisher immer, das "d" in "Rd" stünde für die Nummer des 
Registers also r.B. r16 für d=16 und das "16 ≤ d ≤ 31" gäbe an, welche 
Nummern dür "d" genommen werden können.
Vielleicht kannst Du spess53 mir erklären, wie es richtig zu 
interpretieren ist?

von spess53 (Gast)


Lesenswert?

Hi

>Ich muss mir das mit den Bitmanipulatoren vergegenwärtigen. Mit
>meiner Makroakrobatik und dem Nacheinander setzen der Bits hatte ich
>mich davor gedrückt.

Das bringt wirklich mehr.

>Gibt es da ein Tutorial für die Landbevölkerung?

Wüsste ich aus dem Hut für Assembler nicht. Mir hat eigentlich die 
AVR-Studio-Hilfe:  AVR Assembler->User's Guide->Expressions gereicht. 
Ansonsten must du mal in C-Hilfen wildern. Die sind identisch.

MfG Spess

von spess53 (Gast)


Lesenswert?

Hi

@Philipp Klostermann (ag999)

>Vielleicht kannst Du spess53 mir erklären, wie es richtig zu
>interpretieren ist?

Mein Fehler. Du hast Recht. Ich bin wahrscheinlich in der Schnelle bei 
cbi oder sbi gelandet und habe das '0 ≤ A ≤ 31' falsch interpretiert.

MfG Spess

von Heinz L. (ducttape)


Lesenswert?

Ich geb mal zu, auch meine erste Frage hätte sich auf die Bitsetzerei 
gestürzt. cbr/sbr funktioniert (also, sofern mir nicht jemand etwas 
anderes zeigt) für alle general purpose register, cbi/sbi funktioniert 
nicht bei allen I/O Registern wegen der Adressierung, soweit richtig.

Aber zum Thema:

Schau ins Tutorial hier auf der Seite, gibt's 'n ganzes Kapitel nur zum 
Thema UART mit ASM (links oben auf der Seite, im Punkt AVR). Was danach 
an Fragen bliebt bitte noch posten.

von Reinhard J. (rvj)


Lesenswert?

Hallo
im instruction set manual steht
CBR    Rd,K        16 ≤ d ≤ 31, 0 ≤ K ≤ 255
SBR    Rd,K        16 ≤ d ≤ 31, 0 ≤ K ≤ 255
und ich vermute, dass r0 bis r15 nicht funktionieren werden.
Dann besteht da noch die Schwierigkeit, dass wegen 3=0b00000011
1
sbr    r16,3      ; Set bits 0 and 1 in r16
bits 0 und 1 setzt, während dessen
1
sbi    DDRC, 3     ; Port C.3 output - LCD Data/command
nur bit 3 setzt. Für mich war das ein beliebter Fehler und wenn mein 
Projekt wieder einige Wochen ruhte, lief ich prompt wieder in die selbe 
Falle. Daher die Makros.
Vielen Dank für den Hinweis mit dem Tutorial. Ich habe es sehr sehr oft 
konsultiert. Es st einfach Klasse. Vielleicht liest das ja einer der 
Autoren. Ihnen herzlichsten Dank.
Ich kann leider erst morgen Abend weiter machen. ich werde das Programm 
von spess laufen lassen und dann mal die überflüssigen Interrupts 
entfernen. Diese habe ich auch nicht in der Interrupt Vektortabelle mit 
ISRs versorgt. Das könnte der Grund sein. Falls es so ist beschreibe ich 
es hier.
Vielen Dank für das rege Interesse an diesem thread.
Valentin

von Mark L. (m2k10) Benutzerseite


Lesenswert?

Vielleicht sollte man sich diese Fake-Opcodes gar nicht erst angewöhnen. 
Habe auch schon öfters diesen sbi/sbr-Denkfehler mit der Bitmaske 
gemacht und lange den Fehler gesucht.
Wenn man daran denkt, dass es eigentlich gar kein SBR gibt oder direkt 
ORI verwendet oder gedanklich berücksichtigt, passiert das nicht.bei CBR 
geht das auch mit ANDI reg,!mask sind nur zwei Zeichen mehr zu tippen.

Mark

von Reinhard J. (rvj)


Lesenswert?

Hallo zusammen!

Erst mal vielen Dank an alle! Nachdem ich mit spess53's Hilfe gesehen 
habe, dass der USART funktioniert, habe ich den Fehler eliminieren 
können. Hier mein Analyseweg und mein Fehler:

1. Ich habe das Programm von spess53 laufen lassen und 'A's ohne Ende 
gekriegt (vergleiche Eintrag vom Datum: 18.03.2012 22:13). Speziellen 
Dank an spess53

2. Danach habe ich die überflüssigen Interrupts rausgehauen (vergleiche 
Eintrag vom Datum: 18.03.2012 22:13 und Tipp in Eintrag Datum: 
18.03.2012 22:35) Danke Stefan.
1
; This interrupt is dropped due to the the discussion 
2
; on microcontroller.net
3
; USART Interrupt if send-register empty
4
;       lds     temp0, UCSR0B           
5
;       setbit  temp0, UDRIE0, temp2
6
;       sts     UCSR0B, temp0
7
; This interrupt is dropped due to the the discussion 
8
; on microcontroller.net
9
; USART Interrupt bei Sendevorgang beendet
10
;       lds     temp0, UCSR0B           
11
;       setbit  temp0, TXCIE0, temp2
12
;       sts     UCSR0B, temp0
Leider kein Erfolg. Ich empfange weiterhin nur 0x02.

3. Und jetzt kommts: Ich habe den Fehler! Mein Makro sichert immer alle 
named register temp0 bis temp4. Dann speichere ich das SREG in temp0 und 
haue auch dieses auf den stack. Da ich aber das zu übermittelnde Byte in 
temp0 ablegte bevor ich USARTSEND rufe stand nach dem Sichern des SREG 
das SREG in temp0 und das enthielt zufällig 0x02.

Was mir passiert ist im code ohne Makros:

Ich stelle das zu übermittelnde Byte nach temp0 und rufe USARTSEND
1
        mov     temp0, DIV1
2
        rcall   USARTSEND
und das sieht so aus
1
USARTSEND:  
2
        push    temp0         ; save temp0
3
        push    temp1         ; save temp1
4
        in      temp0, SREG   ; save SREG  !!! hier geht Byte in ...
5
                              ;            ... temp0 kaputt !!! Es ...
6
        push    temp0         ; ... steht jetzt das SREG in temp0          
7
        ;
8
UDR0EmptyOrNot:
9
        lds     temp1, UCSR0A
10
        sbrs    temp1, UDRE0    ; Loop until UDR0 in UCSR0A is empty
11
        rjmp    UDR0EmptyOrNot
12
        sts     UDR0, temp0     ; Gib temp0 nach seriell
13
        ;
14
        pop     temp0           ; restore SREG,
15
        out     SREG, temp0     
16
        pop     temp1           ; restore temp1
17
        pop     temp0           ; restore temp0
18
        ;
19
        ret

Ich denke das war ein Anfängerfehler.

Lehre: Falls das SREG in einem Register gespeichert wird um es auf den 
stack zu legen, dann kann dieses Register nicht zum Parametertransport 
genutzt werden.

Nochmals vielen Dank.

Gruß Valentin

PS. Ich werde noch zum USART Fan. Damit kann ich mir beim Programmieren 
Registerinhalte anzeigen lassen.

von Karl H. (kbuchegg)


Lesenswert?

Reinhard J. schrieb:

> Ich denke das war ein Anfängerfehler.

Es war vor allen Dingen ein Fehler, weil du in deinem Registerchaos die 
Übersicht verloren hast. Alle Register irgendwie tempxx zu nennen trägt 
dann auch nicht dazu bei, die Übersicht zu behalten.

Wenn dir ein Register so wichtig ist, dass du ihm einen Namen geben 
willst, dann gib ihm einen guten Namen, der auch etwas ob die 
beabsichtigte Nutzung des Registers etwas aussagt. Einfach alles temp zu 
nennen ... da kannst du es auch gleich bleiben lassen. Das wär sogar 
noch besser.

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.