Forum: Mikrocontroller und Digitale Elektronik UART des ATMega48 in ASM programmieren


von Bruno M. (brumay)


Lesenswert?

Hallo,

Ich versuche seit geraumer Zeit den UART eines AT48 zu programmieren, 
aber ohne Erfolg. Zur Kontrolle habe ich deshalb das Programm für einen 
AT8 angepaßt und siehe da, es funktioniert. Um den Fehler zu finden bin 
ich nun dabei die für den AT48 nötigen Änderungen schrittweise 
einzufügen und bleibe schon bei der ersten Änderung hängen.

Den Code Abschnitt für den AT8
1
transFolge:
2
  sbis  UCSRA, UDRE    ;überspringe wenn Sender frei
3
  rjmp  transFolge
4
  out    UDR, r0
5
  adiw  zl:zh,1
6
  rjmp  trans

habe ich geändert in:
1
transFolge:
2
  lds  temp, UCSRA
3
  sbrs  temp, UDRE  ;überspringe wenn Sender frei
4
  rjmp  transFolge
5
  out    UDR, r0
6
  adiw  zl:zh,1
7
  rjmp  trans

Wo liegt der Fehler?
Im Simulator sehe ich, daß das Register temp nicht den Wert von UCSRA 
annimmt??

Bruno

von spess53 (Gast)


Lesenswert?

Hi

>Im Simulator sehe ich, daß das Register temp nicht den Wert von UCSRA
>annimmt??

Vielleicht, weil das Register in Wirklichkeit UCSR0A heißt? Genau wie 
UDR beim ATMega 48 UDR0 heißt.

MfG Spess

von spess53 (Gast)


Lesenswert?

Hi

Außerdem solltest du auch die m48def.inc einbinden.

MfG Spess

von Bruno M. (brumay)


Lesenswert?

Hallo Spess,

ich teste diesen Code immer noch mit dem ATMega 8, d.h. alles 
unverändert, nur dieser Abschnitt ist dem Code für den AT48 angepaßt. 
Das müßte doch auch funktionieren, oder?

Bruno

von Cyblord -. (cyblord)


Lesenswert?

Bruno M. schrieb:
> Hallo Spess,
>
> ich teste diesen Code immer noch mit dem ATMega 8, d.h. alles
> unverändert, nur dieser Abschnitt ist dem Code für den AT48 angepaßt.
> Das müßte doch auch funktionieren, oder?

Warum denn bitte so ein Humbug? Schreib und teste den Code doch einfach 
für deine gewünschte Zielplattform und fertig. Wenn der nicht geht, 
stell ihn rein und der Fehler kann gefunden werden.
Stattdessen stellst du jetzt Code für den Mega8 rein, weil ein anderer 
Code für den M48 nicht läuft. Kopf->Wand.

von Bruno M. (brumay)


Lesenswert?

Ganz einfach, weil mich Dinge manchmal interessieren, auch wenn es nicht 
unmittelbar der Problemlösung dient.

von Cyblord -. (cyblord)


Lesenswert?

Bruno M. schrieb:
> Ganz einfach, weil mich Dinge manchmal interessieren, auch wenn es nicht
> unmittelbar der Problemlösung dient.

Nein du kannst einfach keine zielgerichtete Frage stellen und die 
nötigen Infos dazu liefern.
Was soll die ganze Einleitung mit M48 und UART wenn es im Endeffekt um
einen angeblich nicht funktionieren einfachen einzeilligen ASM Befehl 
geht?

> lds  temp, UCSRA

Schreibt den Inhalt von UCSRA in den temp Register. PUNKT.
Ist der Register temp korrekt deklariert? Wissen wir nicht, weil der 
Code nicht vollständig ist.
Ob dein Simulator was anderes sagt, wissen wir nicht, weil deine 
"Aussage"

> Im Simulator sehe ich, daß das Register temp nicht den Wert von UCSRA
> annimmt??

sogar noch Fragezeichen enthält.

Also was war jetzt eigentlich nochmal die Frage? Kannst du das mal 
irgendwie konkretisieren?

von c-hater (Gast)


Lesenswert?

Bruno M. schrieb:

> ich teste diesen Code immer noch mit dem ATMega 8, d.h. alles
> unverändert, nur dieser Abschnitt ist dem Code für den AT48 angepaßt.
> Das müßte doch auch funktionieren, oder?

Nein.

Zwar kann man auch auf im IO-Bereich liegende Register mittels 
SRAM-Instruktionen zugreifen, dann muß man aber die Adresse anpassen, 
denn die beiden Adressräume sind verschieden.

>   lds  temp, UCSRA

Muß also geändert werden in

  lds  temp, UCSRA+$20

Der Hintergrund ist, daß der IO-Bereich im SRAM-Bereich mit einem Offset 
von 32 ($20) gemapped ist.

Beachte: Für IO-Register, die ausschließlich über den SRAM-Bereich 
erreichbar sind, ist der Offset bereits bei der Deklaration des Symbols 
eingerechnet worden. Da beim M48 UCSR0A ein derartiges Register ist, 
darfst du hier also nicht nochmal den Offset hinzurechnen. Für den M48 
müßte die Zeile also lauten:

  lds  temp, UCSR0A

Falls du dich nun fragst, wie man nun herausbekommt, ob der SRAM-Offset 
eines bestimmten Registers bereits in seinem Symbol steckt oder nicht:

Da schaut man einfach in die *def.inc des Zieldevice (hier m48def.inc)

.equ  UCSR0A  = 0xc0  ; MEMORY MAPPED

Einerseits erkennt man es daran, daß die Adresse größer als $3f ist, 
denn das ist das Ende des IO-Adressraumes, größere IO-Adressen gibt es 
schlicht nicht, es muß sich also zwingend um SRAM-Adressen handeln und 
zum anderen natürlich an dem Kommentar, den Atmel freundlicherweise 
gleich drangeschrieben hat.

von spess53 (Gast)


Lesenswert?

Hi

>ich teste diesen Code immer noch mit dem ATMega 8, d.h. alles
>unverändert, nur dieser Abschnitt ist dem Code für den AT48 angepaßt.
>Das müßte doch auch funktionieren, oder?

Nein. lds greift z.B. auf eine andere Adresse als sbis zu. Damit es mit 
lds funktioniert müsstest du

>lds  temp, UCSRA

durch

lds  temp, UCSRA+0x20

ersetzen.

MfG Spess

von Bruno M. (brumay)


Lesenswert?

Hallo c-hater und Spess,

herzlichen Dank für die aufschlußreichen Antworten!

Gruß bruno

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

spess53 schrieb:
> Nein. lds greift z.B. auf eine andere Adresse als sbis zu. Damit es mit
> lds funktioniert müsstest du
>
>>lds  temp, UCSRA
>
> durch
>
> lds  temp, UCSRA+0x20
>
> ersetzen.

 Ahem.
 Nein, das funktioniert sicher nicht so.
 Richtig ist (für MEGA48):
 lds  temp, UCSR0A

 Und falls du mal nicht sicher sein solltest, ob ein bestimmtes
 Register oberhalb oder unterhalb 0x3F liegt, hier ein Macro dafür:


.macro Store       ;Register, Register
   .if   @0>0x3F
      sts   @0, @1
   .else
      out   @0, @1
   .endif
.endmacro

.macro Load       ; Register, Register
   .if   @1>0x3F
      lds   @0, @1
   .else
      in   @0, @1
   .endif
.endmacro

 EDIT: Und hier Macros zum Abfragen:

;*  SKBS : SKip if Bit Set
.macro SKBS      ; Address, Bit
.if @1>7
    .message "Nur bits 0-7 erlaubt !"
.endif
.if @0>0x3F
    lds  MacReg, @0
    sbrs MacReg, @1
.elif @0>0x1F
    in   MacReg, @0
    sbrs MacReg, @1
.else
    sbis @0, @1
.endif
.endmacro

;*  SKBC : SKip if Bit Cleared
.macro SKBC      ; Address, Bit
  .if @1>7
    .message "Nur bits 0-7 erlaubt !"
  .endif
  .if @0>0x3F
    lds  MacReg, @0
    sbrc  MacReg, @1
  .elif @0>0x1F
    in  MacReg, @0
    sbrc  MacReg, @1
  .else
    sbic @0, @1
  .endif
.endmacro

von spess53 (Gast)


Lesenswert?

Hi

>Nein, das funktioniert sicher nicht so.
> Richtig ist (für MEGA48):
> lds  temp, UCSR0A

Es geht nicht um den ATMega48. Der TO hat diesen Teil für den ATMega8 
geschrieben. Und dort landest du mir lds tmp,UCSRA eben nicht im 
Register UCSRA.

>Und falls du mal nicht sicher sein solltest, ob ein bestimmtes
> Register oberhalb oder unterhalb 0x3F liegt, hier ein Macro dafür:

Keine Angst. Ich bin mir diesbezüglich recht sicher.

MfG Spess

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

spess53 schrieb:
> Keine Angst. Ich bin mir diesbezüglich recht sicher.

 Weiss ich.
 TO war gemeint, sorry.

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.