Ich hätte da mal ein Problem :)
ich habe mir relativ simpel mit 4 tastern folgendes szenario
programmiert:
taster 1-3 sind 3 verschiedene programme
taster 0 ist der interupt "stop" taster
klappt auch alles. die interuptroutine wird auch ausgeführt.
in den 3 programmen habe ich einfach eine LED bissi blinken gelassen mit
nem delay
und eben genau das schaltet die interuptroutine nicht aus?
werden unterprogramme von der routine gänzlich ausgenommen?
die unterprogramme sind kopiert und mit absicht "nicht" ordentlich
programmiert, da das nur dummies sind.
ich möchte, bevor ich anfange die unterprogramme zu schreiben die
aufrufroutinen der programme fertig und ordentlich haben. der stop
taster soll immer zu jeder zeit ein programm beenden können, analog
einer NOTAUS-Software (NOTAUS muss ja hardwaretechnisch sein nicht
softwaretechnisch)
hier mein code:
1
#define F_CPU 3686400UL // CPU Takt, externer Quarz
2
#define BAUD 9600 // Baudrate = 9600
3
#include<avr/io.h> // Einbinden der Bib In/Out
4
#include<util/delay.h> // Einbinden der Bib Delay
5
#include<stdint.h> // Einbinden der Bib StandardInteger
6
#include<avr/interrupt.h> // Einbinden der Bib Interrupt
Sven Weinmann schrieb:> und eben genau das schaltet die interuptroutine nicht aus?
Was meinst du mit 'ausschalten'.
Wenn der Interrupt kommt, unterbricht er den normalen Programmfluss. In
deiner ISR wird eine 'Unterbrechung' gemacht, solange wie der Taster
gedrückt ist. Ist diese Bedingung nicht mehr gegeben, dann geht es genau
an der Stelle weiter, an der der Haupt-Programmfluss unterbrochen wurde.
> werden unterprogramme von der routine gänzlich ausgenommen?
Nö.
Interrupt ist Interrupt. Egal was der µC in der Hauptroutine macht,
sobald der Interrupt kommt, unterbricht die ISR diesen Ablauf.
Es wäre vernünftig, wenn du sagen würdest, was du siehst und wie sich
das von dem unterscheidet, was du erwartet hättest.
>Es wäre vernünftig, wenn du sagen würdest, was du siehst und wie sich>das von dem unterscheidet, was du erwartet hättest.
Möglicherweise hat er gerade entdeckt das Taster prellen
und eine Abfrage per INT0 einfach nur Gurkenkram ist;)
holger schrieb:>>Es wäre vernünftig, wenn du sagen würdest, was du siehst und wie sich>>das von dem unterscheidet, was du erwartet hättest.>> Möglicherweise hat er gerade entdeckt das Taster prellen> und eine Abfrage per INT0 einfach nur Gurkenkram ist;)
Das kann durchaus sein, denn
> Ich hätte da mal ein Problem :)
das Problem ist nicht der Taster (ok, er ist auch ein Problem) sondern
der ganze Programmaufbau. Solange er sich nicht von _delay_ms löst, ist
das relativ sinnlos. So wird das nichts mit Blinksequenzen, die
unterbrechbar und/oder zu jedem Zeitpunkt wechselbar sind.
Hi Swen
>die unterprogramme sind kopiert und mit absicht "nicht" ordentlich>programmiert, da das nur dummies sind
Tja, so liebt man diese Fragestellung.... ich sag es mal mit anderen
Worten.... Ich hab da was hingeschludert und es funktioniert nicht so
wie gedacht...
Fang mal da an, wo (fast) alle Programmierer mit beginnen:
"Ein Projekt".
Das wird beschrieben, mit den Funktionen die es erledigen soll. Das ist
erst einmal Skizzen auf Papier malen. Wenn du dir dann im klaren bist,
was dein Programm erfüllen soll, dann kommt Abschnittweise Programm
zusammen. Möglichst kleine prüfbare Schritte und erst weiter, wenn
Aufgabe erfüllt. So dahingeschluderte Funktionen machen nicht wirklich
Sinn. Und der Lerneffekt, na ja, mal ehrlich, außer "das geht nicht"
ist nur geringe Erkenntnis gegeben. SChau dir mal deine Doku an. Da
steht u.a. folgendes:
>Der Stop-Taster an Port D2 wird im ganzen Programm niemals abgefragt. Das >Konstrukt if ( bit_is_clear ( PIND,2 )) existiert> hier also nicht. Der Stop-Taster wird „hardwaremäßig“ abgefragt.
Nun jeder Taster ist Hardware und wenn er an einem µC hängt hängt, dann
wird er, wenn er irgendwo gebraucht wird auch softwaremäßig erfasst. Ob
in einer ISR oder im Polling, das ist erst mal völlig irrelevant. Ein
Not-Aus ist Hardware und schaltet z. B. die Leistung weg. So wie dein
Lichtschalter das Licht. Das ist Hardware.
Solche Kommentare sind irreführend und du selbst gehst dem auf dden
Leim. Versuche Interrupts zu verstehen und dann erkennst duu auch, warum
hier alle das als Blödsinn abtun. ( na ja, es gibt auch hin und wieder
mal einen Versuch, diese Vorgehensweise zu rechtfertigen... )
Normalerweise läßt du ein Programm immer durch die Hauptschleife rennen.
Unterwegs schaust du, ob es irgendwelche Ereignisse gibt, die erledigt
werden müssen. Nur so kannst du sicherstellen, das jeder Block auch so
funktioniert, wie er soll. Nimmst du ein "Delay" in dein Programm und
bremst den Ablauf, ist ein oft "unerklärliches Verhalten" die Folge.
Auch wenn ich nichts mit C am Hut hab, ist nach meiner Meinung die
Umsetzung einer Aufgabe in C genauso aufzubauen, wie sie sinnvollerweise
in anderen Sprachen gemacht wird.
Daher mein Tip:
Du willst mit einfachen Übungen Erkenntnisse erlangen. Gut, aber dann
lerne aus den Ergebnissen. Und wenn du das nicht verstehst, dann denk
mal nach.
>die unterprogramme sind kopiert und mit absicht "nicht" ordentlich>programmiert, da das nur dummies sind
Etwas kopiertes ist nicht unbedingt erfolgreiches Lernen.
Einen "schnellen Erfolg" wollen zwar viele, aber glaub mir, es dauert
eben eine Zeit, bis man versteht, wie es funktioniert.
Gruß oldmax
hallo leute,
hm ich bin ein wenig sprachlos :)
da lösche ich den halben quellcode hier raus, um es übersichtlicher zu
machen und dann kommen solche antworten :)
also zunächst habe ich genau so begonnen, kleine programmabschnitte zu
programmieren und zu testen. diese sind oben nicht aufgelistet, weil die
ADC oder die motorsteuerung oder oder oder da nichts zu suchen haben.
meine frage ging dahin, ob ein interupt ALLES unterbricht oder nur die
main routine.
ich entnehme euren antworten, dass es alles unterbricht. aber ich habe
in einem beitrag auch gelesen:
Karl Heinz Buchegger schrieb:> Solange er sich nicht von _delay_ms löst, ist> das relativ sinnlos. So wird das nichts mit Blinksequenzen, die> unterbrechbar und/oder zu jedem Zeitpunkt wechselbar sind.
was bedeutet das?
baut man blinksequenzen nicht mit delay? sondern mit for-schleifen?
und kann man delay nicht unterbrechen? was wäre denn (weiß ja nicht ob
ich delay im späteren verlauf irgendwo benutze), eine alternative.
das delay sollte mir an den drei stellen nur simuliern, dass das
unterprogramm läuft. es benötigt ja jedes eine zeit x, die ich mir
irgendwie darstellen wollte, um die interupt routine zu testen.
daher finde ich die aussage:
oldmax schrieb:> Etwas kopiertes ist nicht unbedingt erfolgreiches Lernen.> Einen "schnellen Erfolg" wollen zwar viele, aber glaub mir, es dauert> eben eine Zeit, bis man versteht, wie es funktioniert.
bisschen doof, da ich oben extra schrieb, dass es absichtlich dummie
codes sind und kein quellcode. hätte ich das anständig gemacht hätte ich
mir für´s blinken ein unterprogramm geschrieben und hätte mir beim
aufruf, die anzahl und die zeit mit übergeben, statt es dreimal gleich
hinzuschreiben. das meinte ich eigentlich damit :)
nun hoffe ich aber, dass wir auf einer welle sind^^ und ich das mit dem
delay irgendwie verstehen kann.
sollte/gibt es eine möglichkeit wenn ein interupt ausgeführt wird ALLES
zu beenden, egal was. unt mit beenden meine ich nicht unterbrechen?
gruß sven
Etwa chaotisch Deine Beschreibungen.
Ich interpretiere das mal so:
Wenn der Interrupt ausgelöst wurde, sollen die grade laufenden
Unterprogramme beendet werden.
Lösung:
Im Interruptprogramm vermerkst Du daß es aufgerufen wurde in einer
Variablen.
- In den Unterprogrammen mußt Du diese Variable abfragen, um zu
erkennen, daß der Interrupt ausgelöst wurde.
- Dann beendest Du das Unterprogramm durch einen Rücksprung und sonstige
Maßnahmen, die noch zu tun sind.
Jetzt wirds vielleicht sinnig, daß eine Delay bei dieser
Aufgabenstellung horrender Blödsinn ist. Im Delay merkst Du nix vom
Interrupt, auch wenn er kommt.
Interrupt mit Tasten ist immer eine blöde Idee. Begründung kommt gern,
ist mir grad zu viel zu schreiben.
Viel schlauer ist es die Stop-Taste nicht an den Interrupt zu koppeln.
- Bau keine Delays ein, so das die Main flott durchlaufen wird.
- Frag die Stop-Taste im Main ab.
- Reagier auf die Stop-Taste in dem die Unterprogramme nicht mehr
ausgeführt werden, die Motoren gestoppt werden, und was sonst noch alles
zu tun ist.
Hallo Sven,
es gibt keine Möglichkeit das Progrramm zu beenden im Sinne von "alles
steht".
Aber wie "spontan" geschrieben hat: Setze in der Inerruptroutine ein
Flag, mach in der Main abhängig von diesem Flag das was gemacht werden
muss (zB. Ausgänge a schal
ten usw.)
Und dann rufe eine Endlosschleife auf. Diese läuft dann so lange im
Kreis bis ein Reset kommt.
mfG Ulli
Sven Weinmann schrieb:> hallo leute,>> hm ich bin ein wenig sprachlos :)>> da lösche ich den halben quellcode hier raus, um es übersichtlicher zu> machen und dann kommen solche antworten :)
Sven.
Der springende Punkt ist, dass der komplette Programmaufbau nicht
stimmt. Wenn du dafür schon rausgeworfen hast, dann sind die Dinge noch
schlimmer als ursprünglich gedacht.
>> also zunächst habe ich genau so begonnen, kleine programmabschnitte zu> programmieren und zu testen.
Ist alles ok.
Trotzdem stimmt dein Aufbau nicht.
Das eine ist die Technik des Programmierens, das Handwerk.-
Das andere ist die Strategie, das Konzept, die Idee, die man mit diesem
Handwerk umsetzt.
Man muss beides beherrschen! Du kannst ein noch so guter
Programmier-Handwerker sein, wenn du nicht ein paar
Programmierstrategien beherrscht, Wissen darüber, wie man bestimmte
Problemstellungen vernünftig in ein Konzept umwandelt, wird das nichts
(und natürlich unzählige Standard-Algorithmen). >Ein Programm entwickeln
ist nun mal nicht so leicht, wie es aussieht. Nicht umsonst spricht man
von mindestens ein paar Monaten, ehe jemand vom Anfänger zum
fortgeschrittenen Anfänger aufsteigt. Und bis man in die Riege der
Experten aufsteigt, dauert es Jahre. Meinen Azubis hab ich ca. 1 Jahr
gegeben (5 Tage die Woche, 8 Stunden am Tag), ehe ich sie als 'fürs
Produktionsprogrammieren geeignet' eingestuft habe. Dieses Jahr brauchen
sie! In diesem Jahr lernen sie!
In dem Moment, in dem du 'Warten' mit 'delay_ms' assozierst, in dem
Moment bist du schon auf dem Holzweg.
Der Schlüssel zu einem guten µC-Programm besteht darin, seine Denkweise
umzustellen. Die ganze Denkweise
erst schalte ich was ein
dann warte ich eine Zeit lang
dann schalte ich es aus
diese ganze Denkweise ist schon der 'Weg zur Hölle'.
Du musst anfangen zu arbeiten, wie eine Hausfrau.
Die stellt nicht das Gulasch auf den Herd, bleibt daneben stehen bis es
kocht, schaltet den Herd aus und geht zur Waschmaschine, räumt die
Wäsche ein, bleibt daneben stehen bis die Maschine fertig ist und räumt
dann aus, Sondern sie macht das alles 'gleichzeitig'!
Genau gleichzeitig geht natürlich nicht, aber man kann im schnellen
Wechsel immer ein bischen was an einer Aufgabe machen
Herd einschalten
Wäsche einräumen
Am Herd nachsehen ob Gulasch kocht
Waschmaschine einschalten
Am Herd nachsehen ob Gulasch kocht
An der Waschmaschine nachsehen ob fertig
Am Briefkasten nachsehen ob Post da ist
erste Rechnung der Hausaufgaben der Kinder kontrollieren
Am Herd nachsehen ob Gulasch fertig
An der Waschmaschine nachsehen ob fertig
Fische im Auquarium füttern
Am Herd nachsehen ob Gulasch kocht. Ja -> Gulasch ausschalten
Zweite Rechnung der Kinder kontrollieren
Besteck auf Esstich legen
Waschmaschine nachsehen ob fertig
Teller auf Esstisch legen
....
Alle Aufgaben werden in kleine Happen zerlegt, von denen keiner lange
dauert. Und reihum wird bei jeder 'Arbeitsstelle' nachgesehen, ob es
etwas zu tun gibt. Wenn ja, dann wird das gemacht und eventuell der
nächste 'Happen' aktiviert.
Und auf die Art schafft man es, dass ein µC scheinbar mnühelos mehrere
Dinge gleichzeitig machen kann. Unter anderem auch die Beobachtung von
Tasten, von denen einer dazu dient das ganze Werkl wieder auf 0 zu
stellen.
In deiner Problemstellung kommen mehrere Konzepte vor. Da gibt es
* Tastenabfrage. Dazu hat sich die PeDa Entprellung bewährt, die
auf einem Timerinterrupt und Polling basiert.
Entprellung
* Wenn wir schon bei Timer sind. Timer sind DAS Arbeitspferd in der
µC Programmierung. Abgesehen von ganz einfachen Lernbeispielen
kommt so gut wie kein Programm ohne Timer aus. Wann immer es um
irgendwelche Zeitsteuerungen geht, läuft der Lösungsansatz immer
über Timer. Nur am ANfang nimmt man _delay_ms, denn niemand kann
alles auf einmal lernen und irgendwo muss man ja auch mal anfangen
und erste Programme schreiben. Sobald aber eine kritische Wissens-
masse erreicht ist, führt an Timern kein Weg mehr vorbei
FAQ: Timer
* Ablaufsteuerungen
Wo immer möglich versucht man Abläufe auf Kennzahlen zu reduzieren
und legt diese Kennzahlen in Arrays
* Programmlogik
Das Konzept einer Zustandsmaschine hat sich extrem bewährt um
Abläufe in den Griff zu kriegen. Das ist das Werkzeug um
komplexe Maschinenlogiken in den Griff zu bekommen, in denen
Vorgänge von anderen Vorgängen abhängen und deren Beendigung
wieder neue Vorgänge anstossen.
Statemachine
Und wahrscheinlich habe ich noch 10 andere durchaus wichtige Konzepte
jetzt vergessen, ohne die du nicht weiterkommst auf deinem Weg zu einem
vernünftigen Programm.
Hi Sven
Du machst nichts besser, wenn du Text ein bisschen doof findest....
>daher finde ich die aussage:>oldmax schrieb:>> Etwas kopiertes ist nicht unbedingt erfolgreiches Lernen.>> Einen "schnellen Erfolg" wollen zwar viele, aber glaub mir, es dauert>> eben eine Zeit, bis man versteht, wie es funktioniert.>bisschen doof, da ich oben extra schrieb, dass es absichtlich dummie>codes sind und kein quellcode. hätte ich das anständig gemacht hätte ich>mir für´s blinken ein unterprogramm geschrieben und hätte mir beim>aufruf, die anzahl und die zeit mit übergeben, statt es dreimal gleich>hinzuschreiben. das meinte ich eigentlich damit :)
Doof finde ich u. a. , wenn man absolut nix mit deutscher
Rechtschreibung am Hut hat und die Groß- und Kleinschreibung ignoriert.
Aber das hat nix mit dem Thema zu tun und nur mal am Rande.
Du hast nicht verstanden, was ein Programm ist. Ein Interrupt ist etwas,
was einen Programmablauf unterbricht und eine andere Arbeit dazwischen
schiebt. Danach wird an der unterbrochenen Stelle die Arbeit
fortgesetzt. Willst du ein Unterprogramm mit einem Interrupt
"abbrechen", so ist das zwar möglich, aber nicht so, wie du denkst.
Ich schreib mal, wie ich das sehe:
Du hast einen Antrieb, der mit dem UP "Drehe_Rechts" bzw. "Drehe_Links"
eine Bewegung bis in eine Endlage ausführt. Signalisiert ein Sensor,
Endlage erreicht, dann verläßt du das UP und der Antrieb bleibt stehen.
Diese Denkweise ist falsch !
Der Controller hat ja noch anderes zu tun, daher ist ein Programm anders
anzugehen:
Hier mal ein Schema nach dem uralten "EVA" - Prinzip:
Loop:
(E)ingänge lesen
(V)erarbeite-> soll Antrieb rechts laufen-> ja, dann setze Merker
Rechts
-> Sensor rechts erreicht- ja, dann lösche Merker Rechts
-> soll Antrieb links laufen -> ja, dann setze Merker links
-> Sensor links erreicht-> ja, dann lösche Merker links
-> Taster "Halt" gedrückt->ja, lösche Merker rechts und
links
-> mach andere Aufgaben
(A)usgabe Merker
Weiter bei Loop
Interrupt:
Taster "Not-Halt"
ja, dannn lösche Merker rechts und links
Ende Interrupt
Der Trick ist, das du mit Tastern die entsprechenden Merkerbits setzt
und das Programm nicht dauernd fragt, "hälst du den Taster noch ?"
Solange gesetzt, ist auch der Ausgang gesetzt. Löscht dir die ISR den
Merker, dann wird beim nächsten Erreichen der Ausgabe auch der Ausgang
weggeschaltet. Willst du noch schneller reagieren, dann kommt auch das
Schreiben der Ausgänge in der ISR in Betracht. Aber so eine
Programmschleife braucht vielleicht 10 .. 30 msek. Baust du aber
"delays" ein, dann verlängert sich so ein Programmzyklus und das ist
das, was dir die Kollegen hier sagen wollen. Zeiten werden mit dem Timer
generiert. Dieser wird ebenfalls einen Interrupt auslösen, vielleicht
jede msek. In der ISR setzt du dir dann entsprechende "Time_Flags", die
du im Programm für zeitrelevante SChritte auswertest.
Etwa so:
Timer_ISR:
Inc Zeitzähler
Zeitzähler = 10 Setze Flag 10 msek
Zeitzähler = 100 setze Flag 1/10 Sek
Zeitzähler =1000 setze Zeitzähler zurück und setze Flag 1 Sek.
Ende Interrupt
Was macht nun das Hauptprogramm ?
Hier noch einmal das erweiterte Schema
Loop:
(E)ingänge lesen
(V)erarbeite-> soll Antrieb rechts laufen-> ja, dann setze Merker
Rechts
-> Sensor rechts erreicht- ja, dann lösche Merker Rechts
-> soll Antrieb links laufen -> ja, dann setze Merker links
-> Sensor links erreicht-> ja, dann lösche Merker links
-> Taster "Halt" gedrückt->ja, lösche Merker rechts und
links
-> mach andere Aufgaben... z. B.
-> Zeitflag 10 msek -> bearbeite und lösche Flag
-> Zeitflag1/10 Sek -> bearbeite und lösche Flag
-> Zeitflag 1 Sek -> bearbeite und lösche Flag
(A)usgabe Merker
Weiter bei Loop
Du siehst, nirgends wird etwas abgebrochen. Es wird lediglich auf
Ereignisse reagiert. Und das kann ein µC sehr gut. Damit hast du auch
überschaubare Zykluszeiten von deinem programm und nicht einen Zustand,
wo dein Controller tatsächlich nur auf Interrupts reagiert.
Gruß oldmax
oldmax schrieb:> Loop:> (E)ingänge lesen> (V)erarbeite-> soll Antrieb rechts laufen-> ja, dann setze Merker> Rechts> -> Sensor rechts erreicht- ja, dann lösche Merker Rechts> -> soll Antrieb links laufen -> ja, dann setze Merker links> -> Sensor links erreicht-> ja, dann lösche Merker links> -> Taster "Halt" gedrückt->ja, lösche Merker rechts und> links> -> mach andere Aufgaben> (A)usgabe Merker> Weiter bei Loop>> Interrupt:> Taster "Not-Halt"> ja, dannn lösche Merker rechts und links> Ende Interrupt
super erklärt das EVA prinzip, kenne ich ja von der SPS (die ich
übrigends von grund auf gelernt habe im ggsatz zu C! )
ich habe zwar schon mit timern und so gearbeitet, allerdings bin ich
damit nicht 100% vertraut, daher habe ich delay genutzt.
ob ich eine zeiterfassung habe weiß ich noch garnicht, ist aber gut
möglich!
das projekt (portalmanipulator, mit ifrarotsensor) soll 3 programme
beherrschen.
1. komplettfahrt
2. referenzpunktfahrt
3. (steht noch aus, ggf motor einzelansteuerung)
der motor in X-Richtung ist ein elektromotor, welchen ich über eine
L298-Schaltung wenden kann.
der motor in Y-Richtung ist ein Schrittmotor, welcher über eine
L297-L298 Schaltung angesteuert wird, allerdings habe ich da noch keinen
Erfolg, da die Schaltung nicht fuktioniert....
X Ansteuerung funktioniert, da ich automatisch umschalte bei endschalter
"erreichen" dort habe ich einen 10 Stufen Poti dran, den ich via ADC
abfrage.
bei jedem erreichen eines endschalters soll der schrittmotor einen
schritt fahren.
und der sharp sensor soll alle x-schritte, welche ich aus der
angesprochenen ADC entnehme eine messung vornehmen. (hier kann ggf die
zeitrechnung von nutzen sein, da der sensor in den ersten 37ms nicht
korrekt misst)
letztlich sieht das aus wie eine schnecke/schlang die sich in x und y
richtung bewegt.
referenzpunktfahrt soll einfach beide motoren in grundstellung bringen,
oder ggf als zusatz -> je ihren endpunkt anfahren und via ausgabe von
schritten oder adc wert vergleichen ob und wie die werte übereinstimmen,
um eine korrekte auflösung der sensorwerte zu gewährleisten. aber das
nur ggf später, erstmal muss einiges vorher funktionieren.
letztlich soll laut aufgabenstellung das vermessene objekt via visual
studio 2010 optisch dargestellt werden.
es ist also sozusagen eine art sonar mit infrarot sensor um
oberflächenreliefs visualisiert darzustellen.
Hi
>ich habe zwar schon mit timern und so gearbeitet, allerdings bin ich>damit nicht 100% vertraut, daher habe ich delay genutzt.
Da sehe ich einen kleinen Widerspruch.. wenn du damit schon gearbeitet
hast, dann ist es doch kein Problem. Du mußt dich nur von dem Gedanken
trennen, wenn du eine Zeitverzögerung brauchst, dein Programm für diese
Zeit tatenlos werden zu lassen.
Angenommen, du setzt in deiner Timer_Isr alle 100 msek ein Flag, also
ein Bit in einer Variablen. In Assembler ist das wie folgt:
1
lds r16, time_Flag
2
ori r16, 0b00000100
3
sts time_Flag, r16
hab nur mal den relevanten Teil aufgeführt. Nun brauchst du eine
Zeitverzögerung, sagen wir 5 Sek.
immer noch Schleife Hauptprogramm:
->Bedingung für Zeitverzögerung erfüllt,
->setze Zeitwert 50
->reset Bedingung für Zeitverzögerung
->TimeFlag = 1
-> Zeitwert>0 dann
->Zeitwert - 1
-> Zeitwert = 0 dann Zeit_Ende_Flag
-> Time_Flag =0
->Zeit_Ende_Flag = 1 ?
-> Ereignisbearbeitung nach Zeit
-> Zeit_Ende_Flag = 0
-> weiter mit anderen Dingen....
Wie gesagt, ich spreche Assembler daher...
1
LDS r16, Prg_Ctrl ; Programmsteuerkontrolle
2
ANDI r16, 0b00010000 ; Bit Verzögerung für Abschnit "x" starten ?
BRNE ende_Takt ; wenn Zeroflag nicht gesetzt ist ->Ende
30
LDS r16, Event_Flag
31
ORI r16, 00001000 ; definiertes Eventflag setzen
32
STS Event_Flag, r16 ; und ablegen
33
ende_Takt:
34
LDS r16, Time_Flag
35
ANDI r16, 0b111110111 ; Zeitflag zurücksetzen
36
STS Zeit_Flag, r16 ; und ablegen
37
ret
Ich weiß, das man das auch anders lösen und auch Programmtechnisch
anders darstellen kann. So wird aber klar, wie mit den Bits in den
Variablen umgegangen wird und das das Programm nur auf diese Steuerbits
reagiert. Ob das nun ein Programmkontrollbit oder Zeit oder Ereignisbit
ist. Nur wenn so ein Bit gesetzt ist, wird etwas getan, ansonsten nur
weiter im Kreis drehen. Ist ein Ereignis bearbeitet, wird das Bit
gelöscht. Der Vorteil: Dein Programm kann eine einfache Schleife sein.
Willst du etwas neues hinzufügen, kommt halt ein Unterprogrammaufruf in
die Schleife. So kann es auch mal ganz einfach auskommentiert werden.
Wenn du so perfekt auf SPS getrimmt wurdest, dürfte dir die
Assemblerdarstellung bekannt vorkommen. Sie ist ähnlich der AWL.
Gruß oldmax
Variante 1:
Nimm den Interupt mit der höchsten Priorität im System: Den Reset.
Variante 2: (Ich warte schon auf das Geschrei :)
Wenn Du den Prozessor nicht zurücksetzen möchtest, kannst Du im Interupt
den Stackpointer manipulieren, so, daß die Programmausführung nicht mehr
zu der Stelle zurückkehrt, wo sie her kam, sondern dort hin
'zurückkehrt' wo Du weiter machen möchtest.
Ist zwar nicht die feine englische Art, aber was soll's?
Vor allem, wenn Du schon fertige Programmmodule hast, ist dies ein recht
einfacher Weg.
Und es bricht auch Dein delay ab.
Gruß
Jobst
Jobst M. schrieb:> Variante 2: (Ich warte schon auf das Geschrei :)
:-)
> Wenn Du den Prozessor nicht zurücksetzen möchtest, kannst Du im Interupt> den Stackpointer manipulieren, so, daß die Programmausführung nicht mehr> zu der Stelle zurückkehrt, wo sie her kam, sondern dort hin> 'zurückkehrt' wo Du weiter machen möchtest.> Ist zwar nicht die feine englische Art, aber was soll's?> Vor allem, wenn Du schon fertige Programmmodule hast, ist dies ein recht> einfacher Weg.
Und du denkst das kriegt er hin?
Er kriegst ja noch nicht mal auf die saubere englische Art hin. Und die
ist nun wirklich nicht schwer.
Hi
Na ja, der Weg, die Rücksprungadresse im Stack zu ändern, macht riesig
Spaß..... Vor allem, wenn man als Anfänger damit beginnt, wo das Wort
"Stack" noch ziemlich fremdartig klingt. In Assembler geht das in etwa
so....
1
....
2
....
3
pop .... ; Register zurückholen
4
;RETI ; Return from Interrupt ausblenden
5
LDI XL, Low(Ruecksprung) ; Adresszeiger setzen
6
LDI XH, High(Ruecksprung)
7
POP r2 ; Dummiregister für alten Rücksprung
8
POP r2
9
Push XL
10
Push XH
11
Reti
Hab ich so noch nicht getestet, aber sollte gehen. Eventuell ist XH und
XL in der Reihenfolge zu tauschen.....
Gruß oldmax
oldmax schrieb:> Na ja, der Weg, die Rücksprungadresse im Stack zu ändern, macht riesig> Spaß.
Und woher weiß der Interrupt, was alles auf dem Stack liegt ?????
Er weiß es nämlich nicht!
Glaub mir, der Spaß ist ganz schnell vorbei, wenn Du Dich dumm und
dämlich suchst, warum der Stack unter- oder überläuft.
In C kann man das machen mit setjmp, longjmp. Damit wird der CPU-Status
in einer Struct gesichert und kann daraus wieder restauriert werden.
Du wirst aber sehen, daß diese Funktion erfahrene Programmierer nur sehr
sehr selten benutzen.
Peter
Peter Dannegger schrieb:> oldmax schrieb:>> Na ja, der Weg, die Rücksprungadresse im Stack zu ändern, macht riesig>> Spaß.> Und woher weiß der Interrupt, was alles auf dem Stack liegt ?????> Er weiß es nämlich nicht!
Das ist in diesem Fall aber völlig egal. Wenn schon schweinisch, dann
aber richtig: Einfach das komplette RAM, Weicheier ab SP aufwärts,
durchnullen. Dann wird er beim return irgendwas für Adresse 0 halten.
Egal was. 100 Pro, weil ja alles 0 ist.
mfg.
Hi Peter
Nun da ich in Assembler programmiere, denke ich schon, das ich weiß, was
auf dem Stack liegt, dafür stand die "POP ... -Zeile". Aber du hast
recht, sowas ist kaum pflegbar und auch unsinnig für einen Anfänger.
Gruß oldmax
oldmax schrieb:> Nun da ich in Assembler programmiere, denke ich schon, das ich weiß, was> auf dem Stack liegt
Das weißt Du in Assembler auch nicht. Du weißt ja nicht, ob Du im Main
oder in einer Unterfunktion unterbrochen wurdest.
Die Calling-Tiefe kann der Interrupt nicht feststellen. Und auch nicht,
ob noch lokale Variablen auf dem Stack liegen.
Es geht "zuverlässig" nur, wenn man den Stackpointer für den Rücksprung
irgendwo sichert.
"zuverlässig" deshalb, weil es das in Real nicht ist.
Z.B. Du drückst die Taste während ein 4Bit-Nibble zum LCD übertragen
wird, springst irgendwo hin und ab da zeigt das LCD nur noch Unsinn an,
weil die Nibble vertauscht sind.
Peter