Forum: Mikrocontroller und Digitale Elektronik Atmega 48 UART Daten empfangen


von Jochen (Gast)


Lesenswert?

Hallo, ich habe folgendes Programm geschrieben um per Hyperterminal 
gesendete Daten mit einem Atmega 48 zu empfangen:
1
.include "m48def.inc"
2
.org 0x000
3
       rjmp RESET
4
.org 0x012
5
    rjmp USART_RXC
6
7
USART_RXC:
8
    ldi r16, 0b01000000
9
    out TCCR0A, r16
10
    reti
11
reset:
12
    rcall INIT
13
  
14
15
16
    sei
17
main:
18
    rjmp main
19
20
21
22
INIT:
23
  ;Ports setzen
24
    ;Summer
25
    ldi r16, 0b11000000
26
    out DDRD, r16
27
28
    
29
30
31
  ;Timer für Summer (aus)
32
    ldi r16, 0b00000000
33
    out TCCR0A, r16
34
    ldi r16, 0b00000010
35
    out TCCR0B, r16
36
37
  ;UART RX 2400 baud, RX INT
38
    ldi r16, 0b10010000
39
    sts UCSR0B, r16
40
    ldi r16, 0b00000110
41
    sts UCSR0C, r16
42
    ldi r16, 95
43
    sts UBRR0L, r16
44
    ret

Es soll einfach nur ein Summer angehen wenn irgendein Zeichen empfangen 
worden ist. Der Summer funktioniert, daten an den Pc senden funktioniert 
auch (hatte ich mal kurz getestet)
Sieht jemand einen Fehler?

von Jochen (Gast)


Lesenswert?

Ach ja: Ich benutze natürlich einen Quarz :)

von Achim M. (minifloat)


Lesenswert?

Jochen schrieb:
>   ;UART RX 2400 baud, RX INT
>     ldi r16, 0b10010000
>     sts UCSR0B, r16
>     ldi r16, 0b00000110
>     sts UCSR0C, r16
>     ldi r16, 95
>     sts UBRR0L, r16
>     ret

Kann man die elend langen Bitschreibweise mal durch was klar 
ersichtliches ersetzen(oder gleich verbieten)? (1 << UMSEL)|(1 << 
wasweißich) kann ich viel leichter optisch dekodieren, als das 
Bitgewusel. In ein paar Monaten schon kann die Schreibfaulheit nach 
hinten los gehen, wenn man sich slebst nicht mehr auskennt. Code, der 
selbstdokumentierend ist, braucht nicht viel weitere Erklärungen.
mfg mf

PS: Genau darum muss ich jetzt fragen: Ist RXEN gesetzt?

von Jochen (Gast)


Lesenswert?

Ich schreib mal kurz auf was die Bytes machen:
    ldi r16, 0b10010000
    sts UCSR0B, r16
RXCIE0 setzen
RXEN0 setzen


    ldi r16, 0b00000110
    sts UCSR0C, r16
UCSZ01 setzen
UCSZ00 setzen

von Jochen (Gast)


Lesenswert?

Noch ein Nachtrag. Ich benutze einen USB Seriell Wandler mit CP2102. Der 
funktioniert auch, TX und RX verbinden führt zu einem Echo

von Karl H. (kbuchegg)


Lesenswert?

Jochen schrieb:
> Ich schreib mal kurz auf was die Bytes machen:
>     ldi r16, 0b10010000
>     sts UCSR0B, r16
> RXCIE0 setzen
> RXEN0 setzen

UCSR0B wird laut Datenblatt mittels out angesprochen und nicht mit sts

Und warum schreibst du dann nicht gleich

     ldi r16, (1<<RXCIE0) | (1<<RXEN0)

dann brauchst du das keinem erklären und auch keinen Kommentar

>     ldi r16, 0b00000110
>     sts UCSR0C, r16
> UCSZ01 setzen
> UCSZ00 setzen


AUch UCSR0C wird laut Datenblatt mit out angesprochen.

Das ist NICHT egal, weil die Adresslage eine andere ist, je nachdem ob 
du einen out oder einen sts benutzt. Im Beschreibungsteil des 
Datenblattes sind immer wieder Codeschnipsel enthalten, aus denen 
hervorgeht, welchen Befehl du benutzen musst.

: Wiederhergestellt durch User
von Jochen (Gast)


Lesenswert?

Hallo Karl Heinz. Also wenn ich das mit out schreibe kriege ich immer 
einen Fehler "Operand out of Range"
Vielleicht gibts da Unterschiede zwischen den 3 Atmega (48/88/168) ?

von Karl H. (kbuchegg)


Lesenswert?

Jochen schrieb:
> Hallo Karl Heinz. Also wenn ich das mit out schreibe kriege ich immer
> einen Fehler "Operand out of Range"
> Vielleicht gibts da Unterschiede zwischen den 3 Atmega (48/88/168) ?

Du hast recht.
Hab grade den Abschnitt 'Register Summary' studiert. Das scheint sich 
tatsächlich um einen Fehler im UART Abschnitt im Datenblatt zu handeln. 
Die Register sind allesamt nicht per out zu erreichen. Da war ich zu 
voreilig und habe dem Code im Abschnitt vertraut.

von Spess53 (Gast)


Lesenswert?

Hi

>Vielleicht gibts da Unterschiede zwischen den 3 Atmega (48/88/168) ?

Gibt es nicht.

MfG Spess

von Karl H. (kbuchegg)


Lesenswert?

Ich konnte im Datenblatt nichts darüber finden, dass der Stackpointer 
automatisch korrekt initialisiert wird. D.h. du solltest das selbst in 
die Hand nahmen.

von Spess53 (Gast)


Lesenswert?

Hi

Siehe Datenblatt S.13:

6.6.1 SPH and SPL – Stack Pointer High and Stack Pointer Low Register

MfG Spess

von Stefan E. (sternst)


Lesenswert?

Karl Heinz Buchegger schrieb:
> Ich konnte im Datenblatt nichts darüber finden, dass der Stackpointer
> automatisch korrekt initialisiert wird.

"Initial Value" unter 6.5.1.

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?

Aargh, wenn du im Interrupt R16 benutzt, muss das vorher gerettet 
werden.
Normalerweise beginnt eine ISR mit:
1
; sichererplatz ist ein beliebiges, sonst unbenutztes register
2
       mov sichererplatz, SREG
3
       push   r16
4
; nun mache ich mit r16 rum
5
; und am ende:
6
      pop     r16
7
      mov     SREG,sichererplatz
8
      reti
Da deine Hauptschleife noch nix tut, ist das im Moment noch nicht 
wichtig. Aber später wunderst du dich.

von Karl H. (kbuchegg)


Lesenswert?

@Spess + @Stefan

Hä?  Hab ich das falsche Datenblatt oder ihr?
Ich verwende das da

http://www.atmel.com/images/doc2545.pdf


Abschnitt 7.6
1
This Stack space in the data SRAM must be defined by the program
2
before any subroutine calls are executed or interrupts are enabled.
3
The Stack Pointer must be set to point above 0x0100, preferably RAMEND.

von Jochen (Gast)


Lesenswert?

So, Stackpointer ergänzt. Außerdem habe ich r16 sowie sreg in der 
Interruptroutine gesichet und wieder hergestellt.
Funktioniert immer noch nicht.

von Jochen (Gast)


Lesenswert?

Fehler gefunden. Ich habe nur 2 USB Ports und habe daher mein AVR ISP 
MKII herausgezogen und den USB seriell Wandler eingesteckt. Aber 
anscheinend hält der stromlose Programmer den Controller im Reset.
ARGH
Vielen Dank für eure Hilfe!

von Stefan E. (sternst)


Lesenswert?

Karl Heinz Buchegger schrieb:
> Hä?  Hab ich das falsche Datenblatt oder ihr?
> Ich verwende das da

Und dort unter 7.6.1 "Initial Value".

Der Text suggeriert in der Tat was anderes. Ist meiner Meinung nach aber 
nur als Hinweis gedacht, wo der Stack-Pointer starten muss, ohne dabei 
zu erwähnen, dass er bereits einen passenden Default-Wert hat.

In "meinem" Datenblatt sieht der Text übrigens so aus:
1
The Stack in the data SRAM must be defined by the program before any
2
subroutine calls are executed or interrupts are enabled. Initial Stack
3
Pointer value equals the last address of the internal SRAM and the Stack
4
Pointer must be set to point above start of the SRAM, see Table 7-3 on
5
page 18.

von Karl H. (kbuchegg)


Lesenswert?

Stefan Ernst schrieb:
> Karl Heinz Buchegger schrieb:
>> Hä?  Hab ich das falsche Datenblatt oder ihr?
>> Ich verwende das da
>
> Und dort unter 7.6.1 "Initial Value".

Hmm.
Anscheinend gibt es da mehrere Versionen. Goggle hat mir diesen Hit als 
ersten Treffer bei Atmel rausgeworfen

7.6.1 ist bei mir
7.6.1 SPH and SPL – Stack pointer high and stack pointer low register

Und Initial Values werden da keine erwähnt.

von Thomas E. (thomase)


Lesenswert?

Karl Heinz Buchegger schrieb:
> Und Initial Values werden da keine erwähnt.
Steht doch darunter:
Initial Value: RAMEND

mfg.

von Karl H. (kbuchegg)


Lesenswert?

Thomas Eckmann schrieb:
> Karl Heinz Buchegger schrieb:
>> Und Initial Values werden da keine erwähnt.
> Steht doch darunter:
> Initial Value: RAMEND
>

Autsch. Du hast recht.
Wenn man mir freundlich mit dem Brett den Hinterkopf tätschelt, dann seh 
ich das sogar :-)
Danke.

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.