RS 232 Code für Mic rocontroller (GCC C ompiler)

Guido Grohmann schrieb:

Die Hilfe-Funktion ist völlig sinnlos. Besser wäre es, M$ hätte einfach nur einen Satz reingeschrieben: Nicht vorhanden!

- Henry

--
www.ehydra.dyndns.info
Reply to
Henry Kiefer
Loading thread data ...

Ich kann zwischen Vista und XP keinen Fortschritt erkennen. Die Fenster sind nun transparent, was manchmal irritiert und manchmal etwas mehr Übersicht bringt. Alles andere is olle Kamelle.

Ein Anwender - Henry

--
www.ehydra.dyndns.info
Reply to
Henry Kiefer

Jetzt haste ihn gepimpt und nun läuft das Dingens nicht mehr ordentlich. Selbst Schuld!

- Henry

--
www.ehydra.dyndns.info
Reply to
Henry Kiefer

Henry Kiefer schrieb:

ut=20

Hilfe-Funktion? es ging doch um die "Eingabeaufforderung" ... und ich=20 fre=DF 2 Besen, wenn die nicht mittels Eingabe von cmd (so hei=DFt sie se= it=20 NT4) in irgendein Suchfeld zu finden sein soll.

Was in diesem Fall (ui, ich verteidige ein MS-Produkt) unsinnig ist. In=20 die Konsole haben die richtig viel Arbeit reingesteckt, der Win2008=20 Server kann sogar ohne GUI betrieben werden. Oder meintest du, die Hilfe =

sollte besser durhc "Nicht vorhanden" ersetzt werden? DAs warbei XP auch =

schon so - also im Westen nix neues.

Guido

Reply to
Guido Grohmann

Ich finde Vista furchtbar umständlich, wegen jedem Pups wird man zweimal gefragt, ob man das wirklich will, und die gewohnte Struktur der settings (wo ist was) wurde erfolgreich aufgebrochen, man sucht sich einen Wolf. Dazu dann das eigenmächtige Umbiegen von Pfaden für Daten ins User-Verzeichnis, die unsichtbaren Ordner...alles nicht wirklich angenehm.

-ras

--

Ralph A. Schmid

http://www.dk5ras.de/ http://www.db0fue.de/
http://www.bclog.de/
Reply to
Ralph A. Schmid, dk5ras

D.h., Du hast vermutlich die Vista-Installation abgebrochen. Auf vielen Rechnern findet sich als Preload das Installationsabbild, welches dann beim ersten Einschalten Windows installiert.

Bernd

Reply to
Bernd Laengerich

formatting link

Habs nur abgeschätzt: Abtastung auf der Mitte des Bits. Damit nach 10 Bits der Abtastpunkt nicht ins nächste Bit läuft, muss der Absolutfehler je Bit < 1/20 der Bitlänge sein, entsprechend 5%.

Wenn ich nur 3-mal abtaste, habe ich einen zusätzlichen Fehler von bis zu 1/3 Bitlänge. In dem Fall taste ich dann nicht auf der Mitte des Bits ab, sondern im Extremfall bei 1/3 + 1/2 = 5/6 (oder 1/2 - 1/3 = 1/6).

Damit muss der Baudratenfehler nach 10 Bits unter 1/6 Bitlänge bleiben, entsprechend je Bit bei 1/60 oder 1,6666%.

Berücksichtigt man dann noch, dass die Flanken eventuell nicht steil genug sind, wird eng.

Gruß

Stefan DF9BI

Reply to
Stefan Brröring

Ja, genau. Einmal hatte ich für ca. ein halbes Jahr eine Testpartition Vista, das System läuft fast so flott wie XP, wenn der Müll, den die PC-Hersteller beipacken, nicht installiert wird. Die anderen genannten Ärgernisse jedoch blieben bestehen und ließen sich zumindest zum damaligen Zeitpunkt auch nicht einfach abstellen.

-ras

--

Ralph A. Schmid

http://www.dk5ras.de/ http://www.db0fue.de/
http://www.bclog.de/
Reply to
Ralph A. Schmid, dk5ras

Nix. Frueher sprang er nur bei jedem zweiten Startversuch an. Jetzt bei jedem :-)

--
Gruesse, Joerg

http://www.analogconsultants.com/

"gmail" domain blocked because of excessive spam.
Use another domain or send PM.
Reply to
Joerg

Na siehste, dann wäre er im Originalzustand _JETZT_ bei 40° ja gerade nicht angesprungen :-P

Bernd

Reply to
Bernd Laengerich

Nein, er haette etliche vergebliche Startversuche gemacht, waere verrusst und mit viel Pech waere die Transportschnecke festgegangen. Das war so schlimm, dass ich mir fuer die Schnecke extra ein "Freirappelwerkzeug" gemacht hatte. Denn auf die Idee einen Rueckwaertsgang einzubauen sind sie auch nicht gekommen. Manchmal faellt einem beim Anblick solcher "Designs" echt nix mehr ein.

--
Gruesse, Joerg

http://www.analogconsultants.com/

"gmail" domain blocked because of excessive spam.
Use another domain or send PM.
Reply to
Joerg

Joerg schrieb:

Tröste dich. Unser Wärmezähler der Solaranlage zeigt auch schon seit 2 oder 3 Jahren irgendwas mit 29994 kWh an. Ansonsten geht er aber als Steuergerät.

- Henry

--
www.ehydra.dyndns.info
Reply to
Henry Kiefer

Programm

noch

Arrays

Das w=E4re nat=FCrlich eine profunde Erleichterung. Mir ist nur eines nicht klar. Ich kann jetzt verm=F6ge der Angabe der Anzahl in diesem Beispiel 4 gleiche structs (Array von Structs) deklarieren. Aber wie komme ich jetzt in C an eine aus der Anzahl generierte Funktionenschar der numerierten delays. So?:

#if DELAY_ANZAHL > 0 int delay01 (int delay01input); =20 .... #endif

#if DELAY_ANZAHL > 1 int delay02 (int delay02input); =20 .... #endif

#if DELAY_ANZAHL > 2 int delay03 (int delay03input); =20 .... #endif

......

Oder geht das auch k=FCrzer?

Reply to
Paul Rosen

Hab ich gar nicht bedacht.

C mit Klassen ;-) einmal Code und vielfach Daten:

int delayCounter[DELAY_ANZAHL];

int delay(int index, int ticker);

int delay(int index, int ticker){ delayCounter[index] = ticker; }

void interrupt newTick(void){ int d; for (d = 0; d < DELAY_ANZAHL; d++) if(delayCounter[d]) delayCounter[d]--; else printf("Wie reagierst Du auf einen abgelaufenen Ticker?"); printf("und wie hälst Du den an?"); }

Meine Lösung für das Ausgangsthema ohne Delayfunktion:

{ :

mache_1(); // warten bis Lichtschranke triggert WaitOnEvent(LICHTSCHRANKE_A);

mache_2(); // 100ms warten WaitOnTicker(_msTickerNow+100);

mache_3(); // warten auf TAstendruck oder Schlüssel gedreht WaitOnEvent(KEYPAD | SCHLUESSELSCHALTER);

: }

Für Multitasking ist das aber ungeeignet.

Statemaschine der Task2, die alle 100ms was tut:

switch (state){ case INIT: state = WAIT2; /*sonstige Inits*/ continue2 = msTickerNow+1; break; case MACH2: mache_2(); state = WAIT2; continue2 += 100; /* Tickerüberlauf behandeln! */ break; case WAIT2: if(msTickerNow >= continue2); state = MACH2; break; : }

--
Gruß, Raimund
Mein Pfotoalbum 
Mail ohne Anhang an  wird gelesen. Im Impressum der Homepage
findet sich immer eine länger gültige Adresse.
Reply to
Raimund Nisius

Raimund Nisiusschrieb: " [...]

Haben wir hier etwa aneinander vorbei gesprochen? Das hier oben sind keine 3 Task. Es ist nur ein Task und die geschweiften Klammern könnten die Klammern von while(1) sein. Alle WaitOnEvent() geben die Rechenzeit wieder ab an die anderen Task.

Das das ohne einen Scheduler nur aufwendiges Gefummel ist, wird doch hier ganz klar ersichtlich, zumal es ja auch noch getestet werden muss. Wie ich schon schrieb wird der Code dann in eine komplizierte state-machine zerhackt. Das entspricht weder dem realen Ablauf, noch ist es gut und übersichtlich zu lesen (zu warten). Ein Blick ein halbes Jahr später in den Code zwingt unweigerlich dazu, den dicken Ordner mit den Visio-Charts herauszusuchen, weil der Code - wie heist es so schön - nicht mehr so einfach selbsterklärend ist.

Paul hatte ja schon die Möglichkeit einer verketteten Liste angesprochen. Das ist aber genau das, was ein RTOS macht. Jeder Task hat einen Task Control Block (Datenstruktur) in dem auch ein Element enthalten ist, welches den Delay-Wert enthält. Ist das gesetzt, dann ist der entsprechende Task inaktiv und der Scheduler dekrementiert diesen Wert z.B. jede Millisekunde. Wenn er irgendwann 0 ist, dann wird der Task wieder abgearbeitet und die Arbeit nach WaitOnEvent fortgesetzt. Es findet somit kein Bruch im Abfluss statt zwischen Abarbeitung und der Reihenfolge, wie der Code aufgeschrieben ist. Das ist sehr übersichtlich, weil logisch in der Abfolge aufgeschrieben. Alle TCBs sind über eine Liste miteinander verkettet und ein weiteres Beispiel dafür, wie man etwas neu erfindet, was ein RTOS bereits zur Verfügung stellt.

Die Aufgaben auf mehrere Controller zu verteilen, wie Paul auch vorgeschlagen hat, ist übrigens keine wirklich gute Lösung. Man verschiebt dann die Aufgaben (Tasks ?) auf mehrere Controller. Letztendlich müssen die Anforderungen und Ergebnisse untereinander wieder synchronisiert werden. Genau das sind aber elementare Funktionen, die ein RTOS zur Verfügung stellt und wenn man die Tasks auf mehrere Controller verteilt, dann muss man sich wieder selbst etwas aus dem "Kopp drücken", wie dieser Thread hier zeigt, bei dem es um die Synchronisierung mehrer Schnittstellen geht.

Dirk

Reply to
Dirk Ruth

snipped-for-privacy@raimund.in-berlin.de (Raimund Nisius) wrote:

Ich fange mal mit der Beantwortung dieser Fragen an. Dazu muss man erst mal die Frage beantworten, wie man den Ticker startet. Hierzu ben=F6tigt die delayfunktion noch einen Eingangsparameter, der den Startimpuls darstellt. Dieser geht zum Startzeitpunkt von False auf True. Der Returnwert der delay-Funktion ist der zeitverz=F6gerte Ausgang des delays. Beide sind boolean.=20

Um hier in der Abhandlung nun nicht mit Unions hantieren zu m=FCssen, habe ich das Ganze bisher so vereinfacht, dass ich statt booleans einfach "int"s genommen habe, die man auch mit 0 und 1 belegen kann. Um mal darzustellen, wie ein delay Funktionsaufruf am Ende aussehen soll, nehme ich jetzt mal ganz popelige Beispiele, damit unmissverst=E4ndlich ist, was gemeint ist:

EingangKlingel =3D Controller Inputport (T=FCrklingel) AusgangKlingel =3D delay(EingangKlingel, 300) =20

Dieser Aufruf von delay liegt in der Hauptschleife des Programms, damit der Klingelknopf gepollt wird. Wenns klingeln soll, wird also im Programm die Variable EingangKlingel von 0 auf 1 gesetzt. Im Beispiel kommt der Impuls vom Klingeltaster. Infolge davon wird der delayCounter in diesem Moment geladen und AusgangKlingel (der Returnwert der delay Funktion) auf 1 gesetzt, was gleichzeitig eine Indikation daf=FCr ist, dass der delay aktiv ist. Ist die Zeit (hier

300) abgelaufen, geht der Ausgang wieder auf 0 (delay inaktiv). Es h=F6rt auf zu Klingeln. Mithilfe der Ausgangsvariable k=F6nnen dann auch weitere anschlie=DFende Vorg=E4nge ausgel=F6st werden, z.B. bei einer Mehrklangklingel der n=E4chste Ton.=20

Nun k=F6nnen auch mehrere delays parallel, also zur gleichen Zeit ablaufen. Zudem werden sie zu unterschiedlichen Zeiten gestartet (3 externe Taster) und auch zu unterschiedlichen Zeiten gestoppt. Dem Prozessor sind die Startzeitpunkte vorher nicht bekannt, da sie von au=DFen =FCber seine Eing=E4nge kommen k=F6nnen. Das bedeutet aber, dass = eine delayfunktion nicht mehr ausreicht Es m=FCssen also mehrere verschiedene delayfunktionen erzeugt werden, die nat=FCrlich nicht den gleichen Namen haben d=FCrfen und ebensoviele Eingangs- und Ausgangsvriablen. Weil in dem Mehrfamilienhaus auch ein Schwerh=F6riger und ein Tauber wohnen, sieht das Ganze so aus:

AusgangKlingel =3D delayKlingel(EingangKlingel, 300) AusgangHupe =3D delayHupe(EingangHupe, 800) AusgangLampe =3D delayLampe(EingangLampe, 1000)

Um jetzt Dein Konzept mit den Defines anzuwenden, m=FCsste es der Preprozessor schaffen, folgende Zeilen in geeigneter Form umzusetzen, dass sie ins Programm unter irgendeinem index eingef=FCgt werden.=20

Klingel 300 Hupe 800 Lampe 500

#define DELAY_ANZAHL 3

Eine Indexumwandlung k=F6nnte nun so gehen:

#define Klingel [1] #define Hupe [2] #define Lampe [3]

Das l=F6st aber nicht das Problem des Eingangsparameters, des Zeitparameters, und noch m=F6glicher weiterer Zahlenparameter, was aber analog zum Zeitparameter w=E4re.

So ich habe Dein Programm mal erweitert:

int Eingang[DELAY_ANZAHL]; int EingangAlt(DELAY ANZAHL) int Ausgang[DELAY_ANZAHL}; int out[DELAY_ANZAHL]; int delayCounter[DELAY_ANZAHL];

int delay(int index, int ticker);

int delay(int index, int ticker) { if(~EingangAlt[index] && Eingang[index]) //Eingang von 0->1? { delayCounter[index] =3D ticker; =20 ) =20 EingangAlt[index] =3D Eingang[index] //Eingangalt speichert alten Eingangsport //f=FCr n=E4chsten Schleifendurchlauf //Denn Eingangsport kann sich bis dahin =E4ndern=20 =20 //return out[index]; //FEHLER //Ersatzl=F6sung:=20 Ausgang[index] =3D out[index} } Hier liegt ein Problem. Die Funktion ben=F6tigt mehrere R=FCckgabewerte, n=E4mlich f=FCr jeden Timer eine. Legt man alles auf diesen einen Return, so beeinflussen die Eing=E4nge aller drei Delays diesen einen Ausgang. Da wir hier aber =FCber das Problem von zeitgleich laufenden Timern verhandeln, w=FCrden jetzt alle drei diesen einen Ausgang bereinflussen. Mit verschiedenen Indexwerten aufgerufen, wird der Ausgang wild zwischen 0 und 1 hin und hergeworfen.=20

Es geht IMHO einfach nicht ohne eine delay-Funktionenschar von der Anzahl DELAY_ANZAHL. An diesen Funktionen m=FCssen die unten erzeugten out[d] entsprechend dem Index returned werden. Verwendet man allerdings =FCberhaupt keinen Return, sondern void, so k=F6nnen die out[index] Werte direkt in die Ausgangsvariable kopiert werden. Dann muss man den Funktionaufruf im Programm durchf=FChren und die Ausgangsvariable steht dann irgendwo bereit, ohne dass der direkte Bezug sichtbar ist. Es scheint also so, als ob der einzige Weg der Verbesserung =FCber die von mir zuvor vorgeschlagene Funtionsdefinition ginge. Dann m=FCsste man diese Kette bei 100 m=F6glichen delays auch auf

100 erweitern. Das ist schon f=FCr kleine Maschinen nicht un=FCblich. Man kann die Kette nat=FCrlich auch in einer include verschwinden lassen.=20 void interrupt newTick(void) { int d; for (d =3D 0; d < DELAY_ANZAHL; d++) { if(delayCounter[d]) { delayCounter[d]--; out[d] =3D 1; }=09 else out[d] =3D 0; //abgelaufener Ticker } } =20

Genau in diesem Stil habe ich das Problem bisher auch gel=F6st.=20

Ich baue im Moment noch eine bessere L=F6sung. Das Prinzip: Es existiert ein weiteres (Sortier)-Array von der Gr=F6=DFe DELAY_ANZAHL. Sobald ein delay aktiv wird (also der Eingang 1 wird), wird der Tickerwert zum derzeitigen Hardware-Timerstand =FCbertragsfrei (So z=E4hlt auch der Hardware Timer) addiert und stellt damit den Zielwert des Hardwaretimers dar, bei dem der Delay beendet w=E4re. Dieser kommt in das Sortierarray, wo er der Gr=F6=DFe nach einsortiert wird. Um einen = Wert in eine sortierte Liste einzusortieren, ist nur ein einziger Sortierlauf n=F6tig. Gleichzeitig sind in einem Parallelarray die zugeh=F6rigen Indexe der Zielwerte gespeichert, die ebenfalls mitsortiert werden und somit die Zuordnung "Zielwert zu Ursprungsindex" erhalten bleibt. Derjenige Zielwert, der dem Hardware-Timerstand am n=E4chsten ist, steht in dessen Komparatorregister. Wenn der neue Wert n=E4her dran ist, wird er ausgetauscht. Ein Zeiger zeigt im Sortierarray auf den gerade geladenen Wert. Erreicht der Hardware Timer nun den Zielwert, wird ein Interrupt ausgel=F6st und der zugeh=F6rige Ausgang (der Index steht ja im Parallelarray) des delays wird bedient. Dann Sortierarray Index ++ und der n=E4chsth=F6here Wert in den Komparator geladen, sofern es nicht der Gleiche war. Sonst wird auch er bedient und der n=E4chst Werte auf Gleichheit gepr=FCft. Ist er verschieden, wird er in den Komparator geladen. Die Werte der bedienten Ausg=E4nge wird aus dem Array entfernt und die L=FCcke durch Aufr=FCcken geschlossen.=20

=46alls sich dabei etwas anstaut, wird beim =FCberrollen auf die Null der Timer angehalten und ein anderer Interupt ausgel=F6st, der daf=FCr sorgt, dass alle Zielwerte =FCber dem bisher letzten bedienten bis zum Timerh=F6chstwert jetzt sofort bedient werden. Nur f=FCr die Bedienungsphase bleibt er stehen. Dann l=E4uft der Timer wieder los, w=E4hrend dann erst die L=FCcke durch Nachr=FCcken wieder gschlossen = wird. Dies ist notwendig, weil jetzt der Timerwert kleiner ist, als deren Zielwerte, und der Komparator nicht mehr ansprechen w=FCrde. Die kleine Verz=F6gerung ist verschmerzbar, denn von Software Delays kann man eh keine hundertprozentige Genauigkeit verlangen.=20

Vergleicht man die beiden Methoden, so muss die erstere bei JEDEM Timerklick alle Delays hochz=E4hlen und alle Delays pr=FCfen, ob sie fertig sind. Bei der zweiten Methode macht das alles der Hardwaretimer. Die Software hat Pause. Sie muss jeden delay nur zweimal bedienen, n=E4mlich am Anfang und am Ende. Ich w=FCrde mal sagen, das ist D=E4umchendrehen gegen=FCber der ersten. Wenn die zweite Methide also zeitlich in Bedr=E4ngnis ger=E4t, so ist es die erste schon lange. =20

Eventuell gehe ich beim Sortieren auch einen anderen Weg und lege die Zielwertee an die indexrichtige Stelle ins Array und speichere im Parallelarray mit Zeigern die Reihenfolge. Das w=FCrde das Aufr=FCcken beim Einf=FCgen und Entnehmen ersparen. Mal sehen, was effizienter ist.=20

Die Rechenarbeit zum Einsortieren oder Aufr=FCcken ist vergleichbar mit dem Abarbeiten eines Tickers in der obigen alten L=F6sung. Blo=DF jetzt muss sich der Prozessor nur noch dann um die Delays k=FCmmern, wenn ein Delayeingang gesetzt wird oder wenn ein delay abgelaufen ist, denn Letzteres wird durch Interrupt ausgel=F6st. Daf=FCr steigt der Speicherbedarf etwas und es wird eventuell ein zus=E4tzlicher Timer als Vorteiler verbraucht. Das ist aber in vielen F=E4llen verkraftbar. In Standardl=F6sungen verbraucht jeder delay einen Timer, w=E4hrend ich = jetzt mit zweien davon und wenig Rechenlast leicht 100 St=FCck bereitstellen kann.

Reply to
Paul Rosen

Jetzt machst Du mich langsam neugierig. Du hattest in einem fr=FCheren Posting geschrieben:=20

Nat=FCrlich wurde es nicht explizit so beworben. Es war lediglich in einem Vorgespr=E4ch so, dass man mir auf die Frage nach der L=F6sung des Problems der parallelen Timerprozesse stolz geantwortet hatte, dass dies mit einem RTOS gel=F6st worden sei. Fazit: Mich verfolgt die saubere L=F6sung des parallelen Delays schon etwas l=E4nger. Und Du = machst mir hier jetzt den Mund w=E4ssrig, das sei tats=E4chlich mit einem RTOS besser zu l=F6sen.

Allerdings kenne ich ein RTOS zu wenig, um zu begreifen, was Du sagst. Mich w=FCrde jetzt mal brennend interessieren, wie ich bei einem RTOS das Problem mehrerer paralleler Delays l=F6se, das wir hier im Thread gerade besprechen. Um mal das einfachste herauszugreifen - Der Rest ist sicher vollst=E4ndige Induktion - nehmen wir mal nur zwei davon, und zwar ganz simple:

Da ist ein Microcontroller, der an einem Eingangsports einen Taster angeschlossen hat. Wenn ein Taster gedr=FCckt wird, also der Eingang von

0 nach 1 geht, dann wird ein zugeordneter Ausgangspin mit 1 angesteuert und l=E4=DFt beispielsweise eine LED aufleuchten. Sobald eine beliebig vorgegebene Zeit (delay) abgelaufen ist, wird der Ausgang zur=FCckgesetzt und die LED verlischt. Ein anderer Eingangs- und Ausgangspin haben genau die identische Beschaltung und Aufgabe. Die Delays m=FCssen unabh=E4ngig voneinander funktionieren, auch wenn beide Taster fast gleichzeitg gedr=FCckt werden.=20

Ich meine, schon einmal zu wissen, dass man hierf=FCr keine Semaphore braucht. Denn kein Prozess muss auf die Ergebnisse des anderen warten. Lege ich jetzt f=FCr diese beiden Prozesse jeweils ein C Programm an? Dann br=E4uchte ich es nur einmal zu schreiben und zu kopieren: Nenne ich die beiden jetzt beispielsweise Prozess1 und das andere Prozess2? Werfe ich die beiden dann ins RTOS und raus kommt ein ausf=FChrbares Programm, das quasi parallelen Code beinhaltet? Es nimmt mir dabei die Aufgabe ab, selbst die Prozesse im Code zu parallelisieren?

Wie s=E4he der reentrante C-Code f=FCr diese beiden Prozesse aus. Wie konkret gehe ich vor?=20

Das Auslagern gestalte ich nat=FCrlich so, dass sich wenig Schnittstellenverkehr zwischen den Controller ergibt. Vereinfachtes Beispiel: Drei Schrittmotore sind jeweils mit Encodern versehen, um ihre Lage zu pr=FCfen. Sowohl Steuerung der Schrittmotoren mit Beschleunigung am Anfang und Abbremsen am Ende der Bewegung als auch Kontrolle der Encoder ist vom Controller durchzuf=FChren. Der Hauptprozess sagt zum Steuerprozess: Fahre eine Raumkurve nach Formel X ab, beachte dabei die H=F6chstbahngeschwindigkeit Y und sage mir Bescheid, wenn Du fertig bist. Hier haben wir einen ganz d=FCnnen Kommunikationsbedarf f=FCr eine komplexe Aufgabe. Das Problem ist wie geschaffen daf=FCr, bei =DCberlast in einen Slave Controller verschoben = zu werden.

Reply to
Paul Rosen

Paul Rosenschrieb: " [...]

Für dieses einfache Beispiel sind Semaphoren sehr wohl ausgezeichnet geeignet. Ich schreibe hier einfach mal den Code runter. Allen RTOS-Funktionen setze ich ein OS_ vor.

---------------------------------------------------------------------

// Parametrierung #define DELAY_KLINGEL_CLARA 5000 // delay fuer 5000ms #define DELAY_KLINGEL_GERDA 10000 // delay fuer 10000ms #define DELAY_TASTEN_POLLING 20 // delay fuer 20ms #define GetKlingelTasterClara() (~p1.0 & 0x01) // Eingangs-Portpin #define GetKlingelTasterGerda() (~p1.1 & 0x01) // Eingangs-Portpin #define SetKlingelClara(x) p2.0 = (x) // Ausgangs-Portpin #define SetKlingelGerda(x) p2.1 = (x) // Ausgangs-Portpin

// sonstiges #define EIN 1 #define AUS 0

OS_SEMA semaClara; // Semaphore fuer Clara OS_SEMA semaGerda; // Semaphore fuer Gerda

void main void(void) { Controller_Initialisierung()

// Task initialisierung : :

OS_Init(); // startet Scheduler und kehrt nie zurueck OS_Start(); }

void TaskPolling(void) { while(1) { OS_SetSemaphore(&semaClara, GetKlingelTasterClara()); OS_SetSemaphore(&semaGerda, GetKlingelTasterGerda()); OS_Delay(DELAY_TASTEN_POLLING); } }

void TaskKlingelClara(void) { OS_SetSemaphore(&semaClara, 1);

while(1) { OS_PendSemaphore(&semaClara); SetKlingelClara(EIN); OS_Delay(DELAY_KLINGEL_CLARA); SetKlingelClara(AUS); } }

void TaskKlingelGerda(void) { OS_SetSemaphore(&semaGerda, 1);

while(1) { OS_PendSemaphore(&semaGerda); SetKlingelGerda(EIN); OS_Delay(DELAY_KLINGEL_GERDA); SetKlingelGerda(AUS); } }

---------------------------------------------------------------------

TaskPolling: Eine Semaphore ist gesperrt, wenn sie größer als null ist. Hier werden die Taster-Eingangspins eingelesen und die entsprechende Sempahore gesetzt. Ist ein Taster gedrückt, dann wird das Signal über das define invertiert und in die Semaphore geschrieben (BTW es ist einfacher die internen Pull-ups zu verwenden und den Portpin nach GND zu schalten, dann kann man sich auch die Invertierung sparen). Danach geht dieser Task für 20ms schlafen und das Spiel beginnt wieder von vorn.

TaskKlingelClara: Als erstes wird die Semaphore gesperrt, weil sie nach der Initialisierung freigegeben ist und wir nicht beim Start sofort klingeln wollen. Dann geht es in OS_PendSemaphore (pending semaphore), wo geprüft wird ob die Semaphore frei ist. Ist sie gesperrt, dann wird der Task hier schlafen gelegt. Wird der Clara Taster gedrückt, dann wird im TaskPolling die Semaphore freigegeben. In OS_SetSemaphore (wenn mit Parameter 0 aufgerufen) geht das OS durch alle TCBs und prüft, ob ein Task auf genau diese Semaphore wartet. Ist das der Fall, dann wird dieser Task (TaskKlingelClara) auf Redy_to_run gesetzt. OS_PendSemaphore(&semaClara) kehrt dann zurück und schaltet die Klingel ein. Dann wird OS_Delay(DELAY_KLINGEL_CLARA) aufgerufen, was diesen Task wieder schlafen legt und die bereits beschriebene Delay-Variable im TCB dieses Tasks auf DELAY_KLINGEL_CLARA setzt. Der Scheduler selbst wird immer periodisch über einen Timer aufgerufen (1ms) geht durch alle TCBs und dekrementiert vorhandene Delays im TCB. Ist die irgendwann auf null heruntergezählt, dann wird dieser Task wieder auf Redy_to_run gesetzt. Die Klingel geht dann wieder aus und das ganze Spiel beginnt von neuem.

Alle Tasks laufen völlig unabhängig von einander. Du mußt nur eine neues Delay definieren, wenn Du eine neue Zeit brauchst. Der Code ist übersichtlich und folgt linear dem, was der Entwickler im Grunde umsetzen will.

Dirk

Reply to
Dirk Ruth

Das liest sich gut, dürfte aber im Vergleich zum Einsatz von RTOS sehr aufwändig sein.

Du hast ein Anwendung mit 100 Tasks? Blickst Du im selbstgestrickten Scheduler noch durch?

--
Gruß, Raimund
Mein Pfotoalbum 
Mail ohne Anhang an  wird gelesen. Im Impressum der Homepage
findet sich immer eine länger gültige Adresse.
Reply to
Raimund Nisius

Gut möglich. Ich habe den Thread nicht konsequent verfolgt.

Ich habe vorbei gehört.

Die 2 bis 3 Beispiele, an die ich denke habe eine mittelkomplexe Statemaschinenstruktur, weil das gewünschte Verhalten entsprechend strukturiert ist. Von einer while-Schleife gezielt in eine andere zu hüpfen geht ja schlecht.

Das ist eine Frage der Kommentierung und des durchgängigen Konzeptes:

1997 erste Arbeitsversion bis 2000 ca. 3 Updates/Jahr davon jährlich einmal ernsthafte Änderungen in der Funktionalität. 2002 eine letzte winzige Anpassung. 2007 30 Minuten gebraucht, um zu verstehen, wo ich ansetzen muß um ein neues Feature anzuflanschen. Doku? Ja, von Grundzügen der ersten Version. Die hätte jemand anderes nicht in 30 Minuten gelesen und hinreichend verstanden. Ich brauchte sie nur kurz.

Wenn man die von Grund auf neu implementiert sollte man den Arbeitsaufwand gegen den Kauf eines RTOS-Lizenz rechnen.

Seinerzeit hatte ich ein scharfes Auge auf RT-Linux wegen der 640kB DOS-Speicher. Kurz bevor es ernst wurde kam das Aus für das aus den Nähten platzende Projekt. Ist RT-Linux noch im Rennen?

--
Gruß, Raimund
Mein Pfotoalbum 
Mail ohne Anhang an  wird gelesen. Im Impressum der Homepage
findet sich immer eine länger gültige Adresse.
Reply to
Raimund Nisius

ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here. All logos and trade names are the property of their respective owners.