Forum: Mikrocontroller und Digitale Elektronik UART + Taschenrechner Teil2


von Flo S. (tuxianer)


Lesenswert?

Hi,
ich mach der Übsicht halber mal nen neuen Thread auf. Also das UArt 
klappt nur komme ich nicht weiter als bis zur ersten LED. Der Code ist 
der:

1
.include "m32def.inc"                    ; bzw. 2333def.inc
2
 
3
.def temp    = R16
4
.def Data    = R17
5
.def Count   = R18
6
7
8
.equ CLOCK   = 16000000
9
.equ BAUD    = 9600
10
.equ UBRRVAL = CLOCK/(BAUD*16)-1
11
 
12
.org 0x00
13
        rjmp main
14
 
15
.org URXCaddr                             ; Interruptvektor für UART-Empfang
16
        rjmp Recive1
17
18
19
;Hauptprogramm
20
main:
21
        ldi temp, LOW(RAMEND)
22
        out SPL, temp
23
        ldi temp, HIGH(RAMEND)
24
        out SPH, temp
25
26
        ldi temp, 0xFF                    ; Port D = Ausgang
27
        out DDRD, temp
28
29
        ldi temp, 0b01100000
30
        out PortD, temp
31
 
32
        ; Baudrate einstellen
33
        ldi temp, HIGH(UBRRVAL)
34
        out UBRRH, temp
35
        ldi temp, LOW(UBRRVAL)
36
        out UBRRL, temp
37
 
38
        ; Frame-Format: 8 Bit
39
        ldi r16, (1<<URSEL)|(1<<USBS)|(1<<UCSZ1)|(1<<UCSZ0)
40
        out UCSRC, temp
41
 
42
        sbi UCSRB, RXCIE                  ; Interrupt bei Empfang
43
        sbi UCSRB, RXEN                   ; RX (Empfang) aktivieren
44
        sbi UCSRB, TXEN                ; TX (Senden) aktivieren 
45
        
46
        sei                               ; Interrupts global aktivieren
47
        
48
loop:  
49
  
50
    rjmp loop                         ; Endlosschleife
51
52
Recive1:
53
54
       sbis UCSRA, RXC    
55
     rjmp  Recive1
56
       in Data, UDR                      ; Empfangenes Byte in Data speichern
57
     cpi  Data, 0x15
58
     brne Ende
59
     
60
     rjmp header_init
61
62
       Ende:
63
     reti                               ; zurück zum Hauptprogramm
64
65
66
Recive:
67
68
       sbis UCSRA, RXC    
69
     rjmp  Recive
70
       in Data, UDR                      ; Empfangenes Byte in Data speichern
71
     ret  
72
73
74
75
Transmit:
76
77
       sbis UCSRA, UDRE                   ; Warten bis UDR ist
78
       rjmp Transmit
79
       out UDR, Data                      ; Data senden
80
     ret
81
82
       
83
84
header_init:
85
86
     cbi UCSRB, RXCIE                   ; Interrupt bei Empfang deaktivieren
87
     cbi  PORTD, 5
88
     
89
     ldi  Data, 0x13
90
     rcall Transmit
91
     ldi  Count, 0x31                    ; Counter der bytes zählt aktivieren
92
93
header_recive:
94
       
95
     
96
       rcall Recive
97
     dec Count
98
     cpi Count, 0
99
     brne header_recive
100
     cbi  PORTD, 6
101
     ldi Data, 0x06
102
     rcall Transmit
103
    
104
    
105
106
107
108
Neustart:
109
110
    sbi UCSRB, RXCIE                   ; Interrupt bei Empfang aktivieren
111
    rjmp loop



hier der Link zum Protokol:

http://users.pandora.be/gp/casio/index.html

von Condi (Gast)


Lesenswert?

Ich denke mal das Problem liegt hier:

header_recive:


       rcall Recive
     dec Count
     cpi Count, 0
     brne header_recive
     cbi  PORTD, 6
     ldi Data, 0x06
     rcall Transmit

entweder du machst das "cpi Count, 0" weg oder ersetzt es durch
"cpi count, 0x00"

von Johannes M. (johnny-m)


Lesenswert?

Condi wrote:
> entweder du machst das "cpi Count, 0" weg oder ersetzt es durch
> "cpi count, 0x00"
Ersetze XYZ durch XYZ oder "den Teufel mit Beelzebub austreiben"? Die 
beiden Ausdrücke sind gleichwertig (und in Assembler sogar tatsächlich, 
da nicht Case-sensitiv und dementsprechend count = Count)...

von Axel R. (Gast)


Lesenswert?

kann man "Taschenrechner Teil 1.0" auch mal sehen??
Ich habe zufällig auch einen CFX-9850...

AxelR.

von Condi (Gast)


Lesenswert?


von Axel R. (Gast)


Lesenswert?

Du springst in der Receive Intrerruptroutine raus aus dieser, falls dein 
eingehendes Datenbyte 0x15 ist. Da Du nie wieder in die INtRoutine 
zurückspringst, wird kein RETI aufgerufen und das I-Flag wird nicht 
gelöscht. Daher können keine weiteren Interrupts abgearbeitet werden.

Pack den Transmitkram in die Hauptroutine und frage dort ein bit im 
Register 20 oder so ab. Ist dieses gesetzt, weil 0x15 empfangen wurde, 
machst Du den Job in der Hauptschleife.

Siehe ...HanneS... "Jobflag
http://www.mikrocontroller.net/search?query=jobflag&forums%5B%5D=1&forums%5B%5D=9&forums%5B%5D=10&forums%5B%5D=2&forums%5B%5D=4&forums%5B%5D=3&forums%5B%5D=6&forums%5B%5D=17&forums%5B%5D=11&forums%5B%5D=8&forums%5B%5D=12&forums%5B%5D=14&forums%5B%5D=7&forums%5B%5D=5&forums%5B%5D=15&forums%5B%5D=13&forums%5B%5D=16&max_age=-

AxelR.

8N1 mit 9K6- bist Du sicher???

von Otto (Gast)


Lesenswert?

Hallo Florentin,

weshalb fängst Du wieder von vorne und mit den selben Problemen an ?

Diesmal rettest Du gar nichts auf den Stack und plötzlich nimmst

Du nur noch 1 Stoppbit....


Gruss Otto

von Axel R. (Gast)


Angehängte Dateien:

Lesenswert?

hab das Blatt mal aufn Scanner gelegt...

Scheint aber schon mal diskutiert worden zu sein, oder? (klar, im Teil 1 
eben;-)) )

von Condi (Gast)


Lesenswert?

Laut meinem Mega32 Datenblatt ist:
ldi r16, (1<<URSEL)|(1<<USBS)|(1<<UCSZ1)|(1<<UCSZ0)

8n2

Der Code ist  zwar nicht so schön, aber er sollte funktionieren. Wenn 
0x15 empfangen wurde, wir der Interrupt disabled und dann wird immer 
geprüft ob wieder was empfangen wurde.

Bei Neustart sollte halt anstelle des rjmp loop ein reti stehen. Das 
Problem liegt in der Schleife, die ich schon erwähnte, die scheint nicht 
0 zu werden.
Du solltest mehr Anzeigen in die Schleifen machen, damit du mehr infos 
bekommst.

von Flo S. (tuxianer)


Lesenswert?

so ich habe lange nicht hier reingeschaut. hier der aktuelle Code:

1
.include "m32def.inc"                    ; bzw. 2333def.inc
2
 
3
.def temp    = R16
4
.def Data    = R17
5
.def Count   = R18
6
7
8
.equ CLOCK   = 16000000
9
.equ BAUD    = 9600
10
.equ UBRRVAL = CLOCK/(BAUD*16)-1
11
 
12
.org 0x00
13
        rjmp main
14
 
15
.org URXCaddr                             ; Interruptvektor für UART-Empfang
16
        rjmp Recive1
17
18
19
;Hauptprogramm
20
main:
21
        ldi temp, LOW(RAMEND)
22
        out SPL, temp
23
        ldi temp, HIGH(RAMEND)
24
        out SPH, temp
25
26
        ldi temp, 0xFF                    ; Port D = Ausgang
27
        out DDRD, temp
28
29
        ldi temp, 0b01100000
30
        out PortD, temp
31
 
32
        ; Baudrate einstellen
33
        ldi temp, HIGH(UBRRVAL)
34
        out UBRRH, temp
35
        ldi temp, LOW(UBRRVAL)
36
        out UBRRL, temp
37
 
38
        ; Frame-Format: 8 Bit
39
        ldi r16, (1<<URSEL)|(1<<USBS)|(1<<UCSZ1)|(1<<UCSZ0)
40
        out UCSRC, temp
41
 
42
        sbi UCSRB, RXCIE                  ; Interrupt bei Empfang
43
        sbi UCSRB, RXEN                   ; RX (Empfang) aktivieren
44
        sbi UCSRB, TXEN                ; TX (Senden) aktivieren 
45
        
46
        sei                               ; Interrupts global aktivieren
47
        
48
loop:  
49
  
50
    rjmp loop                         ; Endlosschleife
51
52
Recive1:
53
54
       in Data, UDR                      ; Empfangenes Byte in Data speichern
55
     cpi  Data, 0x15
56
     brne Ende
57
     
58
     rjmp header_init
59
60
       Ende:
61
     reti                               ; zurück zum Hauptprogramm
62
63
64
Recive:
65
66
       sbis UCSRA, RXC
67
     rjmp Recive
68
       in Data, UDR                      ; Empfangenes Byte in Data speichern
69
     ret  
70
71
72
73
Transmit:
74
75
       sbis UCSRA, UDRE                   ; Warten bis UDR ist
76
       rjmp Transmit
77
       out UDR, Data                      ; Data senden
78
     ret
79
80
       
81
82
header_init:
83
84
     cbi UCSRB, RXCIE                   ; Interrupt bei Empfang deaktivieren
85
    
86
87
88
ldi temp, 10
89
wait0:
90
                push temp
91
                ldi temp, 200
92
wait0_1:                               
93
                nop
94
                nop
95
                nop
96
                nop
97
                nop
98
                dec temp
99
                cpi temp, 0
100
                brne wait0_1
101
                pop temp
102
                dec temp
103
                cpi temp, 0
104
                brne wait0
105
106
107
108
     
109
     ldi  Data, 0x13
110
     rcall Transmit
111
     
112
     ldi  Count, 49                    ; Counter der bytes zählt aktivieren
113
114
       cbi  PORTD, 5
115
header_recive:
116
       
117
     
118
       rcall Recive
119
     
120
     dec Count
121
     cpi Count, 0
122
     brne header_recive
123
     
124
125
126
       ldi temp, 10
127
wait1:
128
                push temp
129
                ldi temp, 200
130
wait1_1:                               
131
                nop
132
                nop
133
                nop
134
                nop
135
                nop
136
                dec temp
137
                cpi temp, 0
138
                brne wait1_1
139
                pop temp
140
                dec temp
141
                cpi temp, 0
142
                brne wait1
143
144
145
146
     ldi Data, 0x06
147
     rcall Transmit
148
     
149
150
151
152
153
     ldi Count, 16
154
data_recive:
155
     rcall Recive
156
     dec count
157
     cpi Count, 0
158
     brne data_recive
159
160
161
162
163
164
ldi temp, 10
165
wait2:
166
                push temp
167
                ldi temp, 200
168
wait2_1:                               
169
                nop
170
                nop
171
                nop
172
                nop
173
                nop
174
                dec temp
175
                cpi temp, 0
176
                brne wait2_1
177
                pop temp
178
                dec temp
179
                cpi temp, 0
180
                brne wait2
181
182
183
184
     ldi Data, 0x06
185
     rcall Transmit
186
187
     
188
cbi  PORTD, 6
189
190
191
ldi  Count, 50
192
193
end_header:
194
       
195
       rcall Recive
196
     
197
     dec Count
198
     cpi Count, 0
199
     brne end_header
200
    
201
202
203
204
ldi temp, 10
205
wait3:
206
                push temp
207
                ldi temp, 200
208
wait3_1:                               
209
                nop
210
                nop
211
                nop
212
                nop
213
                nop
214
                dec temp
215
                cpi temp, 0
216
                brne wait3_1
217
                pop temp
218
                dec temp
219
                cpi temp, 3
220
                brne wait3
221
222
223
224
225
226
227
     ldi Data, 0x06
228
     rcall Transmit
229
230
231
  
232
      
233
234
Neustart:
235
236
rjmp Neustart
237
238
    sbi UCSRB, RXCIE                   ; Interrupt bei Empfang aktivieren
239
    rjmp loop



er hängt bei data_recive...die LED geht nicht an. ansonsten kein Fehler 
auf dem Rechner er hängt sich nur auf

von Condi (Gast)


Lesenswert?

Was sagt hyperterm?

von Flo S. (tuxianer)


Lesenswert?

so ich habe die Warteschleifen jetzt 20mal durchlaufen lassen und es 
geht!!!

von Flo S. (tuxianer)


Lesenswert?

und mit reti am ende kann ich das ganze sogar mehrfach hinterienander 
machen...

von Condi (Gast)


Lesenswert?

Die Warteschleifen sind unnütz. Da du den HW UART nimmst, waret der bis 
die Hardware bereit ist. Hast du auch die richtigen Fuse bits gesetzt?

von Flo S. (tuxianer)


Lesenswert?

also ohne Warteschleifen gehts nicht!


und welche Fusebits meinst du?

von Otto (Gast)


Lesenswert?

Du meinst, dass Du ohne die Warteschleifen nichts
an den LEDS siehst oder ?

Otto

von Flo S. (tuxianer)


Lesenswert?

erstens das und zweiten kommt aud dem Rechner kein Done. Also ich sehe 
nur die erste ohne Warteschleife.

von Condi (Gast)


Lesenswert?

Na die von dem Mega32. Schonmal im Datenblatt nachgelesen?
Vom Werk aus läuft der mit 1Mhz internem Clock.

von Flo S. (tuxianer)


Lesenswert?

die habe ich auf 16 MHz Quarz gestellt...du musst schon sagen welche 
fusebits. ich kann ja nciht erahnen, dass du die für den tackt meinst

von Michael F. (startrekmichi)


Lesenswert?

Wegen den Warteschleifen: Der Taschenrechner ist so lahm, dass der µC 
sich etwas gedulden muss, bevor er die Handshakes usw senden darf. An 
sonsten ist der Taschenrechner noch nicht zum Empfangen bereit und das 
Gesendete geht verloren.
Theoretisch könnte man den µC wahrscheinlich mit 4MHz oder so laufen 
lassen, würde locker reichen. Vielleicht geht sogar noch weniger.

von Axel R. (Gast)


Lesenswert?

nop
                dec temp
                cpi temp, 0
                brne wait0_1

wenn Du temp verringerst, wird das ZeroFlag Erst gesetzt, wenn temp NULL 
ist.

Daher ja auch BRNE. Du brauchst keinen zusätzlichen Vergleich mittels 
CPI temp,0 machen. Das macht der Controller von Hause aus.

dec temp
brne wait0_1

reicht daher.

von Condi (Gast)


Lesenswert?

Stimmt eigentlich, die Bootloader FuseBits hätten es auch sein können. 
Tschuldige.

@Michael

Warum hast du in deinem Programm keine Warteschleifen drin?
Ich war immer der Meinung 9600 Baud ist 9600 Baud egal ob der MC mit 
1Mhz läuft oder 16Mhz, zumindest bei HW-UART.

von Michael F. (startrekmichi)


Lesenswert?

vom µC aus gesehen stimmt das auch. Nur beim Taschenrechner anscheinend 
nicht. (Ev hat der nen Software-uart oder so was.)
Im Protokoll isses so, dass der GTR (=Taschenrechner) etwas sendet und 
dann der µC das bestätigen soll. Wenn das Bestätigungsbyte aber zu 
schnell nach Empfang der Daten gesendet wird, hat der GTR anscheinend 
ein Problem und erkennt das Byte nicht.

von Flo S. (tuxianer)


Lesenswert?

@ Michael Frangenberg


danke nochmal für deine Hilfe gestern. Mein ICQ ging irgendwie nichtmehr 
an.


Ich werde heute mal versuchen die Daten zu speichern und wenn das Klappt 
das Programm für allgemeine Übertragungen bereit machen also das mit der 
Datenlänge aus header etc. Am besten wäre je eigentlich zum speichern 
nen externer EEprom oder Sram. Das müsst ich mir noch besorgen.

von Flo S. (tuxianer)


Lesenswert?

so hier mal mit speicher Funktion:

1
.include "m32def.inc"                    ; bzw. 2333def.inc
2
 
3
.def temp    = R16
4
.def Data    = R17
5
.def Count   = R18
6
7
8
9
.equ CLOCK   = 16000000
10
.equ BAUD    = 9600
11
.equ UBRRVAL = CLOCK/(BAUD*16)-1
12
 
13
.org 0x00
14
        rjmp main
15
 
16
.org URXCaddr                             ; Interruptvektor für UART-Empfang
17
        rjmp Recive1
18
19
20
;Hauptprogramm
21
main:
22
        ldi temp, LOW(RAMEND)
23
        out SPL, temp
24
        ldi temp, HIGH(RAMEND)
25
        out SPH, temp
26
27
        ldi temp, 0xFF                    ; Port D = Ausgang
28
        out DDRD, temp
29
30
        ldi temp, 0b01100000
31
        out PortD, temp
32
 
33
        ; Baudrate einstellen
34
        ldi temp, HIGH(UBRRVAL)
35
        out UBRRH, temp
36
        ldi temp, LOW(UBRRVAL)
37
        out UBRRL, temp
38
 
39
        ; Frame-Format: 8 Bit
40
        ldi r16, (1<<URSEL)|(1<<USBS)|(1<<UCSZ1)|(1<<UCSZ0)
41
        out UCSRC, temp
42
 
43
        sbi UCSRB, RXCIE                  ; Interrupt bei Empfang
44
        sbi UCSRB, RXEN                   ; RX (Empfang) aktivieren
45
        sbi UCSRB, TXEN                ; TX (Senden) aktivieren 
46
        
47
        sei                               ; Interrupts global aktivieren
48
        
49
loop:  
50
51
    ldi temp, 0b01100000
52
        out PortD, temp
53
  
54
    rjmp loop                         ; Endlosschleife
55
56
Recive1:
57
58
       in Data, UDR                      ; Empfangenes Byte in Data speichern
59
     cpi  Data, 0x15
60
     brne Ende
61
     
62
     rjmp header_init
63
64
       Ende:
65
     reti                               ; zurück zum Hauptprogramm
66
67
68
Recive:
69
70
       sbis UCSRA, RXC
71
     rjmp Recive
72
       in Data, UDR                      ; Empfangenes Byte in Data speichern
73
     ret  
74
75
76
77
Transmit:
78
    
79
80
                    ldi temp, 20
81
       wait1:
82
                    push temp
83
                    ldi temp, 200
84
       wait1_1:                               
85
                    nop
86
                    nop
87
                    nop
88
                    nop
89
                    nop
90
                    dec temp
91
                    cpi temp, 0
92
                    brne wait1_1
93
                    pop temp
94
                    dec temp
95
                    cpi temp, 0
96
                    brne wait1
97
98
99
       sbis UCSRA, UDRE                   ; Warten bis UDR ist
100
       rjmp Transmit
101
       out UDR, Data                      ; Data senden
102
     ret
103
104
       
105
106
header_init:
107
108
       cbi  PORTD, 5
109
    
110
     cbi UCSRB, RXCIE                   ; Interrupt bei Empfang deaktivieren
111
    
112
     
113
     ldi  Data, 0x13
114
     rcall Transmit
115
    
116
    
117
     ldi     r30,LOW(Header)
118
       ldi     r31,HIGH(Header)
119
     ldi  Count, 49                    ; Counter der bytes zählt aktivieren
120
121
       
122
header_recive:
123
       
124
     
125
       rcall Recive
126
     st Z+, Data
127
     
128
     dec Count
129
     cpi Count, 0
130
     brne header_recive
131
     
132
133
134
135
     ldi Data, 0x06
136
     rcall Transmit
137
     
138
139
     ldi Count, 16
140
     ldi r30,LOW(Content)
141
       ldi r31,HIGH(Content)
142
data_recive:
143
     rcall Recive
144
     st Z+, Data
145
     dec count
146
     cpi Count, 0
147
     brne data_recive
148
149
150
151
     ldi Data, 0x06
152
     rcall Transmit
153
154
    
155
156
157
       ldi Count, 50
158
     ldi r30,LOW(End_Header)
159
       ldi r31,HIGH(End_Header)
160
161
end_header_recive:
162
       
163
       rcall Recive
164
     st Z+, Data
165
     dec Count
166
     cpi Count, 0
167
     brne end_header_recive
168
    
169
170
171
172
173
     ldi Data, 0x06
174
     rcall Transmit
175
176
177
178
Check:
179
180
ldi r30,LOW(Content)
181
ldi r31,HIGH(Content)
182
183
ld r19, Z
184
 
185
cpi r19, 2
186
187
brne Neustart
188
189
cbi  PORTD, 6
190
191
192
193
194
  
195
      
196
197
Neustart:
198
199
200
    sbi UCSRB, RXCIE                   ; Interrupt bei Empfang aktivieren
201
    reti
202
203
204
205
206
207
.DSEG                                      ; das Folgende kommt ins SRAM
208
Header:     .BYTE  50
209
Content:    .BYTE  16
210
End_Header: .Byte  50


nur leider will das ni so wie ich will...der vergleich ist nicht 
erfolgreich...

von Otto (Gast)


Lesenswert?

Hallo Florentin,

das kann es auch nicht - aus mehreren Gründen aber der Reihe nach:

Du solltest zuerst mal "aufräumen"

1. vor brne muß kein cpi, wenn Du auf "0" vergleichst
2. den Z-Pointer mußt Du auch initialisieren (z.B. auf Ramstart)
3. es heißt "receive"

Otto

von Flo S. (tuxianer)


Lesenswert?

wie geht das mit dem TPointer? Ok Aufräümen werde ich wohl mal machen...

von Otto (Gast)


Lesenswert?

Hallo Florentin,

auf RAMSTART zu initialisieren geht z.B. so:

Z_INIT:  ldi temp, LOW(RAMSTART)  ; Wert LO initialisieren
  mov ZL, temp         ; Z-Register low
      ldi temp, HIGH(RAMSTART) ;
      mov ZH, temp         ; Z-Register high
  ret

Verstehe es bitte nicht falsch - Du solltest Deinen Code
zuerst mal aufräumen, sonst findet sich evtl. keiner, der
Lust hat, sich da durch zu wühlen.....

Gruss Otto

von Condi (Gast)


Lesenswert?

Welches Modell hast du genau?

@Michael
Du hast 8Mhz verwendet, d.h. du hättest mindestens auch die Hälfte der 
"Waitstates" einlegen müssen. Zumindest (9850, 32kb, schwarz) bei meinem 
funktioniert auch 8n1 und Mega162 mit 14,7Mhz. Naja und mit dem PC 
klappt es ja auch....
Was ich so gefunden habe, scheint der schon mindestens ein UART zu 
haben, nur keine Interrupts bzw. halt deaktiviert.

von Flo S. (tuxianer)


Lesenswert?

hier mal aufgeräumt:
1
.include "m32def.inc"                    ; bzw. 2333def.inc
2
 
3
.def temp    = R16
4
.def Data    = R17
5
.def Count   = R18
6
7
8
9
.equ CLOCK   = 16000000
10
.equ BAUD    = 9600
11
.equ UBRRVAL = CLOCK/(BAUD*16)-1
12
 
13
.org 0x00
14
        rjmp main
15
 
16
.org URXCaddr                             ; Interruptvektor für UART-Empfang
17
        rjmp Receive1
18
19
20
;Hauptprogramm
21
main:
22
        ldi temp, LOW(RAMEND)
23
        out SPL, temp
24
        ldi temp, HIGH(RAMEND)
25
        out SPH, temp
26
27
        ldi temp, 0xFF                    ; Port D = Ausgang
28
        out DDRD, temp
29
30
        ldi temp, 0b01100000
31
        out PortD, temp
32
 
33
        ; Baudrate einstellen
34
        ldi temp, HIGH(UBRRVAL)
35
        out UBRRH, temp
36
        ldi temp, LOW(UBRRVAL)
37
        out UBRRL, temp
38
 
39
        ; Frame-Format: 8 Bit
40
        ldi r16, (1<<URSEL)|(1<<USBS)|(1<<UCSZ1)|(1<<UCSZ0)
41
        out UCSRC, temp
42
 
43
        sbi UCSRB, RXCIE                  ; Interrupt bei Empfang
44
        sbi UCSRB, RXEN                   ; RX (Empfang) aktivieren
45
        sbi UCSRB, TXEN                ; TX (Senden) aktivieren 
46
        
47
        sei                               ; Interrupts global aktivieren
48
        
49
loop:  
50
51
    ldi temp, 0b01100000
52
        out PortD, temp
53
  
54
    rjmp loop                         ; Endlosschleife
55
56
Receive1:
57
58
       in Data, UDR                      ; Empfangenes Byte in Data speichern
59
     cpi  Data, 0x15
60
     brne Ende
61
     
62
     rjmp header_init
63
64
       Ende:
65
     reti                               ; zurück zum Hauptprogramm
66
67
68
Receive:
69
70
       sbis UCSRA, RXC
71
     rjmp Receive
72
       in Data, UDR                      ; Empfangenes Byte in Data speichern
73
     ret  
74
75
76
77
Transmit:
78
    
79
80
                    ldi temp, 20
81
       wait1:
82
                    push temp
83
                    ldi temp, 200
84
       wait1_1:                               
85
                    nop
86
                    nop
87
                    nop
88
                    nop
89
                    nop
90
                    dec temp
91
                    brne wait1_1
92
                    pop temp
93
                    dec temp
94
                    brne wait1
95
96
97
       sbis UCSRA, UDRE                   ; Warten bis UDR ist
98
       rjmp Transmit
99
       out UDR, Data                      ; Data senden
100
     ret
101
102
       
103
104
header_init:
105
106
       cbi  PORTD, 5
107
    
108
     cbi UCSRB, RXCIE                   ; Interrupt bei Empfang deaktivieren
109
    
110
     
111
     ldi  Data, 0x13
112
     rcall Transmit
113
    
114
    
115
     ldi     r30,LOW(Header)
116
       ldi     r31,HIGH(Header)
117
     ldi  Count, 49                    ; Counter der bytes zählt aktivieren
118
119
       
120
header_receive:
121
       
122
     
123
       rcall Receive
124
     st Z+, Data
125
     
126
     dec Count
127
     brne header_receive
128
     
129
     ldi Data, 0x06
130
     rcall Transmit
131
     
132
133
     ldi Count, 16
134
     ldi r30,LOW(Content)
135
       ldi r31,HIGH(Content)
136
data_receive:
137
     rcall Receive
138
     st Z+, Data
139
     dec count
140
     brne data_receive
141
142
     ldi Data, 0x06
143
     rcall Transmit
144
145
       ldi Count, 50
146
     ldi r30,LOW(End_Header)
147
       ldi r31,HIGH(End_Header)
148
149
end_header_receive:
150
       
151
       rcall Receive
152
     st Z+, Data
153
     dec Count
154
     brne end_header_receive
155
156
     ldi Data, 0x06
157
     rcall Transmit
158
159
160
161
Check:
162
163
ldi r30,LOW(Content)
164
ldi r31,HIGH(Content)
165
166
ld r19, Z
167
168
brne Neustart
169
170
cbi  PORTD, 6
171
172
173
Neustart:
174
175
176
    sbi UCSRB, RXCIE                   ; Interrupt bei Empfang aktivieren
177
    reti
178
179
180
181
.DSEG                                      ; das Folgende kommt ins SRAM
182
Header:     .BYTE  50
183
Content:    .BYTE  16
184
End_Header: .Byte  50



mit dem Z-Pointer initialisieren habe ich auch noch nicht ganz 
begriffen. Das habe ich noch nirgendwo gelesen. Aber es scheint logisch.

von Otto (Gast)


Lesenswert?

Hallo Florentin,

der Warteschleife solltest Du ein 2. Register
spendieren und nicht mit "push" und "pop"
arbeiten.

Die im SRAM gespeicherten Konstanten werden
von den Routinen überschrieben - da kann ich
keinen Sinn erkennen.

Beispiel:

den Z-Pointer (R30 und R31) hast Du mittels:

ldi r30,LOW(Content)
ldi r31,HIGH(Content)

auf die Adresse von "content" gelegt.

                       ldi Count, 16
                       ldi r30,LOW(Content)
                       ldi r31,HIGH(Content)
data_receive:          rcall Receive
                       st Z+, Data
                       dec count
                       brne data_receive

mit "st Z+" speicherst Du Daten ab dieser
Adresse und überschreibst damit

"END_Header"

Gruss Otto

von Michael F. (startrekmichi)


Lesenswert?

@Condi
Ich hab meine Platinen mit 7,3728MHz laufen lassen und auch die 
entsprechend langen Warteschleifen eingebaut.

von Flo S. (tuxianer)


Lesenswert?

wieso überschreib ich damit das nächste. Ich verstehe das jetzt so ich 
sezt den Z Pointer auf Content lede Byte für Byte data_receive ein und 
lade anschliesend den Pinter auf die Nächste adresse...

von canbastler (Gast)


Lesenswert?

Hallo,

     ldi r30,LOW(Content)
     ldi r31,HIGH(Content)

data_receive:      rcall Receive
                   st Z+, Data
                   dec count
                   brne data_receive

> sezt den Z Pointer auf Content

ja, aber sndchliessend durchläufst Du
16 x Data_receive und speicherst die Daten
mit Z+ d.h. die Daten werden gespeichert
unter

content
content+1
content+2
..
..

von Flo S. (tuxianer)


Lesenswert?

das ist doch richtig so oder? ich habe für Content 16 Bytes reserviert 
und möchte diese nun nacheinander beschreiben.

von Flo S. (tuxianer)


Lesenswert?

Oder doch nicht? Und wenn es falsch ist wie könnte ich den Code ändern? 
Damit es funktioniert, wie es soll. Ich habe da leider noch nicht soviel 
Erfahrung.

von canbastler (Gast)


Lesenswert?

Doch - Du hattest recht. Rette in der
Interrupt-Routine auch das "SREG"
(siehe Tutorium) auf den Stack

von Flo S. (tuxianer)


Lesenswert?

wieso in der inrerrupt Routine? Die wird doch vor dem speichern und 
laden aufgerufen...

ps: das war doch das Status register...wo stand das nochmal im tut?

von canbastler (Gast)


Lesenswert?

weil ansonsten nach der Rückkehr zur normalen Bearbeitung ein Ergebnis 
fehlen könnte: 
http://www.mikrocontroller.net/articles/AVR-Tutorial:_Interrupts

von Flo S. (tuxianer)


Lesenswert?

ich habs jetzt so gemacht. aber es geht leider immer noch nicht.

1
.include "m32def.inc"                    ; bzw. 2333def.inc
2
 
3
.def temp    = R16
4
.def Data    = R17
5
.def Count   = R18
6
7
8
9
.equ CLOCK   = 16000000
10
.equ BAUD    = 9600
11
.equ UBRRVAL = CLOCK/(BAUD*16)-1
12
 
13
.org 0x00
14
        rjmp main
15
 
16
.org URXCaddr                             ; Interruptvektor für UART-Empfang
17
        rjmp Receive1
18
19
20
;Hauptprogramm
21
main:
22
        ldi temp, LOW(RAMEND)
23
        out SPL, temp
24
        ldi temp, HIGH(RAMEND)
25
        out SPH, temp
26
27
        ldi temp, 0xFF                    ; Port D = Ausgang
28
        out DDRD, temp
29
30
        ldi temp, 0b01100000
31
        out PortD, temp
32
33
        ; Baudrate einstellen
34
        ldi temp, HIGH(UBRRVAL)
35
        out UBRRH, temp
36
        ldi temp, LOW(UBRRVAL)
37
        out UBRRL, temp
38
 
39
        ; Frame-Format: 8 Bit
40
        ldi r16, (1<<URSEL)|(1<<USBS)|(1<<UCSZ1)|(1<<UCSZ0)
41
        out UCSRC, temp
42
 
43
        sbi UCSRB, RXCIE                  ; Interrupt bei Empfang
44
        sbi UCSRB, RXEN                   ; RX (Empfang) aktivieren
45
        sbi UCSRB, TXEN                ; TX (Senden) aktivieren 
46
        
47
        sei                               ; Interrupts global aktivieren
48
        
49
loop:  
50
51
    ldi temp, 0b01100000
52
        out PortD, temp
53
  
54
    rjmp loop                         ; Endlosschleife
55
56
Receive1:
57
58
       in   r20, SREG   
59
       in Data, UDR          ; Empfangenes Byte in Data speichern
60
       cpi  Data, 0x15
61
     brne Ende
62
     rjmp header_init
63
64
       Ende:
65
     out SREG, r20 
66
     reti                               ; zurück zum Hauptprogramm
67
68
69
Receive:
70
71
       sbis UCSRA, RXC
72
     rjmp Receive
73
       in Data, UDR                      ; Empfangenes Byte in Data speichern
74
     ret  
75
76
77
78
Transmit:
79
    
80
81
                    ldi temp, 20
82
       wait1:
83
                    push temp
84
                    ldi temp, 200
85
       wait1_1:                               
86
                    nop
87
                    nop
88
                    nop
89
                    nop
90
                    nop
91
                    dec temp
92
                    brne wait1_1
93
                    pop temp
94
                    dec temp
95
                    brne wait1
96
97
98
       sbis UCSRA, UDRE                   ; Warten bis UDR ist
99
       rjmp Transmit
100
       out UDR, Data                      ; Data senden
101
     ret
102
103
       
104
105
header_init:
106
107
       cbi  PORTD, 5
108
    
109
     cbi UCSRB, RXCIE                   ; Interrupt bei Empfang deaktivieren
110
    
111
     
112
     ldi  Data, 0x13
113
     rcall Transmit
114
    
115
    
116
     ldi     r30,LOW(Header)
117
       ldi     r31,HIGH(Header)
118
     ldi  Count, 49                    ; Counter der bytes zählt aktivieren
119
120
       
121
header_receive:
122
       
123
     
124
       rcall Receive
125
     st Z+, Data
126
     
127
     dec Count
128
     brne header_receive
129
     
130
     ldi Data, 0x06
131
     rcall Transmit
132
     
133
134
     ldi Count, 16
135
     ldi r30,LOW(Content)
136
       ldi r31,HIGH(Content)
137
data_receive:
138
     rcall Receive
139
     st Z+, Data
140
     dec count
141
     brne data_receive
142
143
     ldi Data, 0x06
144
     rcall Transmit
145
146
       ldi Count, 50
147
     ldi r30,LOW(End_Header)
148
       ldi r31,HIGH(End_Header)
149
150
end_header_receive:
151
       
152
       rcall Receive
153
     st Z+, Data
154
     dec Count
155
     brne end_header_receive
156
157
     ldi Data, 0x06
158
     rcall Transmit
159
160
161
162
Check:
163
164
ldi r30,LOW(Content)
165
ldi r31,HIGH(Content)
166
167
ld r19, Z
168
169
brne Neustart
170
171
cbi  PORTD, 6
172
173
174
Neustart:
175
176
177
    sbi UCSRB, RXCIE                   ; Interrupt bei Empfang aktivieren
178
    reti
179
180
181
182
.DSEG                                      ; das Folgende kommt ins SRAM
183
Header:     .BYTE  50
184
Content:    .BYTE  16
185
End_Header: .Byte  50

von Falk B. (falk)


Lesenswert?

Quelltexte bitte als Anhang!

von Flo S. (tuxianer)


Angehängte Dateien:

Lesenswert?

so es geht!!!! es lag allerdings nicht an fehlerhafter programmierung, 
sondern das das Rechner protokoll falsch ausgewertet wurde. und die 
variable an der Falschen stelle eingelesen wurde. hier nochmal das 
neuste:

von Flo S. (tuxianer)


Angehängte Dateien:

Lesenswert?

so kaum ist das eine Problem gelöst hat man auch schon das nächste am 
Hals. ich wollte jetzt machen, das man mehrere Dioden via Rechner an und 
aus schalten kann...aber jetzt gehts nimmer. Das äusert sich in sofern, 
dass das prog einmal durchläuft auch ordentlich kommuniziert mit dem 
Reechner...aber keine Diode geht an. Und wenn ich dann ein zweites mal 
was sende was vorher ging kommt jetzt nen Error.

von Flo S. (tuxianer)


Lesenswert?

keine ne Idee?

von Condi (Gast)


Lesenswert?

Was macht deine Check Routine?

von Condi (Gast)


Lesenswert?

ach ja und

       Ende:
     reti                               ; zurück zum Hauptprogramm

ist auch nicht so toll. da hast du wohl vergessen den Interrupt wieder 
einzuschalten oder?

von Condi (Gast)


Lesenswert?

vergiss das letzte

von Flo S. (tuxianer)


Lesenswert?

die überprüft die vom Rechner gesendete Variable auf den einen Wert der 
dann die entsprechende LED aktiviert. Hä die ist doch schon aktiviert. 
Die wird dann nur später deaktiviert und am ende wieder aktiviert.


Also wenn ein Interrupt ausgelöst wird, aber die Bedingung nicht erfüllt 
ist springter inne Schleife. Interrupt ist aber noch aktiv...und wenns 
erfolgreich war springt er zu header_init und da wird sie deaktiviert 
und am ende aktiviert wenn die Übertragung komplett ist.

von Axel R. (Gast)


Lesenswert?

Hallo Florentin,

>die überprüft die vom Rechner gesendete Variable auf den einen Wert der
dann die entsprechende LED aktiviert.

Kannst Du das Programm vom GTR mal bitte in den Anhang stellen?

Dann kann man das evtl. hier mal nachvollziehen.


Danke
AxelR.

von Flo S. (tuxianer)


Lesenswert?

ein Programm direkt ist es nicht zu Testzwecken sende ich nur mit dem 
Befehl:

2->A

also ich schreibe 2 in Variable A



und danach der Befehl:

Send (A)

von Flo S. (tuxianer)


Lesenswert?

ok ein Problem hätte ich gelöst...und zwar hatte ich immer nur versucht 
2 zu senden und genau die LED war falsch angeschlossen auf dem 
Steckbrett. Aber es bleibt immer noch das Problem, das es nicht mehr 
richtig weiter empfängt nach einer Übertragung und das ich auf dem 
Rechner immer nen Error erhalte. Ich vermute es springt nicht richtig 
zurück, weil ich weitere Unterroutinen Aufrufe.

von Flo S. (tuxianer)


Lesenswert?

und zwar im simulator springt er nach dem Anschalten der dieode via ret 
in diee loop. Da liegt das problem. Aber wison springt er nicht dorthin 
zurück, von wo die funktion aufgerufen wurde???

von Flo S. (tuxianer)


Angehängte Dateien:

Lesenswert?

so...also es liegt daran das ret nicht wieder dahin zurückspringt, weil 
ich die Funkt, ja nicht mit call aufgerufen aheb das konnte garnicht 
gehen...so hier der Aktuelle Code:

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.