Hallo zusammen,
Der Wasserstand eines Tanks sollte mit Hilfe von sechs Schwimmschalter
erfasst und über LEDs dargestellt werden. Dafür habe ich mir das unten
stehende Programm ausgedacht. je nach dem ob ein Schwimmschalter
geöffnet oder geschlossen ist, sollte dem entsprechend auch ein LED
leuchte bzw blinken.
bei der Simulation des Programm mit AvR Studuio kommt die Meldung :
error: Relative branch out of reach . Mit drei Schwimmschalter
funktioniert das Programm (getestet) aber mit sechs nicht, da es für die
Sprungbefehle zu lang wird.
Nun möchte ich das Problemm über eine Sprungtabelle lösen (indirekte
Adressierung). bei AVR-Tutorial gibt es ein Kapitel über dieses Thema,
aber aus dem ausgeführten Beispiel werde ich nicht ganz schlau. Daher
dacht ich, vielleicht kann mir jemand an dieser Stelle einen Tipp geben,
wie ich es lösen kann.
bedanke mich
mfg
kaveh
.include"m32def.inc"
rjmp main
.equ c1 = 60000 ; Bestimmt die Blinkfrequenz
.def temp=r16
main: ;Hauptprogramm
;Stack Initialisieren
ldi temp,high(ramend)
out sph,temp
ldi temp,low(ramend)
out spl,temp
;-------------------------------------------------------------------
;Ports als Eingänge konfigurieren, PortD und PortC
;Schwimmschalter SW1 Pin 20 PORTD PD6
;Schwimmschalter SW2 Pin 25 PORTC PC3
;Schwimmschalter SW3 Pin 26 PORTC PC4
;Schwimmschalter SW4 Pin 27 PORTC PC5
;Schwimmschalter SW5 Pin 15 PORTD PD1
;Schwimmschalter SW6 Pin 14 PORTD PD0
;
;
cbi DDRD,6 ;Schwimmschalter SW1
sbi PORTD,6
cbi DDRC,3 ;Schwimmschalter SW2
sbi PORTC,3
cbi DDRC,4 ;Schwimmschalter SW3
sbi PORTC,4
cbi DDRC,5 ;Schwimmschalter SW4
sbi PORTC,5
cbi DDRD,1 ;Schwimmschalter SW5
sbi PORTD,1
cbi DDRD,0 ;Schwimmschalter SW6
sbi PORTD,0
;---------------------------------------------------------------------
;Ports als Aisgänge konfigurieren PortA und PortB und PortD
;PortA >> PA0 >> LED 1 Zeigt den Zustand vom SW1 Pin 40
;PortA >> PA1 >> LED 2 Zeigt den Zustand vom SW2 Pin 39
;PortA >> PA2 >> LED 3 Zeigt den Zustand vom SW3 Pin 38
;PortA >> PA3 >> LED 4 Zeigt den Zustand vom SW4 Pin 37
;PortA >> PA4 >> LED 5 Zeigt den Zustand vom SW5 Pin 36
;PortA >> PA5 >> LED 6 Zeigt den Zustand vom SW6 Pin 35
ldi temp,0xff
out ddra,temp
mainloop:
ldi temp,0x00 ;das code für SW1
in r17,PIND ;PIND.6 in das Register r17 laden
andi r17,0x40 ;mit 0X40 und verknüpfem
cp r17,temp ;das ergebnis mit code für SW1 vergleichen
brne blinken1 ;wenn ungleich, dann die Blinkfunktion1
sbi portA,7 ;led1 einschalten
ldi temp,0x00 ;das code für SW2
in r17,PINC ;PINC.3 in das Register r17 laden
andi r17,0b00001000 ;mit 0X40 und verknüpfem
cp r17,temp ;das ergebnis mit code für SW2 vergleichen
brne blinken2 ;wenn ungleich, dann die Blinkfunktion2
sbi portA,5 ;led2 einschalten
ldi temp,0x00 ;das code für SW3
in r17,PINC ;PINC.4 in das Register r17 laden
andi r17,0b00010000 ;mit 0b00010000 und verknüpfem
cp r17,temp ;das ergebnis mit code für SW3 vergleichen
brne blinken3 ;wenn ungleich, dann die Blinkfunktion3
sbi portA,4 ;led3 einschalten
ldi temp,0x00 ;das code für SW4
in r17,PINC ;PINC.5 in das Register r17 laden
andi r17,0b00100000 ;mit 0b00100000 und verknüpfem
cp r17,temp ;das ergebnis mit code für SW4 vergleichen
brne blinken4 ;wenn ungleich, dann die Blinkfunktion4
sbi portA,3 ;led4 einschalten
ldi temp,0x00 ;das code für SW5
in r17,PIND ;PIND.1 in das Register r17 laden
andi r17,0b00000010 ;mit 0X02 und verknüpfem
cp r17,temp ;das ergebnis mit code für SW5 vergleichen
brne blinken5 ;wenn ungleich, dann die Blinkfunktion5
sbi portA,2 ;led5 einschalten
ldi temp,0x00 ;das code für SW6
in r17,PINC ;PIND.0 in das Register r17 laden
andi r17,0b00000001 ;mit 0X01 und verknüpfem
cp r17,temp ;das ergebnis mit code für SW6 vergleichen
brne blinken6 ;wenn ungleich, dann die Blinkfunktion6
sbi portA,0 ;led6 einschalten
;-----------------------------------------------------------------------
---------------------------
blinken1:
sbi PORTA,7 ; Portbit.7 auf high
sbi PORTA,5 ; Portbit.5 auf high
sbi PORTA,4 ; Portbit.4 auf high
sbi PORTA,3 ; Portbit.3 auf high
sbi PORTA,2 ; Portbit.2 auf high
sbi PORTA,0 ; Portbit.0 auf high
ldi R25,HIGH(c1) ;Zeitschleife
ldi R24,LOW(c1)
Loop_sw1:
sbiw R24,1
brne Loop_sw1
cbi PORTA,7 ; Portbit 7 auf Low
cbi PORTA,5 ; Portbit 5 auf Low
cbi PORTA,4 ; Portbit 4 auf Low
cbi PORTA,3 ; Portbit 3 auf Low
cbi PORTA,2 ; Portbit 2 auf Low
cbi PORTA,0 ; Portbit 0 auf Low
ldi R25,HIGH(c1)
ldi R24,LOW(c1)
Loop_sw11:
sbiw R24,1
brne Loop_sw11
rjmp mainloop
;-----------------------------------------------------------------------
----------------------------
blinken2:
sbi PORTA,5 ; Portbit.5 auf high
sbi PORTA,4 ; Portbit.4 auf high
sbi PORTA,3 ; Portbit.3 auf high
sbi PORTA,2 ; Portbit.2 auf high
sbi PORTA,0 ; Portbit.0 auf high
ldi R25,HIGH(c1) ;Zeitschleife
ldi R24,LOW(c1)
Loop_sw2:
sbiw R24,1
brne Loop_sw2
cbi PORTA,5 ; Portbit 5 auf Low
cbi PORTA,4 ; Portbit 4 auf Low
cbi PORTA,3 ; Portbit 3 auf Low
cbi PORTA,2 ; Portbit 2 auf Low
cbi PORTA,0 ; Portbit 0 auf Low
ldi R25,HIGH(c1)
ldi R24,LOW(c1)
Loop_sw22:
sbiw R24,1
brne Loop_sw22
rjmp mainloop
;-----------------------------------------------------------------------
-------------------------------------
blinken3:
sbi PORTA,4 ; Portbit.4 auf high
sbi PORTA,3 ; Portbit.3 auf high
sbi PORTA,2 ; Portbit.2 auf high
sbi PORTA,0 ; Portbit.0 auf high
ldi R25,HIGH(c1) ;Zeitschleife
di R24,LOW(c1)
Loop_sw3:
sbiw R24,1
brne Loop_sw3
cbi PORTA,4 ; Portbit 4 auf Low
cbi PORTA,3 ; Portbit 3 auf Low
cbi PORTA,2 ; Portbit 2 auf Low
cbi PORTA,0 ; Portbit 0 auf Low
ldi R25,HIGH(c1)
ldi R24,LOW(c1)
Loop_sw33:
sbiw R24,1
brne Loop_sw33
rjmp mainloop
;-----------------------------------------------------------------------
--------------------------------
blinken4:
sbi PORTA,3 ; Portbit.3 auf high
sbi PORTA,2 ; Portbit.2 auf high
sbi PORTA,0 ; Portbit.0 auf high
ldi R25,HIGH(c1) ;Zeitschleife
ldi R24,LOW(c1)
Loop_sw4:
sbiw R24,1
brne Loop_sw4
cbi PORTA,3 ; Portbit 3 auf Low
cbi PORTA,2 ; Portbit 2 auf Low
cbi PORTA,0 ; Portbit 0 auf Low
ldi R25,HIGH(c1)
ldi R24,LOW(c1)
Loop_sw44:
sbiw R24,1
brne Loop_sw44
rjmp mainloop
;-----------------------------------------------------------------------
-----------------------------------
blinken5:
sbi PORTA,2 ; Portbit.2 auf high
sbi PORTA,0 ; Portbit.0 auf high
ldi R25,HIGH(c1) ;Zeitschleife
ldi R24,LOW(c1)
Loop_sw5:
sbiw R24,1
brne Loop_sw5
cbi PORTA,2 ; Portbit 2 auf Low
cbi PORTA,0 ; Portbit 0 auf Low
ldi R25,HIGH(c1)
ldi R24,LOW(c1)
Loop_sw55:
sbiw R24,1
brne Loop_sw55
rjmp mainloop
;-----------------------------------------------------------------------
---------------------------------------
blinken6:
sbi PORTA,0 ; Portbit.0 auf high
ldi R25,HIGH(c1) ;Zeitschleife
ldi R24,LOW(c1)
Loop_sw6:
sbiw R24,1
brne Loop_sw6
cbi PORTA,0 ; Portbit 0 auf Low
ldi R25,HIGH(c1)
ldi R24,LOW(c1)
Loop_sw66:
sbiw R24,1
brne Loop_sw66
rjmp mainloop
;-----------------------------------------------------------------------
-----------------------------------------
Hi
>Nun möchte ich das Problemm über eine Sprungtabelle lösen (indirekte>Adressierung).
Wozu? Das Programm kann man auf die Hälfte bis ein Drittel verkürzen.
Ist sehr umständlich programmiert.
MfG Spess
Oh mein Gott, vergiß indirekte Adressierung, Du bist ja noch ganz am
Anfang.
z.B.: Anstatt
sbi PORTA,4 ; Portbit.4 auf high
sbi PORTA,3 ; Portbit.3 auf high
sbi PORTA,2 ; Portbit.2 auf high
sbi PORTA,0 ; Portbit.0 auf high
schreibt man kürzer:
ldi r16, 29
out PORTA, r16
Hast Du schon mal was von Subroutinen gehört?
delay:
ldi R25,HIGH(c1) ;Zeitschleife
ldi R24,LOW(c1)
Loop_sw6:
sbiw R24,1
brne Loop_sw6
ret
sowas schreibt man nicht dutzendmal in den Code, sondern nur einmal und
ruft's dann mit
call delay
auf - das ret am Ende springt wieder zur aufrufenden Routine zurück.
Wenn Dein Code dann kürzer wird, sollte es dann auch mit den
Branch-Befehlen klappen
Hi,
> Wozu? Das Programm kann man auf die Hälfte bis ein Drittel verkürzen.> Ist sehr umständlich programmiert.
An welcher Stellen könnte es Deiner Meinung nach verkürzt werden??
mfg
kaveh
Kaveh Deiport schrieb:> An welcher Stellen könnte es Deiner Meinung nach verkürzt werden??
An allen.
Aber schreib erstmal in Worten auf, was das Programm machen soll.
Man programmiert nicht so einfach drauf los.
Die komplette Funktion muß vorher festgelegt sein.
Peter
Hi,
> An allen.>> Aber schreib erstmal in Worten auf, was das Programm machen soll.
Das habe ich zwar oben beschrieben aber hier nochmal für Dich.
> Man programmiert nicht so einfach drauf los.
keiner hat einfach hier losprogrammiert
> Die komplette Funktion muß vorher festgelegt sein
das ist hier auch der Fall. es ist ganz einfach. es sind 6
Schwimmschalter, die sich in einem Wassetank befinden, Schwimmschalter-1
ganz unten und schwimmschalter-6 ganz oben und alle andere dazwischen.
Zustand jedes Schalter wird mit einer LED dargestellt. Wenn ein
Schwimmschalter geöffnet ist, dann blinkt die LED und wenn er
geschlossen ist dann leuchtet die LED permanent.
Wenn Schwimmschalter-1 geöffnet ist, dann sind alle andere auch
geöffnet, da sich gerade kein Wasser im Tank befindet und wenn
Schwimmschalter-6 geschlossen ist, dann sind alle andere Schalter auch
geschlossen da der Tank jetzt voll mit Wasser ist.
Insgesamt gibt es 6 Zustände. die programmiert werden. das ist
eigentlich alles und wenn es Dir immer noch zu wenig ist, dann muss ich
leider passen.
mfg
kaveh
Hi
>> An welcher Stellen könnte es Deiner Meinung nach verkürzt werden??>An allen.
Stimmt leider. Aber mal als Anfang: Mit ein paar logischen Verknüpfungen
kannst du die etwas wild verteilten Schaltereingänge in der richtigen
Reihenfolge in einem Byte zusammen bringen:
1
mainloop:
2
in r16,PINC
3
lsr r16
4
lsr r16
5
andi r16,0b00001110
6
7
in r17,PIND
8
swap r17
9
lsr r17
10
bst r17,3
11
bld r16,5
12
andi r17,00010001
13
or r17,r16
Wenn ich mich nicht verhauhen habe enthalten danach die Bit 5..0 die
Schalterzustände 6..1. Damit geht vieles leichter.
MfG Spess
Hi
Irgendwie passt das nicht zusammen:
>;Ports als Aisgänge konfigurieren PortA und PortB und PortD>;PortA >> PA0 >> LED 1 Zeigt den Zustand vom SW1 Pin 40>;PortA >> PA1 >> LED 2 Zeigt den Zustand vom SW2 Pin 39>;PortA >> PA2 >> LED 3 Zeigt den Zustand vom SW3 Pin 38>;PortA >> PA3 >> LED 4 Zeigt den Zustand vom SW4 Pin 37>;PortA >> PA4 >> LED 5 Zeigt den Zustand vom SW5 Pin 36>;PortA >> PA5 >> LED 6 Zeigt den Zustand vom SW6 Pin 35>blinken1:>sbi PORTA,7 ; Portbit.7 auf high>sbi PORTA,5 ; Portbit.5 auf high>sbi PORTA,4 ; Portbit.4 auf high>sbi PORTA,3 ; Portbit.3 auf high>sbi PORTA,2 ; Portbit.2 auf high>sbi PORTA,0 ; Portbit.0 auf high
MfG Spess
Kaveh Deiport schrieb:> Wenn Schwimmschalter-1 geöffnet ist, dann sind alle andere auch> geöffnet, da sich gerade kein Wasser im Tank befindet und wenn> Schwimmschalter-6 geschlossen ist, dann sind alle andere Schalter auch> geschlossen da der Tank jetzt voll mit Wasser ist.> Insgesamt gibt es 6 Zustände.
Nö.
Zähl mal nach, es sind 7:
1
sw 1 2 3 4 5 6 led 1 2 3 4 5 6
2
0 0 0 0 0 0 b b b b b b
3
1 0 0 0 0 0 1 b b b b b
4
1 1 0 0 0 0 1 1 b b b b
5
1 1 1 0 0 0 1 1 1 b b b
6
1 1 1 1 0 0 1 1 1 1 b b
7
1 1 1 1 1 0 1 1 1 1 1 b
8
1 1 1 1 1 1 1 1 1 1 1 1
Und nun überlegt man sich den Programmablaufplan:
LED = Blink OR Schwimmerschalter
Und erst jetzt gehts los mit Programmieren:
spess53 schrieb:> Hi>> Irgendwie passt das nicht zusammen:>>>;Ports als Aisgänge konfigurieren PortA und PortB und PortD>>;PortA >> PA0 >> LED 1 Zeigt den Zustand vom SW1 Pin 40>>;PortA >> PA1 >> LED 2 Zeigt den Zustand vom SW2 Pin 39>>;PortA >> PA2 >> LED 3 Zeigt den Zustand vom SW3 Pin 38>>;PortA >> PA3 >> LED 4 Zeigt den Zustand vom SW4 Pin 37>>;PortA >> PA4 >> LED 5 Zeigt den Zustand vom SW5 Pin 36>>;PortA >> PA5 >> LED 6 Zeigt den Zustand vom SW6 Pin 35>>>>blinken1:>>sbi PORTA,0 ; Portbit.0 auf high>>sbi PORTA,2 ; Portbit.2 auf high>>sbi PORTA,3 ; Portbit.3 auf high>>sbi PORTA,4 ; Portbit.4 auf high>>sbi PORTA,5 ; Portbit.5 auf high>>sbi PORTA,7 ; Portbit.7 auf high
So ist die Reihenfolge jetzt richtig.
mfg
kaveh
warum meinen immer fast alle Anfänger mit Assembler anfangen zu müssen?
Meiner Meinung nach gibt es überhaupt keinen vernünftigen Grund dafür.
Eine höhere Programmiersprache ist für viele ja schon schwierig.
Sich dann aber noch mit den absoltesten Low-Level-Problemen zu quälen
grenzt an Masochismus.
Edit:
Abgesehen davon, dass das gewonnene Wissen nicht universell, sondern nur
begrenzt einsetzbar ist
Warum kann man nicht einfach folgenden Ablauf umsetzen
"Schleife"
- Schalterzustand als Datenwort einlesen
- Bits Schalter 1-6 herausmaskieren
- ggf. invertieren
- als Datenwort an LED ausgeben
- Delay
- alle LEDs anschalten
- Delay
Sprung nach "Schleife"
Kaveh Deiport schrieb:>>>blinken1:>>>sbi PORTA,0 ; Portbit.0 auf high>>>sbi PORTA,2 ; Portbit.2 auf high>>>sbi PORTA,3 ; Portbit.3 auf high>>>sbi PORTA,4 ; Portbit.4 auf high>>>sbi PORTA,5 ; Portbit.5 auf high>>>sbi PORTA,7 ; Portbit.7 auf high>> So ist die Reihenfolge jetzt richtig.
Dann eben:
Vlad Tepesch schrieb:> warum meinen immer fast alle Anfänger mit Assembler anfangen zu müssen?
Wenn jemand eine höhere Programmiersprache gelernt hat und nur in
Objekten und Klassen denkt, ist es IMO ganz gut, wenn er mal in
Assembler auf Bit- und Byteebene runterkommt und lernt was da abläuft.
Dumme Frage schrieb:> Warum kann man nicht einfach folgenden Ablauf umsetzen>> "Schleife"> - Schalterzustand als Datenwort einlesen> - Bits Schalter 1-6 herausmaskieren> - ggf. invertieren> - als Datenwort an LED ausgeben> - Delay> - alle LEDs anschalten> - Delay> Sprung nach "Schleife"
Diese Lösung hat Peter ja oben schon hergezeigt :-)
Wenn der TO das jetzt auch noch gelesen (und verstanden) hätte wäre er
schon fertig (gut, die Delay-Funktion fehlt noch).
Vlad Tepesch schrieb:> warum meinen immer fast alle Anfänger mit Assembler anfangen zu müssen?> Meiner Meinung nach gibt es überhaupt keinen vernünftigen Grund dafür.
Das kann ich Dir nicht beantworten. Wenn man sich als Anfänger mit
Mikrocontroller auseinander setzen will, dann wird einem empfohlen, dass
man mit Assembler anfangen sollte, da man als Anfänger den Controller
besser kennenlernen kann. richte Deine Frage eher den
Programmiergöttern, die von so etwas überzeugt sind bzw. diese Meinung
vertretten.
Aber was schlägst Du denn vor??
> Eine höhere Programmiersprache ist für viele ja schon schwierig.> Sich dann aber noch mit den absoltesten Low-Level-Problemen zu quälen> grenzt an Masochismus.
keiner will, dass Du Dich quälest.
mfg
kaveh
> Diese Lösung hat Peter ja oben schon hergezeigt :-)
Sorry, irgendwie habe ich das nach der vierten Seite Assembler
übersehen. Hatte mich schon gewundert, dass Peter nicht den eleganten
"Dreizeiler" parat hatte.
Rainer