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 ;----------------------------------------------------------------------- -----------------------------------------
Gast
#2145015
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
Gast
#2145021
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
Gast
#2145071
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 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
Wenn ich mich nicht verhauhen habe enthalten danach die Bit 5..0 die Schalterzustände 6..1. Damit geht vieles leichter. MfG Spess
Gast
#2145086
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 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
Und nun überlegt man sich den Programmablaufplan: LED = Blink OR Schwimmerschalter Und erst jetzt gehts los mit Programmieren:
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
Peter
Gast
#2145108
Hi Mit dem obigen Sortieren kann die gesamte 'mainloop' etwa so aussehen: (nicht getestet)
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
14 | |
15 | |
16 | |
17 | |
18 | |
19 | |
20 | |
21 | |
22 | |
23 | |
24 | |
25 | |
26 | |
27 | |
28 | |
29 | |
30 | |
31 | |
32 | |
33 | |
34 | |
35 | |
36 | |
37 | |
MfG Spess
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
Kaveh Deiport schrieb: > ;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 O.k., dann muß man noch etwas umsortieren:
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
Peter
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
Gast
#2145127
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:
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
Peter
Gast
#2145134
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
Gast
#2145149
> 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
Peter Dannegger schrieb: > Nö. > > Zähl mal nach, es sind 7: > [pre] > sw 1 2 3 4 5 6 led 1 2 3 4 5 6 > 0 0 0 0 0 0 b b b b b b > 1 0 0 0 0 0 1 b b b b b > 1 1 0 0 0 0 1 1 b b b b > 1 1 1 0 0 0 1 1 1 b b b > 1 1 1 1 0 0 1 1 1 1 b b > 1 1 1 1 1 0 1 1 1 1 1 b > 1 1 1 1 1 1 1 1 1 1 1 1 Da hast Du recht. sorry mein fehler. mfg kaveh
Antwort schreiben
Bitte melde dich an, um einen Beitrag zu schreiben.