Hey Profis,
ich benutze einen Mikrocontroller um ein Gerät über RS232 anzusteuern.
Wenn ich auf einen Taster drücke wird ein Befehl gesendet, - was auch
funktioniert.
Allerdings soll pro Durchgang der endless-Schleife ein zusätzlicher
Befehl gesendet werden, und die Antwort darauf ausgewertet werden.
Das Senden funktioniert wieder ohne Probleme, allerdings tut sich nach
dem ersten Empfangen gar nichts mehr.
/*hier werden später der reihe nach noch weiterer Pins (Taster) abgefragt*/
49
50
rcall receiveInformation
51
52
rjmp endless
53
54
55
; transmit content of register sign via rs232
56
transmitSign:
57
sbis UCSRA, UDRE ; wait until UDR is ready to transmit
58
rjmp transmitSign
59
out UDR, sign
60
ret
61
62
63
; pause
64
wait:
65
ldi tmp, 0xFF
66
loop_1:
67
ldi tmp2, 0xFF
68
loop_2:
69
ldi tmp3, 0x20
70
loop_3:
71
dec tmp3
72
brbc 1, loop_3
73
dec tmp2
74
brbc 1, loop_2
75
dec tmp
76
brbc 1, loop_1
77
ret
78
79
; if power is pressed
80
power:
81
sbrs state, statePower
82
rjmp transmitPowerOn
83
84
transmitPowerOff:
85
ldi sign, 0x02
86
rcall transmitSign
87
ldi sign, 0x00
88
rcall transmitSign
89
ldi sign, 0x00
90
rcall transmitSign
91
ldi sign, 0x00
92
rcall transmitSign
93
ldi sign, 0x00
94
rcall transmitSign
95
ldi sign, 0x02
96
rcall transmitSign
97
rjmp powerEnd
98
99
transmitPowerOn:
100
ldi sign, 0x02
101
rcall transmitSign
102
ldi sign, 0x01
103
rcall transmitSign
104
ldi sign, 0x00
105
rcall transmitSign
106
ldi sign, 0x00
107
rcall transmitSign
108
ldi sign, 0x00
109
rcall transmitSign
110
ldi sign, 0x03
111
rcall transmitSign
112
113
powerEnd:
114
ldi tmp, (1<<statePower)
115
eor state, tmp
116
rcall wait
117
ret
118
119
receiveInformation:
120
121
ldi tmp2, 0x80
122
123
transmitRequest:
124
ldi sign, 0x00
125
rcall transmitSign
126
ldi sign, 0xC0
127
rcall transmitSign
128
ldi sign, 0x00
129
rcall transmitSign
130
ldi sign, 0x00
131
rcall transmitSign
132
ldi sign, 0x00
133
rcall transmitSign
134
ldi sign, 0xC0
135
rcall transmitSign
136
137
receiveWait:
138
sbis UCSRA, RXC
139
rjmp receiveWait
140
receive:
141
dec tmp2
142
brbs 1, receiveEnd
143
in sign, UDR
144
out PORTA, sign
145
rjmp receiveWait
146
147
receiveEnd:
148
149
ret
In der endless-Schleife wird praktisch gewartet ob ein Taster gedrückt
wird. Pro Durchgang wird ein zusätzlicher Befehl durch aufrufen des
Unterprogramms "receiveInformation" gesendet, nach dem Senden, soll
jedes empfangene Byte an Port A ausgegeben werden... Es werden genau 128
(0x80) Bytes empfangen.
Jetzt funktioniert das ganze genau einmal, - ich sehe das sich an PortA
was tut, aber danach passiert gar nichts mehr...
Versteht ihr was ich will und wo's hängt?
Vielen Dank jetzt schon mal!!! :)
Hallo,
e3onjz schrieb:> ldi tmp, 0x00 ; Port B as input> out DDRB, tmp> ldi tmp, 0xFF ; Port B, activate PullUp Resistor
hier werden die internen pulls aktiviert ok.
/***********************************************************************
*********/
>> endless:>> sbic PINB, 0> rcall power
der SBIC-Befehl tut folgendes:
"SKIP IF BIT IS CLEARED" = nachfolgenden Befehl überspringen wenn der
PIN 0 ist.
Und jetzt kommts da du die Pulls aktiviert hast ist dein PIN immer 1 und
bei 1 wird der folgende Befehl ausgeführt >>>>>> heist dein Programm
wird immer ausgeführt.
sbis Pinb,0
rcall power
wäre eine von mehreren Möglichkeiten
Hey Chris - danke für deine Antwort!!
Aber daran liegts nicht, weil ich die Schaltung so aufgebaut habe, dass
bei Tasterdruck ein High-Pegel anliegt, und somit stimmt der Befehl dann
auch...
Ohne Aufruf des Unterprogramms "receiveInformation" funktioniert das
ganze auch wunderbar - also muss der Fehler iwo dort liegen...
mal so neben bei gefragt du willst in dem Unterprogramm
receiveInformation
das die UP erst Daten sendet und dann auf Eingaben von dir wartet um
dann wieder herauszuspringen aus dem UP ?
Was ist, wenn nur 127 Bytes empfangen werden?
Hat zwar nichts mit dem Problem zu tun, aber das Nachfolgende verstehe
ich nicht:
>.equ ubbr_value = ((systemClock+rs232Baud*8)/(rs232Baud*16)-1)
Ja genau das war der Plan...
Bin total neu auf diesem Gebiet, - wie würdest du es machen?
Also die Antwort auf den Befehl der gesendet wurde, kommt relativ
unmittelbar...
e3onjz schrieb:> Ja genau das war der Plan...
receiveWait:
sbis UCSRA, RXC
rjmp receiveWait
in sign, UDR ;A wie Antwort von deinem PC gesendet
cpi sign, 'A' ; Vergleich auf A
brne receiveWait ;und wenn !=A springe zu label
receiveWaitEnd
; hier dein Code für Visualisierungen
ret
achso und führe dir für die bedingten Verzweigungen mal das DB zu Gemüte
Die Variable state mit dem Bit/Flag statePower wird zu Beginn nicht
gesetzt. Es kann also sein, dass nach dem Senden von PowerOff auf eine
Kommunikation gewartet wird - ist das so korrekt?
Hey Chris, das sieht ziemlich vielversprechend aus - werd mal ein
bisschen mit experimentieren.
>achso und führe dir für die bedingten Verzweigungen mal das DB zu Gemüte
Meinst du mit DB die Direktive zum Speichern? Was hat das mit
Verzweigungen zu tun? Sry bin noch beim Reinlesen in das alles ;)
Und ich bitte auch beim alten Hanns um Entschuldigung, ich kenne bis
jetzt nur eine handvoll Befehle - wollte niemanden verwirren...
Oh sry, hab da ein paar Antworten übersehen...
Yapp stimmt, im Register 'state' wird am Anfang kein Wert gesetzt, was
bedeutet, dass er je nach Inhalt "zufälig" An- bzw Ausschalten will...
Aber das dürfte für dieses Problem nicht relevant sein, da pro Durchlauf
der endless-Schleife immer auf eine Kommunikation gewartet wird, damit
das Gerät auch immer auf dem neuesten Stand ist.
>Hat zwar nichts mit dem Problem zu tun, aber das Nachfolgende verstehe
ich nicht:
>>.equ ubbr_value = ((systemClock+rs232Baud*8)/(rs232Baud*16)-1)
ähm da muss ich passen, - das habe ich von
http://www.mikrocontroller.net/articles/AVR-Tutorial:_UART#UART_konfigurieren
abgeschrieben...
Kann das Gerät nach dem 'Ausschalten' noch auf andere Befehle als
'Einschalten' reagieren?
Und es ist sicher, dass als Antwort genau 128 Zeichen kommen? Sonst
hängt die Empfangsschleife.
Es ist zwar nur ein Schönheitsfehler, aber die Baudrate liegt um 0.4 %
daneben.
Also erstmal auch dir vielen Dank für deine Mühe!!
Ah verdammt, vll ist das nicht klar rübergekommen:
Das oben gezeigt Programm bildet zsm mit dem Controller und ein paar
Bedienelementen eine eingenständige Steuerung, welche ein Gerät X
steuert.
Der Befehl "Ausschalten" schaltet also das Gerät X aus. In diesem
"ausgeschaltetem Zustand (StandBy)" reagiert das Gerät X nur auf den
"Einschalt" Befehl.
>Und es ist sicher, dass als Antwort genau 128 Zeichen kommen?>Sonst hängt die Empfangsschleife.
Yapp das hab ich erstmal wieder zur Fehlersuche weggenommen, - aber ich
wollte diesen Teil (während er auf ein neues Byte im
UART-Empfangs-Register wartet):
1
sbis UCSRA, RXC
2
rjmp receiveWait
einfach auf ein paar Zyklen beschränken...
Das würde ja dann das Problem beheben, oder?
e3onjz schrieb:> sbis UCSRA, RXC> rjmp receiveWait> einfach auf ein paar Zyklen beschränken...> Das würde ja dann das Problem beheben, oder?
vom prinzip her ja, wenn du denn auf alles weitere erstmal verzichten
willst um den Fehler zu finden aber wie weit bist du denn?
>Der Befehl "Ausschalten" schaltet also das Gerät X aus. In diesem>"ausgeschaltetem Zustand (StandBy)" reagiert das Gerät X nur auf den>"Einschalt" Befehl.
Liegt nicht genau hier das Problem? Spätestens beim zweiten Durchlauf
vom Unterprogramm 'power' wird ausgeschaltet, anschließend aber in
'receiveInformation' auf die Antwort einer Frage gewartet, die der
'Ausgeschaltete' verschlafen hat.
ldi tmp2, 0x86 ; Counter2 - damit nur 134 Bytes empfangen werden
4
5
transmitRequest: ; Sende Befehl um Informationen zu bekommen
6
ldi sign, 0x00
7
rcall transmitSign
8
ldi sign, 0xC0
9
rcall transmitSign
10
ldi sign, 0x00
11
rcall transmitSign
12
ldi sign, 0x00
13
rcall transmitSign
14
ldi sign, 0x00
15
rcall transmitSign
16
ldi sign, 0xC0
17
rcall transmitSign
18
19
receiveStart:
20
ldi tmp, 0xFF ; Counter1 damit empfangsschleife abbricht, wenn keine Bytes mehr empfangen werden
21
receiveWait:
22
dec tmp ; dekrementiere Counter1
23
cpi tmp, 0x00 ; vergleíche ob COunter1 abgelaufen ist
24
breq receiveEnd ; breche empfangsschleife ab, wenn Counter1 abgelaufen ist
25
sbis UCSRA, RXC ; überspringe nächsten Befehl, wenn kein Zeichen empfangen wurde
26
rjmp receiveWait ; springe zum anfang der empfangsschlefe
27
receive:
28
in sign, UDR ; lese empfangenes Byte ein
29
out PORTA, sign ; gib Byte an PortA aus (Nur zur überprüfung - später wird hier ausgewertet)
30
dec tmp2 ; decrementiere Counter2
31
cpi tmp2, 0x00 ; vergleiche ob Countr2 abgelaufen ist (alle 134 Bytes empfangen wurden)
32
breq receiveEnd ; breche schleife ab, wenn counter2 abgelaufen ist
33
rjmp receiveStart ; springe wieder zm Anfangspunkt wo der Counter2 initialisiert wird
34
receiveEnd: ; Punkt zum abbrechen der schleifen
35
ret
>Liegt nicht genau hier das Problem? Spätestens beim zweiten Durchlauf>vom Unterprogramm 'power' wird ausgeschaltet, anschließend aber in>'receiveInformation' auf die Antwort einer Frage gewartet, die der>'Ausgeschaltete' verschlafen hat.
Yappt stimmt, hab jetzt beim testen einen anderen Befehl eingesetzt, -
allerdings konnte ich trotzdem noch an der LED sehn, dass sich nach
einer weile nichts mehr tat...
Und mit dem aktualisierten Unterprogramm ist es genau das gleiche. -
Kann es sein, dass nicht gesendet werden darf, während im
Empfangsregister noch Bytes sind?
>Kann es sein, dass nicht gesendet werden darf, während im>Empfangsregister noch Bytes sind?
Nein, senden und empfangen sind getrennt.
Das Grundproblem von gestern abend besteht doch nach wie vor, ich sehe
nicht, dass daran etwas geändert wurde.
Allgemein: Sie sollten etwas mehr in Ihre Grundlagen investieren, z.B.
setzt 'dec' das Z-Flag bereits, ein 'cpi .,0' ist also überflüssig. Und
das timeout in receiveWait wird in 255*6* 54.25 ns = 83 us durchlaufen,
ein Byte benötigt bei 9600 Bd aber 1042 us.
Meinst du mit Grundproblem, dass nach dem Ausschalten des Gerätes X
keine Antwort mehr kommt?
Das ist auch so erwünscht, in dem Fall sollte die Empfangsschleife
abbrechen und (noch nicht implementiert) eine z.b. LED anschalten die
anzeigt, dass das Gerät ausgeschaltet ist. Wird das Gerät wieder
eingeschaltet, sendet es auch wieder eine Antwort ergo sollte die
Empfangsschleife nicht abgebrochen werden - die beispielhafte LED wird
wieder ausgeschaltet und andere LEDs können je nach Antwort
eingeschaltet werden...
Ja das mit dem Timeout hab ich nicht bedacht bzw. falsch eingeschätzt,
werde es morgen gleich mal mit einem längeren probieren.
Danke auf jedenfall für deine Hilfe!! :)
e3onjz schrieb:> in dem Fall sollte die Empfangsschleife abbrechen
dann nutze einen timer dazu in dessen ISR das T-Flag gesetzt wird, in
der empfangsroutine das T-Flag löschen und danach abfragen ob gesetzt.