mikrocontroller.net

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


Autor: Karl Suleyman (bullrin)
Datum:

Bewertung
0 lesenswert
nicht 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:
  INCLUDE REG_51.pdf
 
  code at 0

   SJMP init
   ORG 0013h

isr:  LCALL blink
   RETI
   
   
init:  SETB EA
   SETB EX1
   SETB IT1  
 
start: SETB P2.0
   CLR P2.1
   CLR P2.2
   CLR P2.3
   SETB P2.4

   CLR P2.6
   CLR P2.7
     
m1:  MOV A,P2
   CJNE A,#31h,m1   
   SETB P2.6
   CLR P2.6
   LCALL zeit1
   CLR P2.0
   SETB P2.1
   LCALL zeit1
   CLR P2.1
   SETB P2.2
   LCALL zeit1
   SETB P2.3
   CLR P2.4
   LCALL zeit2
   CLR P2.3
   SETB P2.4
   LCALL zeit1
   SETB P2.1
   LCALL zeit1
   SETB P2.0
   CLR P2.1
   CLR P2.2
   JMP start

zeit1:  ;Übergangsphase 1s
   MOV R0, #00Fh
m2:  DJNZ R0,m2   
   RET

zeit2:   ;Auto-Rotphase  4s
   MOV R0, #0FFh
m3:  DJNZ R0,m3
         RET
        
        
blink:  MOV R1,#30d
m4:  MOV P2,#00h
   LCALL zeit1
   MOV P2,#02h
   LCALL zeit1
   DJNZ R1, m4
   RET

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

Autor: Timmo H. (masterfx)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Matthias Lipinsky (lippy)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Karl Suleyman wrote:

Dein Problem liegt hier:

>
> m1:  MOV A,P2
>    CJNE A,#31h,m1
> 

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:
  jb P2.4, $ ; warten, bis Pin = low
; und weiter


Peter

Autor: Timmo H. (masterfx)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Karl-heinz Strunk (cletus)
Datum:

Bewertung
0 lesenswert
nicht 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...

Autor: Falk Brunner (falk)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Siehe Interrupt

Autor: Karl Suleyman (bullrin)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Skua C:\> (skua)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Karl Suleyman (bullrin)
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht 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:
blink:  MOV R1,#30d
m4:  MOV P2,#00h          ;<- hier
   LCALL zeit1
   MOV P2,#02h            ;<- und hier
   LCALL zeit1
   DJNZ R1, m4
   RET

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


Peter

Autor: Matthias Lipinsky (lippy)
Datum:

Bewertung
0 lesenswert
nicht 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"

Autor: Skua C:\> (skua)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Karl Suleyman (bullrin)
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: Matthias Lipinsky (lippy)
Datum:

Bewertung
0 lesenswert
nicht 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)

Autor: Karl Suleyman (bullrin)
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: Matthias Lipinsky (lippy)
Datum:

Bewertung
0 lesenswert
nicht 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"

Autor: Karl-heinz Strunk (cletus)
Datum:

Bewertung
0 lesenswert
nicht 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....

Autor: Matthias Lipinsky (lippy)
Datum:

Bewertung
0 lesenswert
nicht 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..

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Karl Suleyman (bullrin)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Matthias Lipinsky (lippy)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Karl Suleyman (bullrin)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Karl-heinz Strunk (cletus)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Karl Suleyman (bullrin)
Datum:

Bewertung
0 lesenswert
nicht 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 :(

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.