Hallo,
ich habe eine Platine entwickelt auf Atmega32 Basis. Diese wertet
Sensoren aus und schaltet Aktoren.
Nun ist es so, dass eine übergeordnete Steuerung meiner Platine ein
Go/Stop Signal übergeben kann. Ich wollte diesen PIN dann mit einem
Interrupt abfragen, aber leider sind die externen Interruptpins alle
belegt. Die Platine wurde professionel gefertigt und ich habe dies
einfach nicht bedacht.
Jedenfalls kann ich dieses Go/Stop Signal immernoch an einen anderen Pin
abfragen.
Habe das Programm schon fertig, sequentiell mit if abfragen und while
schleifen. Also bei while auf einen Zustand warten und den Aktor
schalten /abschalten.
Nun ist das Problem eben mit dieses Go/Stop. Das müsste ich ja in jeder
Zeile abfragen und was passiert dann? Ich rufe eine Funktion auf es wird
was gemacht und dann wird ja wieder in das Hauptprogramm gesprungen.
Meine Frage nun: Ist es eine bessere Lösung mit Switch case Anweisungen
zu Arbeiten. Also in jedem case etwas mit if machen und einen Zähler
hochsetzten der dann zur nächsten case springt. Gleichzeitig aber
Go/Stop abfragen und wenn das zutrifft den Zähelr auf Null setzten um
somit von vorn zu beginnen. Ist quasi das Statemachine Prinzip.
Oder gibt es noch bessere Möglichkeiten. Danke schonmal.
Julian S. schrieb:> Oder gibt es noch bessere Möglichkeiten. Danke schonmal.
ja, mit einer Statemachine arbeiten. Dann bist du immer in der
Hauptschleife und kannst solche dinge sehr einfach einbauen.
Dein code ist dafür viel zu unflexibel.
http://www.mikrocontroller.net/articles/Statemachine
> Hast Du einen Timer am laufen?
Ja ein Timerinterrupt ist auch vorhanden, der nach bestimmter Zeit
auslöst wenn z.B. ein bestimmter Sensor lange nichts empfängt. Wieso die
Frage?
Julian S. schrieb:>> Hast Du einen Timer am laufen?>Wieso die Frage?
Ich vermute das dies ein Hinweis sein sollte, dass man in einem Timer
das Signal auf dem Pin pollen könnte, und das Program darin mit einer
While-schleife anhalten.
> Ich vermute das dies ein Hinweis sein sollte, dass man in einem Timer> das Signal auf dem Pin pollen könnte, und das Program darin mit einer> While-schleife anhalten.
Kannst du das kurz erklären?
Hast Du es wirklich so eilig?
Kennst Du Dein eigenes Programm?
Welche maximale Zykluszeit hat Deine Hauptschleife?
Reicht daher eine einfache Abfrage pro Durchlauf nicht aus?
Selbst bei schnellen Automaten ist eine Verzögerung, von einem
Hauptschleifendurchlauf, kein Beinbruch.
Hast Du dort aber jede Menge delay's verbraten, so hilft nur eine
Neuprogrammierung bzw. Neustrukturierung.
>Hast Du es wirklich so eilig?
Sehr sogar.
>Kennst Du Dein eigenes Programm?
Ja.
>Welche maximale Zykluszeit hat Deine Hauptschleife?
Genau kann ich das nicht sagen. Es wird ja wie gesagt auf Zustände an
Sensoren gewartet
>Reicht daher eine einfache Abfrage pro Durchlauf nicht aus?>Selbst bei schnellen Automaten ist eine Verzögerung, von einem>Hauptschleifendurchlauf, kein Beinbruch.
Nein, da in while Schleifen "gewartet" wird
>Hast Du dort aber jede Menge delay's verbraten, so hilft nur eine>Neuprogrammierung bzw. Neustrukturierung.
Kein einziges.
@ Julian S. (r4id)
>>Hast Du es wirklich so eilig?>Sehr sogar.
Wie eilig? Siehe Netiquette!!!
>>Kennst Du Dein eigenes Programm?>Ja.
Das sagen sie alle ;-)
>>Welche maximale Zykluszeit hat Deine Hauptschleife?>Genau kann ich das nicht sagen. Es wird ja wie gesagt auf Zustände an>Sensoren gewartet
Eben DAS ist dein Fehler! Siehe Multitasking!
>Nein, da in while Schleifen "gewartet" wird
FALSCH! Das macht man ANDERS! Siehe oben.
@Julian S. (r4id)
>Wäre super Nett wenn mir jemand das mit dem Pin pollen erklären>könnte.......... Bitte! :)
Bitte? Pollen ist neudeutsch (aka englisch) und bedeutet abfragen. Man
fragt also den Pin ab und reagiert entsprechend. Je nach
Programmstruktur kann die Abfrage direkt im Programmfluß stehen oder in
einerm periodischen Timer-Interrupt.
Wie man einen Pin abfragt ist mir bewusst. Aber warum in einem Timer
Interrupt. Interrupt Routinen sollen doch immer Kurz ohne große Abfragen
programmiert werden.
@Julian S. (r4id)
>Wie man einen Pin abfragt ist mir bewusst. Aber warum in einem Timer>Interrupt.
Weil dieser den normalen Programmablauf unterbrechen kann (Nomen est
Omen!)
> Interrupt Routinen sollen doch immer Kurz ohne große Abfragen> programmiert werden.
Am besten läßt man sie komplett leer, oder?
OMG!
Wie lange glaubst du, dauert so eine Pinabfrage?
Es wird in jedem case ein Timerinterrupt ausgelöst.
Bspw. in case 15 ist mein Go/Stop pin gesetzt. also der Ablauf soll
stoppen.
Wie kann ich in der Interruptroutine den Zähler i wieder Null setzten?
Muss ich die Adresse übergeben?
@Julian S. (r4id)
>Wenn ich nun eine Statemachine programmiere wie etwa folgendes.
Sieht nicht sonderlich sinnvoll aus.
>Es wird in jedem case ein Timerinterrupt ausgelöst.
Keine Sekunde. Wie kommst du darauf?
>Bspw. in case 15 ist mein Go/Stop pin gesetzt. also der Ablauf soll>stoppen.
Das funktioniert anders.
>Wie kann ich in der Interruptroutine den Zähler i wieder Null setzten?>Muss ich die Adresse übergeben?
Nö, man muss sie global und volatile definieren, siehe Interrupt.
Aber das mit der Statemachine geht doch ein wenig anders. Lies die
Artikel und denk nach.
Ok ich habe mal eine Statemachine programmiert, dass wie folgt aussieht.
Über eine Jumperstellung wird in der main.cpp die Fkt kurve();
aufgerufen.
Das Problem ist aber das ich das state in der ISR nicht ändern kann.
Die ISR wird auch aufgerufen, habe ich getestet mit einem Rücksetzten
eines Pins.
Das Problem liegt eindeutig an dem typedef enum. Hat einer eine Idee wie
es richtig geschrieben werden muss oder wo und wie ich die Variablen
definieren muss.
Habe schon einiges Probiert. Ich könnte diese Deklaration natürlich in
die Funktionen.h schreiben aber das typedef enum muss in jeder Funktion
die ich in der Switch case der main.cpp aufrufe andere Inhalte haben.
(Die States der Switch case in Funktionen.cpp haben natürlich Inhalte
und schalten auch jeweils um, habe ich nur aus Übersichtlichkeit
entfernt)
main.cpp
1
#define F_CPU 1000000UL
2
#include<avr/io.h>
3
#include<avr/interrupt.h>
4
#include"funktionen.h"
5
6
//Interrupt
7
ISR(TIMER0_OVF_vect)
8
{
9
if((PINC&(1<<PC3)))
10
{
11
state=GRUNDSTELLUNG;
12
}
13
}
14
15
//Hauptprogramm
16
intmain(void)
17
{
18
// Initialisierung der CPU (Timer, JTAG, usw.)
19
init_cpu();
20
//Initialisierung der Ports aufrufen
21
init_io();
22
23
intfkt;
24
// Jumperstellung prüfen
25
fkt=~PINB&(1<<PB0|1<<PB1|1<<PB2);
26
27
//Funktion anhand von Jumperstellung laden
28
switch(fkt)
29
{
30
case0:break;
31
case1:kurve();break;
32
case2:break;
33
case3:break;
34
case4:break;
35
case5:break;
36
case6:break;
37
case7:break;
38
default:break;
39
}
40
41
return0;
42
}
funktionen.cpp
1
#define F_CPU 1000000UL
2
#include<avr/io.h>
3
#include<avr/interrupt.h>
4
#include"funktionen.h"
5
6
7
voidinit_cpu(void)
8
{
9
// JTAG Abschalten
10
MCUCR=(1<<JTD);
11
MCUCR=(1<<JTD);
12
13
// Interrupt einschalten
14
sei();
15
16
// Timer/Counter0 konfigurieren
17
//- Prescaler auf 1/8
18
TCCR0B|=(1<<CS01);
19
//- Interrupt bei Zählerüberlauf aktivieren
20
TIMSK0|=(1<<TOIE0);
21
22
// Timer/Counter1 konfigurieren
23
//- Prescaler auf 1/8
24
TCCR2B|=(1<<CS01);
25
//- Interrupt bei Zählerüberlauf aktivieren
26
TIMSK2|=(1<<TOIE0);
27
28
}
29
30
voidinit_io(void)
31
{
32
//habe ich aus Übersichtlichkeit weggelassen, hier werden aber die Ein und Ausgänge definiert
Julian S. schrieb:> //Interrupt> ISR(TIMER0_OVF_vect)> {> if ( (PINC & (1<<PC3)) )> {> state=GRUNDSTELLUNG;> }> }
Das möchtest du in den meisten Fällen so nicht machen.
Denn: Du weisst nie im vorraus (zumindest nicht im Normalfall), wann
genau der Interrupt zuschlägt.
Wenn der zb hier
1
....
2
3
> switch( state ) // Statemashine switch case Anweisungen
4
> {
5
> case GRUNDSTELLUNG:
6
> mach irgendwas ganz tolles
7
> mach noch was ganz tolles
8
>
9
> und wenn dann auch noch die Temperatur stimmt
10
> dann
11
> state = FREIRAUMEN;
12
> break;
13
>
vor der Zuweisung an state zuschlägt, dann ist dein ganzer
Zustandeswechesel in der ISR für die Katz.
Warum nicht einfach so
1
....
2
intmain()
3
{
4
....
5
6
while(1){
7
8
// hier die Statemaschine
9
switch(state){
10
11
// mit all ihren cases und sonstiger Logik, wie von einem
12
// Zustand zum nächsten gewechselt wird
13
}
14
15
// und hier dann alle Aktionen, die nach der Behandlung eines
16
// state erfolgen sollen. Wie zum Beispiel der Überprüfung von
17
// Rücksetzbedingungen
18
19
if(PINC&(1<<PANIK_TASTE))
20
state=IDLE;
21
}
22
}
Ob man den state dann auf zb IDLE setzt, oder in der Statemaschine einen
Zustand hat, von dem ausgehend die Statemaschine sich wieder selbst in
einen sicheren Zustand manövriert und man sie auf diesen setzt, ist eine
andere Frage und hängt von der konkreten Statemaschine bzw. den
Bedingungen ab. Bei einer Spritzgussmaschine wird es wahrscheinlich
vernünftig sein, wenn sich die Maschine beim Drücken vom Notaus nicht
einfach abschaltet, sondern die Form erst mal (langsamer als normal)
auseinanderfährt, ehe sie dann steht.
Der springende Punkt ist aber: Da in keinem state gewartet wird, wird
damit auch ganz automatisch immer wieder laufend geprüft, ob der Panik
Taster gedrückt wurde und es findet dann auch zwischendrinn immer wieder
die Prüfung statt, ob die Statemaschine in den Grundzustand
zurückgeführt werden soll.
Eine Statemaschine zu haben, bedeutet ja nicht, dass es ausschliesslich
und nur diese eine Statemaschine geben darf. Ein Programm kann
beispielsweise auch 2 oder mehr Statemaschinen implementieren. Die sich
auch gegenseitig beeinflussen können.
>Der springende Punkt ist aber: Da in keinem state gewartet wird, wird>damit auch ganz automatisch immer wieder laufend geprüft, ob der Panik>Taster gedrückt wurde und es findet dann auch zwischendrinn immer wieder>die Prüfung statt, ob die Statemaschine in den Grundzustand>zurückgeführt werden soll.
Also meinst du ich sollte ohne Timer-Interrupt arbeiten, sondern den Pin
jedes mal am ende der Endlosschleife abfragen?
Julian S. schrieb:>>Der springende Punkt ist aber: Da in keinem state gewartet wird, wird>>damit auch ganz automatisch immer wieder laufend geprüft, ob der Panik>>Taster gedrückt wurde und es findet dann auch zwischendrinn immer wieder>>die Prüfung statt, ob die Statemaschine in den Grundzustand>>zurückgeführt werden soll.>> Also meinst du ich sollte ohne Timer-Interrupt arbeiten
Ich weiss nicht, was dein Timer sonst noch macht. Wenn der eine
Systemuhr bereit stellst, die du zb für Wartesachen benutzen kannst,
dann ist er vernünftig.
> sondern den Pin> jedes mal am ende der Endlosschleife abfragen?
Wenn es nur um diesen Pin geht und es um die Fragestellung geht "soll
ich den Pin in jedem einzelnen State jedesmal wieder neu abfragen" dann
kann man sich dafür entscheiden.
Aber wie angesprochen. Welche Version man wählt, hängt auch von den
Gegebenheiten und den persönlichen Vorlieben ab.
Gewöhn dich daran, dass es in der Programmierung kein 'One size fits
all' gibt. Das funktioniert bei Baseballkappen, aber selten in der
Programmierung. Deshalb ist es auch so wichtig, dass man viele Techniken
kennt und die auch kombinieren kann. Und nicht notwendigerweise bei
"externem Signal" gleich "Interrupt" assoziert. Ein Interrupt kann eine
Lösung sein, muss es aber nicht.
Okay. Aber nun möchte ich doch einen Interrupt verwenden. Zwar nicht für
den Pin, sondern soll er wenn 10s nichts passiert das state auf
Grundstellung setzten.
Alleine das state global und volatile zu definieren reicht nicht, da
dieses ja ein typdef enum von state_t ist, welches ja später erst in
einer Fkt definiert wird.
@Julian S. (r4id)
>Über eine Jumperstellung wird in der main.cpp die Fkt kurve();>aufgerufen.
Tu mal nicht so gescheit, das ist stinknormales C. Von C++ weit
entfernt.
>Das Problem ist aber das ich das state in der ISR nicht ändern kann.
Wozu auch. Dort fummelt man nicht rum. Das macht man über andere
Variablen, welche in der Statemachine abgefragt werden. Wobei dann die
ISR aber überflüssig ist, denn die Pinabfrage kann die FSM selber
machen.
>Das Problem liegt eindeutig an dem typedef enum.
Das Problem liegt eindeutig am schlechten Konzpt deinerseits.
>Habe schon einiges Probiert. Ich könnte diese Deklaration natürlich in>die Funktionen.h schreiben aber das typedef enum muss in jeder Funktion>die ich in der Switch case der main.cpp aufrufe andere Inhalte haben.
Kaum. Ein typedef ist immer wie er ist. Er wird einmal in einer .h Datei
definiert und fertig.
> int fkt;> // Jumperstellung prüfen> fkt = ~PINB & (1<<PB0 | 1<<PB1 | 1<<PB2);
Hier fehlt noch eine Maske. Besser so, denn die restlichen Bits sind
sonst undefiniert!
fkt = (~PINB & (1<<PB0 | 1<<PB1 | 1<<PB2)) & 0x07;
>void kurve(void)>{> typedef volatile enum { GRUNDSTELLUNG, FREIRAUMEN, WARTEN} state_t ;> volatile state_t state = GRUNDSTELLUNG;
Lokale Variabeln müssen so gut wie NIE volatile sein. Bestenfalls
GLOBALE Variablen.
Julian S. schrieb:> Okay. Aber nun möchte ich doch einen Interrupt verwenden. Zwar nicht für> den Pin, sondern soll er wenn 10s nichts passiert das state auf> Grundstellung setzten.>> Alleine das state global und volatile zu definieren reicht nicht, da> dieses ja ein typdef enum von state_t ist, welches ja später erst in> einer Fkt definiert wird.
Und wie schon gesagt, willst du sowieso nicht in einem Interrupt den
State ändern. Aus genau den genannten Gründen. Du kannst im Interrupt
ein 'Signal' setzen, dass die 10s um sind und dann darauf reagieren. Oft
kann man das zb so machen
1
volatileuint8_twaitTime;
2
3
....
4
ISR(...)
5
{
6
if(waitTime)
7
waitTime--;
8
}
9
10
11
voidMotor1()
12
{
13
....
14
15
switch(state)
16
{
17
18
caseIDLE:
19
if(TasterPressed){
20
waitTime=10;// Wartezeit von 10 Sekunden
21
// erst danach gehts wirklich los
22
state=WAIT_FOR_BEGIN;
23
}
24
break;
25
26
caseWAIT_FOR_BEGIN:
27
if(WaitTime==0)
28
{
29
Motor1_On(FORWARD);
30
state=WAIT_FOR_ENDPOSITION_FORWARD;
31
}
32
break;
33
34
caseWAIT_FOR_ENDPOSITION_FORWARD:
35
if(Endschalter_Forward)
36
{
37
Motor1_Off();
38
waitTime=2;
39
state=WAIT_FOR_BACKDRIVE;
40
}
41
break;
42
43
caseWAIT_FOR_BACKDRIVE:
44
if(WaitTime==0)
45
{
46
Motor1_On(BACKWARD);
47
state=WAIT_FORENDPOSITION_BACK;
48
}
49
break;
50
51
caseWAIT_FOR_ENDPOSITION_BACK:
52
if(Endschalter_Backward)
53
{
54
Motor1_Off();
55
state=IDLE;
56
}
57
break;
58
}
59
}
Eine Statemaschine, die nach einem Eingangstaster 10 Sekunden wartet,
einen Motor bis zur Endposition fährt, dort abschaltet, 2 Sekunden
wartet und den Motor wieder in die Ausgangsposition zurückfährt. Und
nirgends wird im Programm auf irgendwas aktiv gewartet. Die Funktion
kann aus der Hauptschleife aus laufend aufgerufen werden und arbeitet
sich durch ihre Aufgabe durch. Bei jedem Aufruf wird das gerade
anstehende gemacht. Aber gewartet im Sinne eines _delay_ms, gewartet
wird nicht.
1
intmain()
2
{
3
....
4
5
6
while(1)
7
{
8
machwas;
9
machnochwas;
10
machganzwasanderes;
11
12
Motor1();// behandle den Motor 1
13
14
...
15
}
16
}
Wenn die Statemaschine 'warten' soll, dann hängt sie eben in einem
State, der prüft, ob die 'Eieruhr', die sie sich selbst gestellt hat,
schon abgelaufen ist, oder nicht. Du stellst dir ja auch nicht den
Küchentimer auf 45 Minuten und bleibst dann 45 Minuten ausschliesslich
am Herd stehen.
Zum Rest: ja klar. Das ist in C so. Der Compiler liest dein Programm von
oben nach unten. Und zwar genau 1 mal. Ehe du etwas irgendwo verwenden
kannst, musst du es definieren. Und zwar so, dass es in diesem Scope
auch verfügbar ist.
So wie die C Regeln eben sind.
@ Julian S. (r4id)
>Okay. Aber nun möchte ich doch einen Interrupt verwenden.
Bla. Diese Frage stellt sich gar nicht. SOndern WAS muss getan werden.
DANACH kommt die Frage nach dem WIE, welche ggf. mit einem Interrupt
beantwortet werden kann.
>den Pin, sondern soll er wenn 10s nichts passiert das state auf>Grundstellung setzten.
Eben dafür nimmt man einen Timer. Und zwar nicht mit 10s sondern
eher 10ms. In diesem Zeitraster wird deine FSM aufgerufen. Dort drin
kann man dann ggf. einen Timeout über einen Zähler bis 1000 reinbauen.
Das ist wasserdicht und lehrbuchartig. Und funktioniert.
https://www.mikrocontroller.net/articles/Multitasking#Ein_einfaches_Beispiel_f.C3.BCr_den_AVR
Bischen runterscollen, 3. Beispiel mit Timer.
>Alleine das state global und volatile zu definieren reicht nicht, da>dieses ja ein typdef enum von state_t ist, welches ja später erst in>einer Fkt definiert wird.
Globale Variablen und auch typedefs werden in headern (.h) deklariert
und in einer globalen Datei (globals.-c) definiert. Damit hat jeder
Programmteil Zugriff und Sichtbarkeit.
@ Karl Heinz (kbuchegg) (Moderator)
>oben nach unten. Und zwar genau 1 mal. Ehe du etwas irgendwo verwenden>kannst, musst du es definieren. Und zwar so, dass es in diesem Scope>auch verfügbar ist.>So wie die C Regeln eben sind.
Und das ist gut so. ;-)
Wobei ich immer noch dafür plädiere, ausser im absoluten Notfall, sich
nicht am state einer Statemaschine ausserhalb derselben zu vergreifen.
Hier ist die freiwillige Selbstkontrolle des Programmierers gefragt, der
zwar akzeptiert, dass es technische Notwendigkeiten gibt, diese aber
nicht missbrauchen wird.
Aber du hast ja auch schon in dieses Horn gestossen. Ich will das nur
noch mal herausstreichen, weil ich das für wichtig halte.
@ Karl Heinz (kbuchegg) (Moderator)
>Wobei ich immer noch dafür plädiere, ausser im absoluten Notfall, sich>nicht am state einer Statemaschine ausserhalb derselben zu vergreifen.
Stimmt! Es ging hier nur um die globalen Variablen.
Falk Brunner schrieb:>> int fkt;>> // Jumperstellung prüfen fkt = ~PINB & (1<<PB0 | 1<<PB1 |>> 1<<PB2);>> Hier fehlt noch eine Maske. Besser so, denn die restlichen Bits sind> sonst undefiniert!>> fkt = (~PINB & (1<<PB0 | 1<<PB1 | 1<<PB2)) & 0x07;>>
Warum ist hier etwas Undefiniert?
Beim left-shift werden doch nullen reingeschoben, wodurch 3 int werte
mit einem gesetzten bit entstehen. Nach dem verodern sind diese bits in
einem int wert gesetzt, der rest sind weiterhin nullen, die verundung
dieser bitmaske mit dem int wert, der durch die Invertierung von PINB
entstanden ist, beinhaltet auch nichts undefiniertes...
Ich sehe es einfach nicht...
Ausserdem: Woher willst du wissen, ob PB0, PB1 und PB2 keine werte > 2
hatten? Da könnte man ja sonst gleich die Zahl hinschreiben!
@ Daniel A. (daniel-a)
>> fkt = (~PINB & (1<<PB0 | 1<<PB1 | 1<<PB2)) & 0x07;>Warum ist hier etwas Undefiniert?
Oh, da hab ich wohl den Wald vor lauter Bäumen nicht gesehen 8-)
Erstmal danke für alle Antworten. Habe es nun hinbekommen wie ich es
möchte. :)
@Falk Brunner
>>Über eine Jumperstellung wird in der main.cpp die Fkt kurve();>>aufgerufen.>Tu mal nicht so gescheit, das ist stinknormales C. Von C++ weit>entfernt.
Macht funktionell doch keinen Unterschied. Oder leidet die Performance
beim compiliern von C++?
Mal abgesehen davon, dass ich aus juchs ein C++ Projekt erstellt habe.
;P
Ich weiß das ich die Vorteile von C++ nicht ausnutze und wollte das
sowieso noch in C schreiben.
@ Julian S. (r4id)
>Erstmal danke für alle Antworten. Habe es nun hinbekommen wie ich es>möchte. :)
Wie? Siehe
https://www.mikrocontroller.net/articles/Netiquette#Happy_End>>Tu mal nicht so gescheit, das ist stinknormales C. Von C++ weit>>entfernt.>Macht funktionell doch keinen Unterschied. Oder leidet die Performance>beim compiliern von C++?
Nein.
>Mal abgesehen davon, dass ich aus juchs ein C++ Projekt erstellt habe.>;P>Ich weiß das ich die Vorteile von C++ nicht ausnutze und wollte das>sowieso noch in C schreiben.
Wer noch nicht mal die C und allgemeine Grundlagen solide heherrscht,
sollte nicht von C++ rumtönen.
Oder etwas volkstümlicher formuliert
"Kein Haar am Sack aber nen Kamm in der Tasche!" ;-)
Ich schreibe auch keine Abhandlungen über Quantenmechanik, nur weil ich
nen Laserpointer besitze.
>Wie?
Indem ich bei jeden Durchlauf der FSM am anfang den Pin Prüfe.
So wie Karl Heinz das beschrieben hat. Nach dem Schema...
1
....
2
intmain()
3
{
4
....
5
6
while(1){
7
8
// hier die Statemaschine
9
switch(state){
10
11
// mit all ihren cases und sonstiger Logik, wie von einem
12
// Zustand zum nächsten gewechselt wird
13
}
14
15
// und hier dann alle Aktionen, die nach der Behandlung eines
16
// state erfolgen sollen. Wie zum Beispiel der Überprüfung von
17
// Rücksetzbedingungen
18
19
if(PINC&(1<<PANIK_TASTE))
20
state=IDLE;
21
}
22
}
>Wer noch nicht mal die C und allgemeine Grundlagen solide heherrscht,>sollte nicht von C++ rumtönen.>Oder etwas volkstümlicher formuliert
Ich denke das ich C und auch C++ ganz gut beherrsche, nur ist es schon
ein Unterschied wenn man von reinen theoretischen C-Code der nur im
Command Menu lustig vor sich hinfrimelt hin zu Mikrocontrollern geht.
Zum Beispiel habe ich gelernt niemals globale Variablen anzulegen,
sondern über Adressen und Zeigern auf Adressen usw. zu gehen. Mal
abgesehen von den Endlosschleifen ;).
@Julian S. (r4id)
>Indem ich bei jeden Durchlauf der FSM am anfang den Pin Prüfe.>So wie Karl Heinz das beschrieben hat. Nach dem Schema...
Kann man so machen, ist solide.
>Ich denke das ich C und auch C++ ganz gut beherrsche,
;-)
Der Herr belieben zu scherzen?
Wer nicht mal elementare Regeln zur Deklaration von Variablen und der
Sichtbarkeit kennt, "beherrscht" rein gar nichts. Schon gar nicht C++.
Beitrag "Re: Problem mit Programmunterbrechung"
Der ganze Thread erweckt nicht ein einziges Mal die Vermutung, dass hier
jemand mit soliden Kenntnissen unterwegs ist.
>;-)>Der Herr belieben zu scherzen?>Wer nicht mal elementare Regeln zur Deklaration von Variablen und der>Sichtbarkeit kennt, "beherrscht" rein gar nichts. Schon gar nicht C++.
Die Diskussion ist jetzt eh Quatsch. ;)
Aber:
Variablendeklaration und deren Geltungsbereich sind mir sehr bewusst,
nur meinte ich eben die Tatsache das es üblich ist im µC Bereich mit
globalen Variablen zu arbeiten, was wieder zu "Spagetti-Code" führt und
weg von objektorientierter Programmierung ist.
@Julian S. (r4id)
>nur meinte ich eben die Tatsache das es üblich ist im µC Bereich mit>globalen Variablen zu arbeiten, was wieder zu "Spagetti-Code" führt und>weg von objektorientierter Programmierung ist.
Es ist die pragmatische Version von Sempaphoren etc. Wenn man es
diszipliniert macht, ist das kein "Spagetti-Code". Schließlich sind alle
IO Register auch global.