Forum: Mikrocontroller und Digitale Elektronik Zeichen aus SRAM per UART senden


von Cyrill M. (kerik)


Angehängte Dateien:

Lesenswert?

Hallo!

Ich beschäftige mich gerade mit der Adressierung der Speicherbereiche 
bei Atmega8. Ich habe dazu ein sehr kurzes Assembler Programm 
geschrieben, wo mehrere Zeichen per UART vom PC empfangen und im SRAM 
abgegelegt werden. Gleich danach werden die gleichen Zeichen aus dem 
SRAM abgelesen und wieder per UART an PC gesendet.
Das Problem ist jetzt - die beiden letzten Zeichen sind nicht die, die 
am Anfang gesendet worden sind. Egal was für eine Zahl ich bei "counter" 
eingebe und viel mehr Zeichen im SRAM speichere. Die letzten beiden 
bleiben immer mit Fehlern.
Hoffentlich kann einer mir helfen oder wenigstens ein Tipp geben. 
Vielleicht ist die Sache viel einfacher als ich denke!
Hier ist mein Code:
1
.include "m8def.inc"
2
3
.def    temp = r16
4
.def counter = r17
5
6
.DSEG
7
8
var1:   .BYTE 22
9
10
11
.CSEG  
12
anfang:   
13
     ldi counter,5                     ; 5 Zeichen uf einmal senden
14
15
     ldi temp, HIGH(23)                ; UBRR = 23 bei Baud 9600 und
16
     out UBRRH, temp                   ; F_CPU = 3686400 Hz
17
18
     ldi temp, LOW(23)
19
     out UBRRL, temp
20
21
     ldi temp, (1<<URSEL) | (1<<UCSZ0) | (1<<UCSZ1)
22
     out UCSRC, temp                   ; 8 bit Uebertragung
23
24
     sbi UCSRB, TXEN                   ; Empfaenger und Sender freischalten
25
     sbi UCSRB, RXEN
26
27
;___________Stack pointer setzen_____________________
28
29
     ldi temp, HIGH(RAMEND) 
30
     out SPH, temp
31
32
     ldi temp, LOW(RAMEND)
33
     out SPL, temp
34
;_____________________________________________________
35
36
     ldi ZH, HIGH(var1)                
37
     ldi ZL, LOW(var1)
38
39
start:
40
     rcall RC
41
     ldi YH, HIGH(var1)
42
     ldi YL, LOW(var1)
43
44
loop:
45
     ld temp, Y+
46
     rcall UP
47
     cp YL, ZL
48
     cpc YH, ZH
49
     brne loop                        ;Beide Pointer gleich? -> dann fertig
50
     rjmp anfang
51
52
;*********************************************************************
53
;UNTERPROGRAMME
54
;*********************************************************************
55
56
RC:                            ;Zeichen werden empfangen bis Counter=0
57
     sbis UCSRA, RXC           ;und im SRAM gespeichert
58
     rjmp RC
59
     dec counter
60
     in temp, UDR
61
     st Z+, temp
62
     tst counter
63
     brne RC
64
     ret
65
       
66
67
UP:                             ;Ausgabe der Zeichen
68
     sbis UCSRA, UDRE
69
     rjmp UP
70
     out UDR, temp
71
     ret
Zuvor hat die UART-Verbindung bei mir super funktioniert. Der Fehler 
tritt nur dann auf, wenn ich die Daten im SRAM speichere! Vielen Dank 
schon mal im vorraus!

MfG
Kerik

von Helfer (Gast)


Lesenswert?

Das Programm ist komisch. Spontan frage ich mich nach dem Sinn dieser 
Zeilen:

     ldi temp, HIGH(23)                ; UBRR = 23 bei Baud 9600 und
     out UBRRH, temp                   ; F_CPU = 3686400 Hz

     ldi temp, LOW(23)
     out UBRRL, temp

Und warum die Stackinitialisierung so spät gemacht wird. Das sieht eher 
nach einem zusammengestückelten Werk aus zwei Quellen aus als nach einem 
wohlüberlegten Programmablauf.

von Cyrill M. (kerik)


Lesenswert?

Helfer schrieb:
> Das Programm ist komisch. Spontan frage ich mich nach dem Sinn dieser
> Zeilen:
>
>      ldi temp, HIGH(23)                ; UBRR = 23 bei Baud 9600 und
>      out UBRRH, temp                   ; F_CPU = 3686400 Hz
>
>      ldi temp, LOW(23)
>      out UBRRL, temp

Hier wird der UART Baud Rate Register initialisiert. Bei einer BAUD von 
9600 und dem Takt 3686400 beträgt der Wert 23.
Das kommt aus der Gleichung F_CPU/(16*BAUD)-1

Helfer schrieb:
> Und warum die Stackinitialisierung so spät gemacht wird.

Weil der Stackpointer vorher nicht gebraucht wird. Ist doch egal wo man 
den initialisiert, sobald das vor der ersten Benutzung gemacht wird, 
oder irre ich mich da?

Das Programm wurde wirklich nur dazu geschrieben, um SRAM-Adressierung 
und UART Benutzung zu praktizieren. Mittlerweile bin ich etwas weiter - 
ich habe zum Test einfach eine Verzögerung von mehreren Milisekunden in 
die Loop-Schleife eingebaut und jetzt kriege ich alle Zeichen richtig 
angezeigt. Die Lösung ist also da, aber wieso das so ist, verstehe ich 
immer noch nicht.

MfG
Kerik

von Route_66 (Gast)


Lesenswert?

Hallo!
Wenn Du nach
     out UDR, temp
sofort
     ret
machst und nicht wartest bis alle Zeichen auch wirklich gesendet sind, 
sondern gleich wieder auf Anfang springst, wird dem UART Senderegister 
und dem Schieberegister der "Hals abgedreht"

Oder anders: Das vorletzte Zeichen ist noch im Schieberegister das 
letzte im UDR und du springst auf anfang und initialisierst den UART 
neu. Du musst im Programm UP oder zwischen diesen Zeilen
    brne loop                        ;Beide Pointer gleich? -> dann 
fertig
     rjmp anfang

warten, bis das letzte Zeichen raus ist, und dann erst auf anfang 
springen.

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.