Forum: Mikrocontroller und Digitale Elektronik Ampelschaltung mit Interrupt - Problem mit Interrupt


von Karl S. (bullrin)


Lesenswert?

Hallo,

habe mich hier angemeldet weil ich ein Problem bei der Programmierung 
eines 8051 Mikrokontrollers habe.

Ich soll eine Ampelschaltung mit 1 Kfz Ampel und 1 Fußgängerampel 
machen.
Für die Fußgänger gibt es eine Ruftaste.

Das Problem ist der Interrupt den ich für den Notbetrieb eingebaut habe.
Wird der Interrupt ausgelöst blinkt die KFZ Ampel gelb.


Ich poste hier einmal den kompletten ASM Code:
1
  INCLUDE REG_51.pdf
2
 
3
  code at 0
4
5
   SJMP init
6
   ORG 0013h
7
8
isr:  LCALL blink
9
   RETI
10
   
11
   
12
init:  SETB EA
13
   SETB EX1
14
   SETB IT1  
15
 
16
start: SETB P2.0
17
   CLR P2.1
18
   CLR P2.2
19
   CLR P2.3
20
   SETB P2.4
21
22
   CLR P2.6
23
   CLR P2.7
24
     
25
m1:  MOV A,P2
26
   CJNE A,#31h,m1   
27
   SETB P2.6
28
   CLR P2.6
29
   LCALL zeit1
30
   CLR P2.0
31
   SETB P2.1
32
   LCALL zeit1
33
   CLR P2.1
34
   SETB P2.2
35
   LCALL zeit1
36
   SETB P2.3
37
   CLR P2.4
38
   LCALL zeit2
39
   CLR P2.3
40
   SETB P2.4
41
   LCALL zeit1
42
   SETB P2.1
43
   LCALL zeit1
44
   SETB P2.0
45
   CLR P2.1
46
   CLR P2.2
47
   JMP start
48
49
zeit1:  ;Übergangsphase 1s
50
   MOV R0, #00Fh
51
m2:  DJNZ R0,m2   
52
   RET
53
54
zeit2:   ;Auto-Rotphase  4s
55
   MOV R0, #0FFh
56
m3:  DJNZ R0,m3
57
         RET
58
        
59
        
60
blink:  MOV R1,#30d
61
m4:  MOV P2,#00h
62
   LCALL zeit1
63
   MOV P2,#02h
64
   LCALL zeit1
65
   DJNZ R1, m4
66
   RET
67
68
END.



Das Problem ist, wenn das Programm gerade am Ablauf ist und ich dann den 
Interrupt auslöse. Dann nämlich speichert er sich ja die 
Rücksprungadresse. Wenn er nun im UP Blink das mit dem Interrupt 
ausgeführt wird, die KFZ Ampel gelb blinkt, sind die Bits alle anders 
gesetzt.

Nun springt er nach einer gewissen Zeit aus dem Notbetrieb wieder heraus 
und zurück an die Stelle mitten im Programm. Dann funktioniert nichts 
mehr.

Ich wollte es irgendwie so lösen, dass wenn der Interrupt zuende ist, 
dass das Programm wieder von vorne anfängt. Also bei start. Wie könnte 
ich das machen?

Ich musste immer mit SETB und CLRB Arbeiten weil sonst das Programm 
8051win mit dem wir nachher das vorführen sollen nichts macht. Also 
einfach mit MOV bla bla geht nicht.

Habt ihr eine Idee?



Grüße

von Timmo H. (masterfx)


Lesenswert?

Du musst doch einfach nur die Rücksprungadresse, die beim Auslösen des 
Interrupts gespeichert wird mit der Adresse von "Start" überschreiben. 
Ich weiß jetzt nicht wie das Register beim 8051 heißt, aber da gibts 
bestimmt eins.

von Matthias L. (Gast)


Lesenswert?

Warum machst du nicht einfach eine ordentliche Schrittkette mit 
geeigneten Transitionen für alle Ampelzustände, auch für den Zustand 
"Ampel_gestört_blinkt".
Interrupts werden dazu nicht benötigt.

von Peter D. (peda)


Lesenswert?

Karl Suleyman wrote:

Dein Problem liegt hier:

>
1
> m1:  MOV A,P2
2
>    CJNE A,#31h,m1
3
>

Das ist Quatsch mit Soße.
Du vergleichst alle 8 Portpins, aber Du willst doch nur den Pin testen, 
wo die Taste dran ist.

Also richtig:
1
  jb P2.4, $ ; warten, bis Pin = low
2
; und weiter


Peter

von Timmo H. (masterfx)


Lesenswert?

@Matthias Lipinsky
>Warum machst du nicht einfach eine ordentliche Schrittkette mit
>geeigneten Transitionen für alle Ampelzustände, auch für den Zustand
>"Ampel_gestört_blinkt".
>Interrupts werden dazu nicht benötigt.

Da es sich um eine Aufgabe handelt, würde ich mal fast behaupten dass es 
mit Interrupts gemacht werden soll. Solche aufgaben werden gerne zu 
Übungszwecken verwendet.

von Karl-heinz S. (cletus)


Lesenswert?

Aus meine ASM-Laiensicht:

Ich würde in der ISR nicht zur Blinkroutine springen, sondern nur ein 
Flag ändern, dass regelmäßig in deiner Schaltung abgerufen wird (z.B. 
vor jeder Schaltung und während des Wartens).

So kommst du mit deiner Finite-State-Machine nicht durcheinander...

von Falk B. (falk)


Lesenswert?

Siehe Interrupt

von Karl S. (bullrin)


Lesenswert?

Timmo H. wrote:
> Du musst doch einfach nur die Rücksprungadresse, die beim Auslösen des
> Interrupts gespeichert wird mit der Adresse von "Start" überschreiben.
> Ich weiß jetzt nicht wie das Register beim 8051 heißt, aber da gibts
> bestimmt eins.


mhh wenn ich das wüsste wäre das natürlich die Lösung!


>Interrupts werden dazu nicht benötigt.

Ist aber leider in der Aufgabe verlangt.


>Dein Problem liegt hier:
Danke stimmt hast du Recht, das mit $ hatten wir noch nicht gelernt.
Ändert aber leider nichts an meinem Problem.


>Ich würde in der ISR nicht zur Blinkroutine springen, sondern nur ein
>Flag ändern, dass regelmäßig in deiner Schaltung abgerufen wird (z.B.
>vor jeder Schaltung und während des Wartens).
>
>So kommst du mit deiner Finite-State-Machine nicht durcheinander...

Sry versteh ich nicht ganz.


>Siehe Interrupt

Mh joa hat mir jetzt nicht weitergeholfen, wenn du auf was spezielles 
Hinweisen willst, gib mir bitte noch ein Stichwort ;)





Danke auf jeden Fall für die vielen Antworten in kürzester Zeit! Ich bin 
sicher wir finden eine Lösung!




Greetz

von Skua C. (skua)


Lesenswert?

Im Init
mov R7,#0

in ISR
mov R7,#1

vor jedem lcall zeitx
mov A,R7
CJNE A,#1,blinken

am ende von blinken
mov R7,#0
ljmp start

von Karl S. (bullrin)


Lesenswert?

Skua S. wrote:
> Im Init
> mov R7,#0
>
> in ISR
> mov R7,#1
>
> vor jedem lcall zeitx
> mov A,R7
> CJNE A,#1,blinken
>
> am ende von blinken
> mov R7,#0
> ljmp start


Das ist ja genial! Glaube mein INF Lehrer wird das nicht raffen :D
Hab kurz gebraucht es nachzuvollziehen, aber macht echt sinn und ist 
genialst!
Vielen Dank!!!




NOch ne Frage benutzt hier jemand 8051win? Ist das Problem bekannt das 
ich beschrieben habe? Also das ich die Ampelschaltung mit SETB und CLRB 
machen muss und nicht einfach MOV p2, wert?

von Peter D. (peda)


Lesenswert?

Karl Suleyman wrote:
> NOch ne Frage benutzt hier jemand 8051win? Ist das Problem bekannt das
> ich beschrieben habe? Also das ich die Ampelschaltung mit SETB und CLRB
> machen muss und nicht einfach MOV p2, wert?

Welches Problem?

Du benutzt es ja:
1
blink:  MOV R1,#30d
2
m4:  MOV P2,#00h          ;<- hier
3
   LCALL zeit1
4
   MOV P2,#02h            ;<- und hier
5
   LCALL zeit1
6
   DJNZ R1, m4
7
   RET

Also funktioniert es doch.
Wäre auch schlimm, wenn ein 8051-Assembler kein MOV könnte.


Peter

von Matthias L. (Gast)


Lesenswert?

>Ich würde in der ISR nicht zur Blinkroutine springen, sondern nur ein
>Flag ändern, dass regelmäßig in deiner Schaltung abgerufen wird (z.B.
>vor jeder Schaltung und während des Wartens).

Und was macht das denn für einen SInn?
Da kann ja gleich statt des Flags, das EIngangspin abgefragt werden!
(So wie es sinnvoller ist)


>>Interrupts werden dazu nicht benötigt.
>Ist aber leider in der Aufgabe verlangt.

Beitrag "Re: Berechnung einer Pause"

von Skua C. (skua)


Lesenswert?

Die Bitbefehle sind doch das tolle an den Dingern.

Der Assembler hat bestimmt auch einen EQU Befehl.

Damit kannst du am anfabg des Programmes die Pins und Register benennen.


Dann geht sowas wie
CLRB RotFussgaenger
SETB GruenFussgaenger

oder

MOV Anforderung,#1

von Karl S. (bullrin)


Lesenswert?

@lippy: Ja was will man tun! Das ganze ist sogar ein Projekt und wird 
mir wenn ichs gut mach 12pkt (Abi Note) bringen O.o ....


Stimmt mit EQU könnt ich das ganze eigentlich ein wenig Durchschaubarer 
machen ;)

Was mir noch eingefallen ist, wenn ich vor jedes LCall die Abfrage 
mache, ob der Interrupt ausgelöst wurde, dauert das ja auch noch eine 
gewisse Zeit bis dann Blink wirklich aufgerufen wird. Das ist ja gerade 
der Sinn am Interrupt das es keine Verzögerung geben soll.


Kann ich denn irgendwie die Rücksprungadresse vom Interrupt verändern?
Die wird doch im Stack gespeichert oder?



Das Problem mit dem MOV Befehl war, dass wenn ein Bit gelöscht wurde, 
konnte man es nicht mehr neusetzen. Ich werde aber das noch einmal 
überprüfen.

Was wäre denn die saubere Lösung die man bevozugen sollte? Mit SETB CLRB 
oder MOV?

von Matthias L. (Gast)


Lesenswert?

>Das ganze ist sogar ein Projekt und wird
>mir wenn ichs gut mach 12pkt (Abi Note) bringen O.o ....

Ich würde das dann ohne Interrupt programmieren. Eine ordentliche 
Schrittkette mit geeigneten Transistionen und fertig.

Bei Punktabzug würde ich mit den Lehrern rumdiskutieren.

(Hab ich immer so gemacht-geschadet hats mir gewöhnlich nicht)

von Karl S. (bullrin)


Lesenswert?

mh ok kannst du mir noch kurz sagen was "geeignete Transistionen" sind? 
Habe ich so noch nie gehört und google hat mir jetzt auch nichts 
erklärendes geliefert.

Meinst du damit die Abfragen?

von Matthias L. (Gast)


Lesenswert?

>Meinst du damit die Abfragen?
Ja. Das sind die Übergänge von einem Schritt in einen anderen.

>mit 1 Kfz Ampel und 1 Fußgängerampel
Man könnte das etwa so aufschlüsseln:

Nr.  ZustandsName       Kfz-Ampel(R+Ge+Gn)   Fussgängerampel(R+Gn)
=======================================================================
 0      Ampel aus       blinkt gelb          alles aus
 1      Stopp           rot                  rot
 2      Anfahren        rot+gelb             rot
 3      Fahren          grün                 rot
 4      Bremsen         gelb                 rot
 5      Laufen          rot                  grün

Das sind die Zustände. Jetzt musst du dir für jeden Zustand separat 
Gedanken machen, unter welchen Bedingungen du in welchen (neuen) Zustand 
übergehst.

Beispiel:
Zustand 3:Fahren
Dieser Schritt wird beendet, wenn (zB):
- eine Zeit x abgelaufen ist, dann zu Zustand 4.
- Notbetrieb aktiviert, dann zu Zustand 0

Das war beispielhaft (und muss nicht stimmen). Mache das für jeden 
Zustand.

Das kannst du dann ganz easy programmieren:
Beitrag "Re: Programm bzw. Ablaeufe steuern"

von Karl-heinz S. (cletus)


Lesenswert?

Matthias Lipinsky wrote:
>>Ich würde in der ISR nicht zur Blinkroutine springen, sondern nur ein
>>Flag ändern, dass regelmäßig in deiner Schaltung abgerufen wird (z.B.
>>vor jeder Schaltung und während des Wartens).
>
> Und was macht das denn für einen SInn?
> Da kann ja gleich statt des Flags, das EIngangspin abgefragt werden!
> (So wie es sinnvoller ist)
>

1) Weils gefordert ist.

Und rational: 2) Eine Störung ist eine Störung, und die muss in einer 
Ampelanlage sicher gefangen werden und in einen definierten Zustand 
führen.

Wenn das Signal 'Störung' nur sehr kurz anliegt, kann es sonst sein, 
dass es von der Anlage nicht bemerkt wird....

von Matthias L. (Gast)


Lesenswert?

>Wenn das Signal 'Störung' nur sehr kurz anliegt,

Eine Ampelanlage ist kein schnelles (Mikro..Nanosekunden) System!
Also was soll da hier kurz sein..?


>Weils gefordert ist.

Das ist kein Argument. Oder gilt bei Entwicklungen auch:
"Junger Freund, wir machen das schon immer so!"

Wenn das so wäre, würden wir heute noch in Höhlen hausen!


Aber wenns dir gefällt, bau in der ISR ein Flag ein, welches du dann 
zyklisch abfragst. Das ist zwar sinnlos aufwändig, aber du hast deine 
ISR..

von Peter D. (peda)


Lesenswert?

Karl Suleyman wrote:
> Skua S. wrote:
>> Im Init
>> mov R7,#0
>>
>> in ISR
>> mov R7,#1
>>
>> vor jedem lcall zeitx
>> mov A,R7
>> CJNE A,#1,blinken
>>
>> am ende von blinken
>> mov R7,#0
>> ljmp start
>
>
> Das ist ja genial! Glaube mein INF Lehrer wird das nicht raffen :D

Wenn er es rafft, wirds aber ne 6 geben.

Aus einem Interrupt ins Main zu springen ist ein ganz böses Foul, weil 
das bald einen Stacküberlauf gibt.
Solche "genialen" Stolperfallen sind typisch für Anfänger.
Man muß erstmal den Unterschied zwischen einem Jump und einem Call 
lernen.

Es klang ja schon an, daß Interrupt Unterbrechung mit nachfolgender 
Wiederaufnahme bedeutet und daher nicht gut geeignet ist, um etwas 
abzubrechen.
Auf MCs setzt daher der Interrupt nur ein Flag, womit dann in der 
Mainloop verzweigt wird.


In Betriebssystemen kann ein Interrupt auch etwas abbrechen, indem er 
Funktionen aufruft, um eine laufende Task zu killen. Das ist aber doch 
sehr kompliziert, da dabei der Stack und der RAM aufgeräumt werden muß 
und diverse andere Sachen.


Peter

von Karl S. (bullrin)


Lesenswert?

@ peda:

der springt aber nicht von isr ins main. er setzt ja nur ein Register.
blinken ist ja ein UP und wird von dem Vergleich aufgerufen. Nicht 
direkt von der ISR.

So dürfte es kein Stack überlauf geben.

Berichtige mich wenn ich doch falsch liege ;)


Wollte ich kurz anmerken, die anderen Beiträge habe ich noch nicht 
verarbeitet ;)


@Lippy: Ich glaube das würde unseren Umfang sprengen. Klar sieht 
wahrscheinlich so sauberes Programmieren aus, mit case und if, 
allerdings fällt dem Lehrer das sofort auf, dass es nicht von mir sein 
kann, denn das haben wir selbst so noch nicht gemacht.
Deshalb fordert er das auch so nicht.

von Matthias L. (Gast)


Lesenswert?

>allerdings fällt dem Lehrer das sofort auf, dass es nicht von mir sein
>kann, denn das haben wir selbst so noch nicht gemacht.

Das ist gewöhnlich aber kein Problem. Wenns eine Hausaufgabe ist, kannst 
du dir jederzeit Hilfe holen.
Wichtig ist jedoch immer, das du die Lösung erklären kannst.
Also wenn du mein Vorschlag selbst durchziehst, dann kannst du dem 
lehrer auch alles im Detail erklären. Somit kann er das nicht negativ 
bewerten.

Wenn er will, das du das allein machst, dann muss es eine Klausur sein.


>Ich glaube das würde unseren Umfang sprengen.
Das ist ein Trugschluss. Ich würde sagen, das dauert mit Programmierung 
einen Samstagnachmittag (vielleicht den Abend noch, als Anfänger).
Sicherlich dauert das Austellen der Zustände und deren Übergänge 
(Transitionen) länger als das danach zu programmieren, aber so ist das 
gewöhnlich bei "professioneller Programmierung". Und: Gewöhnlich 
funktioniert das dann auf Anhieb.


Eine Fehlersuche, aufgrund von Spaghetticode dauert Größenordungen 
länger..

PS: 70% des Codes schreibt man in 30% der Zeit.

von Peter D. (peda)


Lesenswert?

Karl Suleyman wrote:
> der springt aber nicht von isr ins main. er setzt ja nur ein Register.
> blinken ist ja ein UP und wird von dem Vergleich aufgerufen. Nicht
> direkt von der ISR.

Stimmt, er setzt wohl nur ein Flag.
Ist eben schwer, Code zu verstehen, wenn er nicht richtig da steht.

Statt ein ganze Byte zu nehmen "MOV R7,#1", reicht aber ein Bit völlig 
aus "SETB F0".


Peter

von Karl S. (bullrin)


Lesenswert?

na toll jetzt wollte ich den quellcode ändern und mir in 8051win 
anschauen, nun funktioniert dieses Programm nicht mehr. Ich könnte 
verrückt werden...

Klick ich auf Run oder Step passiert einfach nichts mehr.

von Karl-heinz S. (cletus)


Lesenswert?

Matthias Lipinsky wrote:
>>Wenn das Signal 'Störung' nur sehr kurz anliegt,
>
> Eine Ampelanlage ist kein schnelles (Mikro..Nanosekunden) System!
> Also was soll da hier kurz sein..?
>

Darum geht es ja nicht. Ab dem Moment, wo du nicht mehr garantieren 
kannst, dass wirklich alle Störungen abgefangen werden, ist das doch 
eher mies.


Leute, die behaupten, man müsse diverse Eingaben nicht prüfen, weil 
String nie länger als xx Zeichen wären, sind auch alle hingefallen.

Bei sicherheitstechnischen Anlagen geht es am Ende wirklich nur darum 
beweisen zu können, dass alle Störungen in einen sicheren Zustand 
überführt werden.

von Karl S. (bullrin)


Lesenswert?

Danke auf jeden Fall für eure Antworten!

Gibt es noch weiter Vorschläge? Konnte leider bisher noch nichts Testen 
da ich hier keinen Lizenzschlüssel habe. Nur in der Schule :(

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.