Forum: Mikrocontroller und Digitale Elektronik Atmega88 RS232 Assembler Problem


von A. B. (developer_x)


Angehängte Dateien:

Lesenswert?

Sehr geehrtes Forum,
ich habe folgenden Versuchsaufbau:
Einen Atmega88, angeschlossen an einen MAX232, welcher
über RS232 an einen PC angeschlossen ist, und am PC
über das Programm HTerm empfangen wird.

Ich verwende folgenden Code:
1
.include "m88def.inc" // Definitionsdatei für den Prozessortyp einbinden
2
3
/*
4
  RS232_TEST
5
6
  Frequenz 1 MHZ
7
8
  Es sollen Zeichen empfangen werden, 
9
  und das Byte an PORTB ausgegeben werden.
10
*/
11
12
// Richtung der IO Ports definieren
13
LDI R16, 0b11111111    // 1=Output, 0=Input
14
OUT DDRB, R16
15
16
// Stackpointer initialisieren
17
LDI R16, low(RAMEND)
18
OUT SPL, R16
19
LDI R16, high(RAMEND)
20
OUT SPH, R16
21
22
// RS232 Definitionen
23
.equ F_CPU = 1000000                            ; Systemtakt in Hz
24
.equ BAUD  = 4800                               ; Baudrate
25
 
26
; Berechnungen
27
.equ UBRR_VAL   = ((F_CPU+BAUD*8)/(BAUD*16)-1)  ; clever runden
28
.equ BAUD_REAL  = (F_CPU/(16*(UBRR_VAL+1)))     ; Reale Baudrate
29
.equ BAUD_ERROR = ((BAUD_REAL*1000)/BAUD-1000)  ; Fehler in Promille
30
 
31
.if ((BAUD_ERROR>10) || (BAUD_ERROR<-10))       ; max. +/-10 Promille Fehler
32
  .error "Systematischer Fehler der Baudrate grösser 1 Prozent und damit zu hoch!"
33
.endif
34
35
//  Transceiver Definitionen
36
.def EMPFANGEN_BYTE = R16
37
.def ZU_SENDEN_BYTE = R17
38
39
// Main Methode
40
MAIN:
41
//  RS232 Initialisieren
42
  RCALL RS232_INIT
43
44
//  AKTIVIEREN von SENDEN UND EMPFANGEN
45
  RCALL ACTIVATE_RS232_TRANSMIT
46
  RCALL ACTIVATE_RS232_RECEIVE
47
48
  SBI PORTB, PINB0
49
50
//  EMPFANGEN von BYTE
51
  RCALL RECEIVE_BYTE
52
53
//  Warte eine Sekunde
54
  RCALL WAIT_SEC
55
56
//  LED SIGNAL
57
  CBI PORTB, PINB0
58
  SBI PORTB, PINB1
59
60
//  Zurücksenden der Nachricht
61
  MOV ZU_SENDEN_BYTE, EMPFANGEN_BYTE
62
  RCALL TRANSMIT_BYTE
63
RJMP MAIN
64
65
//   RS232 Initialisierung
66
RS232_INIT:
67
//  Baudrate einstellen
68
  LDI R16, HIGH(UBRR_VAL)
69
  STS UBRR0H, R16
70
  LDI R16, LOW(UBRR_VAL)
71
  STS UBRR0L, R16
72
73
//  Frame Format einstellen (8 Bit)
74
  LDI R16, (1<<UCSZ01)|(1<<UCSZ00)
75
  STS UCSR0C, R16
76
RET
77
78
//  RS232 Steuerungsfunktionen
79
ACTIVATE_RS232_TRANSMIT:
80
  LDS R20, UCSR0B
81
  SBR R20, (1<<TXEN0)
82
  STS UCSR0B, R20
83
RET
84
85
DEACTIVATE_RS232_TRANSMIT:
86
  LDS R20, UCSR0B
87
  CBR R20, (1<<TXEN0)
88
  STS UCSR0B, R20
89
RET
90
91
ACTIVATE_RS232_RECEIVE:
92
  LDS R20, UCSR0B
93
  SBR R20, (1<<RXEN0)
94
  STS UCSR0B, R20
95
RET
96
97
DEACTIVATE_RS232_RECEIVE:
98
  LDS R20, UCSR0B
99
  CBR R20, (1<<RXEN0)
100
  STS UCSR0B, R20
101
RET
102
103
TRANSMIT_BYTE:
104
  LDS  R20, UCSR0A
105
  SBRS R20, UDRE0
106
  RJMP TRANSMIT_BYTE
107
108
  STS UDR0, ZU_SENDEN_BYTE
109
RET
110
111
RECEIVE_BYTE:
112
  LDS  R20, UCSR0A
113
  SBRS R20, RXC0
114
  RJMP RECEIVE_BYTE
115
116
  LDS EMPFANGEN_BYTE, UDR0
117
RET
118
119
//  Warte Methoden
120
WAIT_SEC:
121
  LDI R21,255
122
123
  WAIT_SEC_22:
124
  RCALL WAIT_SEC_2
125
  DEC R21
126
  BRNE WAIT_SEC_22
127
RET
128
129
WAIT_SEC_2:
130
  LDI R20,255
131
132
  WAIT_SEC_21:
133
  RCALL WAIT_SEC_1
134
  DEC R20
135
  BRNE WAIT_SEC_21
136
RET
137
138
WAIT_SEC_1:
139
  NOP
140
  NOP
141
  NOP
142
  NOP
143
  NOP
144
  NOP
145
  NOP
146
  NOP
147
  NOP
148
  NOP
149
RET

Folgendes soll geschehen:
Grüne LED leuchtet,
ich sende ein Zeichen vom PC aus,
eine Sekunde nach Ankommen geht die grüne aus, und die rote leuchtet,
und das empfangene Byte wird zurückgesendet

Folgendes geschieht:
Grüne LED leuchtet,
ich sende ein Zeichen vom PC aus,
eine Sekunde nach Ankommen leuchtet die Rote, die grüne seltsamerweise 
immer noch,
als Antwort immer das gleiche, 216, 195

Ich wäre dankbar für eure Hilfe, wenn mir jemand erklären könnte was ich 
falsch mache, danke für eure Hilfe,
m.f.G:: Developer_X

von Karl H. (kbuchegg)


Lesenswert?

Bevor wir uns auf das Programm stürzen, erst mal die naheliegenste 
Frage.
Hast du schon getestet, ob deine Serielle grundsätzlich funktioniert?

D.h. du hast ein Programm, welches ständig ein zb 'U' sendet und an 
deinem Terminal taucht auch tatsächlich ein 'U' auf?

von A. B. (developer_x)


Lesenswert?

Problem gelöst,
lag daran, dass die Mainschleife wieder von vorne beginnt,
was sie gar nicht sollte.

Danke trotzdem,
m.f.G.: Developer_X

@KBuchegg:
das hat schon geklappt, ich wollte so etwas wie ein Echo programmieren,
als kleine spielerei, man sendet ein zeichen, und eine sekunde kommt es 
wieder

: Bearbeitet durch User
von c-hater (Gast)


Lesenswert?

A. B. schrieb:

> Problem gelöst,
> lag daran, dass die Mainschleife wieder von vorne beginnt,
> was sie gar nicht sollte.

Quatsch mit Soße. Es lag daran, dass du die Initialisierung in der 
Hauptschleife gemacht hast, statt davor, wo sie hingehört.

Nicht die böse Hauptschleife ist schuld, sondern einfach nur du selber! 
So einfach ist das.

Das ist das Schlimme bei Assembler: du kannst dich nicht auf 
irgendwelche kaputte Libs oder sonstige schrägen Schutzbehauptungen 
herausreden wie die regulären C&P-C-ler. Die CPU macht (bei einwandfrei 
funktionierender Hardware) immer genau das, was du ihr sagst und das ist 
eben auch exakt das, was du hinschreibst.

D.h.: wenn's nicht so funktioniert, wie du wolltest, brauchst du 
(fast) niemals aufwendig nach einem Schuldigen suchen: in 99,9999% der 
Fälle warst du es selbst...

Hier, in diesem konkreten Fall, ist aber wohl ein besonderes Problem 
akut, kein Problem der Sprache oder der Maschine, sondern ein rein 
kognitives.

Du versuchst offensichtlich, Code-Einrückungen der Art zu erzeugen, wie 
sie in einer strukturierten Programmiersprache sinnvoll wären. Das kann 
in Asm nur schief gehen, weil Asm eben gerade keine strukturierte 
Programmiersprache, sondern von Natur aus in einer "GOTO-Hölle" gefangen 
ist. Jedenfalls dann, wenn man die Peformance-Vorteile der Sprache 
wirklich nutzen möchte...

Deine Gewohnheiten beim Lesen von Code sind aber offensichtlich stark 
von einer strukturierten Sprache geprägt. Vermutlich war genau das das 
Problem, was es dir unmöglich gemacht hat, selber zu erkennen, dass die 
Initialisierung innerhalb der Schleife liegt...

Einzig mögliche Abhilfe: Programmieren bis der Arzt kommt und dabei aus 
Fehlern lernen. Mit der Zeit gewöhnt man sich auch an grundsätzlich 
verschiedene Stile zu Code-Einrückung. Man muß einfach nur oft genug in 
den verschiedenen Welten programmieren.

Oder anders ausgedrückt: Eine reine Fleißaufgabe. Oder auch: noch'n 
Winter und auch du kommst dahinter...

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.