Multitasking auf PIC-Mikrocontrollern


17

Multitasking ist heutzutage wichtig. Ich frage mich, wie wir das mit Mikrocontrollern und eingebetteter Programmierung erreichen können. Ich entwerfe ein System, das auf einem PIC-Mikrocontroller basiert. Ich habe seine Firmware in MplabX IDE unter Verwendung von C entworfen und dann eine Anwendung dafür in Visual Studio unter Verwendung von C # entworfen.

Gibt es eine Möglichkeit, dasselbe in meinem Mikrocontroller-Code zu tun, seit ich mich daran gewöhnt habe, Threads in der C # -Programmierung auf dem Desktop zu verwenden, um parallele Aufgaben zu implementieren? MplabX IDE bietet, pthreads.haber es ist nur ein Stub ohne Implementierung. Ich weiß, dass es FreeRTOS-Unterstützung gibt, aber das macht Ihren Code komplexer. Einige Foren sagen, dass Interrupts auch als Multitasking verwendet werden können, aber ich glaube nicht, dass Interrupts Threads entsprechen.

Ich entwerfe ein System, das einige Daten an einen UART sendet und gleichzeitig Daten über (kabelgebundenes) Ethernet an eine Website senden muss. Ein Benutzer kann die Ausgabe über die Website steuern, die Ausgabe wird jedoch mit einer Verzögerung von 2-3 Sekunden ein- und ausgeschaltet. Das ist also das Problem, vor dem ich stehe. Gibt es eine Lösung für Multitasking in Mikrocontrollern?


Threads können nur auf Prozessoren verwendet werden, auf denen ein Betriebssystem ausgeführt wird, da Threads Teil eines Prozesses sind und Prozesse nur in Betriebssystemen verwendet werden.
TicTacToe

@Zola ja du hast recht. Aber was ist mit Controllern?
Flugzeug

2
Mögliches Duplikat von RTOS für eingebettete Systeme
Roger Rowland

1
Können Sie erklären, warum Sie echtes Multitasking benötigen und Ihre Software auf der Grundlage eines Round-Robin-Task-Ansatzes oder einer select () -Schleife oder ähnlichem nicht sinnvoll implementieren können?
Whatsisname

2
Nun, wie ich bereits sagte, sende und empfange ich Daten an uart und gleichzeitig sende und empfange ich Daten an ethernet. Abgesehen davon muss ich auch Daten auf der SD-Karte zusammen mit der Zeit speichern, also ist ja DS1307 RTC beteiligt und EEPROM ist auch beteiligt. Bis jetzt habe ich nur 1 UART, aber möglicherweise werde ich nach ein paar Tagen Daten von 3 UART-Modulen senden und empfangen. Die Website empfängt auch Daten von 5 verschiedenen Systemen, die an einem entfernten Ort installiert sind. Dies alles muss parallel sein, aber richtig, nicht parallel, sondern mit einer Verzögerung von wenigen Sekunden. !
Flugzeuge

Antworten:


20

Es gibt zwei Haupttypen von Multitasking-Betriebssystemen: präventive und kooperative. Mit beiden können mehrere Aufgaben im System definiert werden. Der Unterschied besteht darin, wie die Aufgabenumschaltung funktioniert. Natürlich läuft mit einem einzigen Core-Prozessor immer nur eine Task gleichzeitig.

Für beide Arten von Multitasking-Betriebssystemen ist für jede Aufgabe ein separater Stack erforderlich. Dies impliziert also zwei Dinge: Erstens, dass der Prozessor das Platzieren von Stacks an einer beliebigen Stelle im RAM zulässt und daher Anweisungen zum Bewegen des Stack-Zeigers (SP) enthält - dh, es gibt keinen speziellen Hardware-Stack wie am unteren Ende PIC's. Dadurch entfallen die PIC10, 12 und 16-Serien.

Sie können ein Betriebssystem fast vollständig in C schreiben, aber der Task-Switcher, in dem sich der SP bewegt, muss sich in der Assembly befinden. Zu verschiedenen Zeiten habe ich Task-Switches für PIC24, PIC32, 8051 und 80x86 geschrieben. Die Eingeweide sind je nach Architektur des Prozessors sehr unterschiedlich.

Die zweite Anforderung besteht darin, dass genügend RAM vorhanden ist, um mehrere Stapel bereitzustellen. Normalerweise möchte man mindestens ein paar hundert Bytes für einen Stapel; Aber selbst bei nur 128 Bytes pro Task benötigen acht Stapel 1 KB RAM - Sie müssen jedoch nicht für jeden Task die gleiche Stapelgröße zuweisen. Denken Sie daran, dass Sie genügend Stack benötigen, um die aktuelle Task und alle Aufrufe der verschachtelten Subroutinen zu verarbeiten, aber auch Speicherplatz für einen Interrupt-Aufruf, da Sie nie wissen, wann einer auftreten wird.

Es gibt ziemlich einfache Methoden, um zu bestimmen, wie viel Stapel Sie für jede Aufgabe verwenden. Sie können beispielsweise alle Stapel auf einen bestimmten Wert initialisieren, z. B. 0x55, und das System für eine Weile ausführen und dann den Speicher stoppen und untersuchen.

Sie sagen nicht, welche Art von PICs Sie verwenden möchten. Die meisten PIC24- und PIC32-Geräte bieten ausreichend Platz für die Ausführung eines Multitasking-Betriebssystems. Der PIC18 (der einzige 8-Bit-PIC mit Stapeln im RAM) hat eine maximale RAM-Größe von 4 KB. Also das ist ziemlich zweifelhaft.

Bei kooperativem Multitasking (das einfachere von beiden) wird die Taskumschaltung nur durchgeführt, wenn die Task ihre Kontrolle an das Betriebssystem "zurückgibt". Dies geschieht immer dann, wenn die Task eine OS-Routine aufrufen muss, um eine Funktion auszuführen, auf die sie warten wird, z. B. eine E / A-Anforderung oder einen Timer-Aufruf. Dies erleichtert dem Betriebssystem das Wechseln von Stapeln, da nicht alle Register und Statusinformationen gespeichert werden müssen. Der SP kann einfach auf eine andere Task umgeschaltet werden (wenn keine anderen Tasks ausgeführt werden können, handelt es sich um einen inaktiven Stack gegebene Kontrolle). Wenn die aktuelle Task keinen OS-Aufruf tätigen muss, aber schon eine Weile ausgeführt wurde, muss sie die Kontrolle freiwillig aufgeben, um das System reaktionsfähig zu halten.

Das Problem mit kooperativem Multitasking besteht darin, dass es das System überlasten kann, wenn die Aufgabe niemals die Kontrolle verliert. Nur es und alle Interrupt-Routinen, die zufällig gesteuert werden, können ausgeführt werden, sodass das Betriebssystem anscheinend abstürzt. Dies ist der "kooperative" Aspekt dieser Systeme. Wenn ein Watchdog-Timer implementiert ist, der nur zurückgesetzt wird, wenn ein Taskwechsel ausgeführt wird, können diese fehlerhaften Tasks abgefangen werden.

Windows 3.1 und frühere Versionen waren kooperative Betriebssysteme, weshalb ihre Leistung teilweise nicht so hoch war.

Präventives Multitasking ist schwieriger zu implementieren. Hier müssen Aufgaben nicht manuell die Steuerung aufgeben, sondern jeder Aufgabe kann eine maximale Ausführungszeit (z. B. 10 ms) zugewiesen werden, und dann wird zur nächsten ausführbaren Aufgabe gewechselt, falls eine vorhanden ist. Dazu muss eine Task willkürlich angehalten, alle Statusinformationen gespeichert und der SP auf eine andere Task umgeschaltet und gestartet werden. Dies macht den Task-Switcher komplizierter, erfordert mehr Stack und verlangsamt das System ein wenig.

Sowohl beim kooperativen als auch beim präemptiven Multitasking können zu jeder Zeit Interrupts auftreten, die die ausgeführte Task vorübergehend präemptieren.

Wie Supercat in einem Kommentar hervorhebt, besteht ein Vorteil von kooperativem Multitasking darin, dass es einfacher ist, Ressourcen gemeinsam zu nutzen (z. B. Hardware wie ein Mehrkanal-ADC oder Software wie das Ändern einer verknüpften Liste). Manchmal möchten zwei Aufgaben gleichzeitig auf dieselbe Ressource zugreifen. Bei der vorbeugenden Zeitplanung könnte das Betriebssystem mithilfe einer Ressource Aufgaben in der Mitte einer Aufgabe wechseln. Daher sind Sperren erforderlich, um zu verhindern, dass eine andere Task hereinkommt und auf dieselbe Ressource zugreift. Bei kooperativem Multitasking ist dies nicht erforderlich, da die Task steuert, wann sie sich selbst an das Betriebssystem zurückgibt.


3
Ein Vorteil von kooperativem Multitasking besteht darin, dass Sperren zum Koordinieren des Zugriffs auf Ressourcen in den meisten Fällen nicht erforderlich sind. Es reicht aus, sicherzustellen, dass die Ressourcen bei Aufgaben immer in einem gemeinsam genutzten Zustand bleiben, wenn sie die Kontrolle abgeben. Präventives Multitasking ist sehr viel komplizierter, wenn eine Aufgabe ausgeschaltet wird, während sie eine Ressource sperrt, die von einer anderen Aufgabe benötigt wird. In einigen Fällen wird die zweite Aufgabe möglicherweise länger blockiert als bei einem kooperativen System, da die Aufgabe, die die Sperre hält, die ...
supercat 07.10.15 um 17:44

1
... volle Ressourcen für den Abschluss der Aktion, für die (auf dem präventiven System) die Sperre erforderlich gewesen wäre, um das geschützte Objekt für die zweite Aufgabe verfügbar zu machen.
Supercat

1
Während kooperative Multitasker Disziplin erfordern, kann es unter kooperativen Multitaskern manchmal einfacher sein, sicherzustellen, dass die Timing-Anforderungen erfüllt werden, als unter präventiven. Da nur sehr wenige Sperren über einen Task-Switch gehalten werden müssen, ist ein Round-Robin-Task-Switch-System mit fünf Tasks erforderlich, bei dem Tasks nicht länger als 10 ms dauern müssen, ohne nachzugeben, kombiniert mit einer kleinen Logik mit der Aufschrift "If task X urgently" muss laufen, führe es als nächstes aus ", stellt sicher, dass Task X nie länger als 10 ms warten muss, wenn es signalisiert, bevor es ausgeführt wird. Im Gegensatz dazu, wenn eine Aufgabe eine Sperre erfordert, welche Aufgabe X ...
Supercat

1
... wird benötigt, wird aber von einem vorbeugenden Switcher ausgeschaltet, bevor es freigegeben wird. X kann möglicherweise erst dann etwas Nützliches tun, wenn der CPU-Scheduler die erste Aufgabe ausführt. Wenn der Scheduler keine Logik zum Erkennen und Behandeln der Prioritätsumkehr enthält, kann es eine Weile dauern, bis der erste Task seine Arbeit beendet und die Sperre aufhebt. Solche Probleme sind nicht unlösbar, aber ihre Lösung erfordert eine Menge Komplexität, die in einem kooperativen System hätte vermieden werden können. Kooperative Systeme funktionieren hervorragend, bis auf einen Punkt: ...
supercat

3
Sie benötigen keine Mehrfachstapel für die Zusammenarbeit, wenn Sie in Fortsetzungen codieren. Im Wesentlichen ist Ihr Code in Funktionen unterteilt. void foo(void* context)Die Controller-Logik (der Kernel) zieht jeweils ein Zeiger- und Funktionszeigerpaar aus der Warteschlange und ruft es einzeln auf. Diese Funktion verwendet den Kontext zum Speichern ihrer Variablen und dergleichen und kann dann hinzufügen, dass der Warteschlange eine Fortsetzung hinzugefügt wird. Diese Funktionen müssen schnell wieder verfügbar sein, damit andere Aufgaben in der CPU ausgeführt werden können. Dies ist eine ereignisbasierte Methode, die nur einen Stapel benötigt.
Ratschenfreak

16

Threading wird von einem Betriebssystem bereitgestellt. In der eingebetteten Welt haben wir normalerweise kein Betriebssystem ("Bare Metal"). Somit bleiben die folgenden Optionen:

  • Der klassische Hauptwahlkreis. Ihre Hauptfunktion hat eine Weile (1), die Aufgabe 1 erledigt und dann Aufgabe 2 ...
  • Hauptschleife + ISR-Flags: Sie haben eine ISR, die die zeitkritische Funktion ausführt und dann die Hauptschleife über eine Flag-Variable benachrichtigt, dass die Task gewartet werden muss. Möglicherweise fügt der ISR ein neues Zeichen in einen Ringspeicher ein und weist die Hauptschleife an, die Daten zu verarbeiten, wenn sie dazu bereit sind.
  • All ISR: Ein Großteil der Logik wird hier vom ISR ausgeführt. Auf einem modernen Controller wie einem ARM mit mehreren Prioritätsstufen. Dies kann ein leistungsfähiges "thread-ähnliches" Schema bereitstellen, kann aber auch verwirrend beim Debuggen sein, sodass es nur für kritische Zeiteinschränkungen reserviert werden sollte.
  • RTOS: Ein RTOS-Kernel (unterstützt durch einen Timer-ISR) kann das Umschalten zwischen mehreren Ausführungsthreads ermöglichen. Sie haben FreeRTOS erwähnt.

Ich rate Ihnen, das einfachste der oben genannten Schemata zu verwenden, das für Ihre Anwendung geeignet ist. Nach dem, was Sie beschreiben, würde ich die Hauptschleife haben, die Pakete erzeugt und sie in kreisförmige Puffer legt. Lassen Sie dann einen UART ISR-basierten Treiber starten, der jedes Mal ausgelöst wird, wenn das vorherige Byte gesendet wurde, bis der Puffer gesendet wurde, und dann auf weiteren Pufferinhalt wartet. Ähnliches gilt für das Ethernet.


3
Dies ist eine sehr nützliche Antwort, da sie die Wurzel des Problems adressiert (Multitasking auf einem kleinen eingebetteten System anstelle von Threads als Lösung). Ein Absatz darüber, wie es auf die ursprüngliche Frage angewendet werden könnte, wäre großartig, vielleicht einschließlich der Vor- und Nachteile der einzelnen Punkte für das Szenario.
David

8

Wie bei jedem Single-Core-Prozessor ist echtes Software-Multitasking nicht möglich. Sie müssen also darauf achten, dass Sie auf eine Weise zwischen mehreren Aufgaben wechseln. Die verschiedenen RTOS kümmern sich darum. Sie verfügen über einen Scheduler und wechseln basierend auf einem System-Tick zwischen verschiedenen Aufgaben, um eine Multitasking-Funktion zu erhalten.

Die damit verbundenen Konzepte (Speichern und Wiederherstellen von Kontexten) sind recht kompliziert. Daher wird das manuelle Ausführen wahrscheinlich schwierig und macht den Code komplexer. Da Sie dies noch nie getan haben, treten darin Fehler auf. Mein Rat hier wäre, ein getestetes RTOS wie FreeRTOS zu verwenden.

Sie haben erwähnt, dass Interrupts eine Multitasking-Ebene bieten. Das ist irgendwie wahr. Der Interrupt unterbricht Ihr aktuelles Programm zu jedem Zeitpunkt und führt den Code dort aus. Dies ist vergleichbar mit einem Zwei-Task-System, bei dem Sie eine Task mit niedriger Priorität und eine andere mit hoher Priorität haben, die innerhalb einer Zeitscheibe des Schedulers endet.

Sie könnten also einen Interrupt-Handler für einen wiederkehrenden Timer schreiben, der ein paar Pakete über den UART sendet, und dann den Rest Ihres Programms für ein paar Millisekunden ausführen und die nächsten Bytes senden. Auf diese Weise erhalten Sie eine begrenzte Multitasking-Fähigkeit. Aber Sie werden auch eine ziemlich lange Unterbrechung haben, was eine schlechte Sache sein könnte.

Die einzige Möglichkeit, mehrere Aufgaben gleichzeitig auf einer Single-Core-MCU auszuführen, besteht darin, den DMA und die Peripheriegeräte zu verwenden, da sie unabhängig vom Core arbeiten (DMA und MCU teilen sich denselben Bus, arbeiten also etwas langsamer, wenn beide sind aktiv). Während der DMA die Bytes zum UART mischt, kann Ihr Core die Daten an das Ethernet senden.


2
danke, DMA hört sich interessant an. Ich werde auf jeden Fall danach suchen.!
Flugzeug

Nicht alle Serien von PICs haben DMA.
Matt Young

1
Ich benutze PIC32;)
Flugzeuge

6

In den anderen Antworten wurden bereits die am häufigsten verwendeten Optionen (Hauptschleife, ISR, RTOS) beschrieben. Hier ist eine weitere Option als Kompromiss: Protothreads . Es ist im Grunde eine sehr leichte Bibliothek für Threads, die die Hauptschleife und einige C-Makros verwendet, um ein RTOS zu "emulieren". Natürlich ist es kein vollständiges Betriebssystem, aber für "einfache" Threads kann es nützlich sein.


Von wo kann ich den Quellcode für Windows herunterladen? Ich denke, es ist nur für Linux verfügbar.!
Flugzeug

@CZAbhinav Es sollte betriebssystemunabhängig sein und Sie können den neuesten Download hier herunterladen .
Erebos

Ich bin gerade in Windows und benutze MplabX. Ich denke nicht, dass es hier nützlich ist. Trotzdem danke.!
Flugzeug

Habe noch nichts über Protothreads gehört, hört sich nach einer interessanten Technik an.
Arsenal

@CZAbhinav Worüber sprichst du? Es ist C-Code und hat nichts mit Ihrem Betriebssystem zu tun.
Matt Young

3

Mein grundlegendes Design für ein RTOS mit minimalen Zeitfenstern hat sich in mehreren Mikrofamilien nicht wesentlich geändert. Es ist im Grunde eine Timer-Unterbrechung, die eine Zustandsmaschine antreibt. Die Interrupt-Serviceroutine ist der Betriebssystemkern, während die switch-Anweisung in der Hauptschleife die Benutzertasks sind. Gerätetreiber sind Interrupt-Serviceroutinen für E / A-Interrupts.

Die Grundstruktur ist wie folgt:

unsigned char tick;

void interrupt HANDLER(void) {
    device_driver_A();
    device_driver_B();
    if(T0IF)
    {
        TMR0 = TICK_1MS;
        T0IF = 0;   // reset timer interrupt
        tick ++;
    }
}

void main(void)
{
    init();

    while (1) {
        // periodic tasks:
        if (tick % 10 == 0) { // roughly every 10 ms
            task_A();
            task_B();    
        }
        if (tick % 55 == 0) { // roughly every 55 ms
            task_C();
            task_D();    
        }

        // tasks that need to run every loop:
        task_E();
        task_F();
    }
}

Dies ist im Grunde ein kooperatives Multitasking-System. Aufgaben sind so geschrieben, dass sie niemals in eine Endlosschleife eintreten. Dies ist uns jedoch egal, da die Aufgaben in einer Ereignisschleife ausgeführt werden und die Endlosschleife daher implizit ist. Dies ist eine ähnliche Art der Programmierung wie bei ereignisorientierten / nicht blockierenden Sprachen wie Javascript oder Go.

Sie können ein Beispiel für diesen Architekturstil in meiner RC-Sendersoftware sehen (ja, ich benutze ihn tatsächlich, um RC-Flugzeuge zu fliegen, daher ist es etwas sicherheitskritisch, um zu verhindern, dass ich meine Flugzeuge abstürze und möglicherweise Menschen töte): https://github.com / slebetman / pic-txmod . Es hat im Grunde 3 Aufgaben - 2 Echtzeitaufgaben, die als Stateful Device-Treiber implementiert sind (siehe ppmio) und 1 Hintergrundaufgabe, die die Mischlogik implementiert. Im Grunde ist es Ihrem Webserver insofern ähnlich, als es 2 E / A-Threads hat.


1
Ich würde das eigentlich nicht als "kooperatives Multitasking" bezeichnen, da es sich nicht wesentlich von anderen Mikrocontroller-Programmen unterscheidet, die mehrere Aufgaben erfüllen müssen.
Whatsisname

2

Ich weiß zwar zu schätzen, dass in der Frage speziell die Verwendung eines eingebetteten RTOS gefragt wird, aber mir fällt die allgemeinere Frage ein, wie Multitasking auf einer eingebetteten Plattform erreicht werden kann.

Ich rate Ihnen dringend, zumindest vorerst die Verwendung eines eingebetteten RTOS zu vergessen. Ich rate dazu, weil ich denke, dass es wichtig ist, zuerst zu lernen, wie man durch extrem einfache Programmiertechniken, die aus einfachen Task-Schedulern und Zustandsautomaten bestehen, eine „Parallelität“ von Aufgaben erreicht.

Um das Konzept extrem kurz zu erklären, hat jedes zu erledigende Arbeitsmodul (dh jede "Aufgabe") eine bestimmte Funktion, die regelmäßig aufgerufen ("angekreuzt") werden muss, damit dieses Modul einige Aufgaben ausführt. Das Modul behält seinen eigenen aktuellen Zustand. Sie haben dann eine Endlosschleife (den Scheduler), die die Modulfunktionen aufruft.

Grobe Darstellung:

for(;;)
{
    main_lcd_ui_tick();
    networking_tick();
}


...

// In your LCD UI module:
void main_lcd_ui_tick(void)
{
    check_for_key_presses();
    update_lcd();
}

...

// In your networking module:
void networking_tick(void)
{
    //'Tick' the TCP/IP library. In this example, I'm periodically
    //calling the main function for Keil's TCP/IP library.
    main_TcpNet();
}

Eine solche Single-Thread-Programmierstruktur, bei der Sie die Funktionen der Hauptzustandsmaschine regelmäßig aus einer Hauptplanungsschleife aufrufen, ist in der eingebetteten Programmierung allgegenwärtig. Aus diesem Grund empfehle ich dem OP nachdrücklich, sich damit vertraut zu machen, bevor Sie direkt mit der Verwendung beginnen RTOS-Tasks / -Threads.

Ich arbeite an einem eingebetteten Gerät mit einer Hardware-LCD-Schnittstelle, einem internen Webserver, einem E-Mail-Client, einem DDNS-Client, VOIP und vielen anderen Funktionen. Obwohl wir ein RTOS (Keil RTX) verwenden, ist die Anzahl der verwendeten einzelnen Threads (Tasks) sehr gering und der größte Teil des "Multitasking" wird wie oben beschrieben erreicht.

Um einige Beispiele für Bibliotheken zu nennen, die dieses Konzept veranschaulichen:

  1. Die Keil-Netzwerkbibliothek. Der gesamte TCP / IP-Stack kann Single-Threaded ausgeführt werden. Sie rufen regelmäßig main_TcpNet () auf, das den TCP / IP-Stack und alle anderen Netzwerkoptionen durchläuft, die Sie aus der Bibliothek (z. B. vom Webserver) kompiliert haben. Siehe http://www.keil.com/support/man/docs/rlarm/rlarm_main_tcpnet.htm . Zugegebenermaßen erreichen Sie in einigen Situationen (möglicherweise außerhalb des Rahmens dieser Antwort) einen Punkt, an dem die Verwendung von Threads nützlich oder erforderlich wird (insbesondere, wenn blockierende BSD-Sockets verwendet werden). (Weitere Anmerkung: Der neue V5-MDK-ARM erzeugt tatsächlich einen dedizierten Ethernet-Thread - aber ich versuche nur, eine Illustration bereitzustellen.)

  2. Die Linphone VOIP-Bibliothek. Die Linphone-Bibliothek selbst ist Single-Threaded. Sie rufen die iterate()Funktion in einem ausreichenden Intervall auf. Siehe http://www.linphone.org/docs/liblinphone-javadoc/org/linphone/core/LinphoneCore.html#iterate () . (Ein schlechtes Beispiel, da ich dies auf einer eingebetteten Linux-Plattform und in den Abhängigkeitsbibliotheken von Linphone verwendet habe, aber es soll einen Punkt verdeutlichen.)

Zurück zu dem vom OP beschriebenen spezifischen Problem scheint das Problem darin zu liegen, dass die UART-Kommunikation zur gleichen Zeit stattfinden muss wie ein Netzwerk (Übertragung von Paketen über TCP / IP). Ich weiß nicht, welche Netzwerkbibliothek Sie tatsächlich verwenden, aber ich würde annehmen, dass sie eine Hauptfunktion hat, die häufig aufgerufen werden muss. Sie müssten Ihren Code schreiben, der sich mit dem Senden / Empfangen von UART-Daten befasst, um auf ähnliche Weise wie eine Zustandsmaschine zu strukturieren, die durch periodische Aufrufe einer Hauptfunktion iteriert werden kann.


2
Vielen Dank für diese nette Erklärung, ich verwende die von microchip bereitgestellte TCP / IP-Bibliothek und es ist ein sehr großer komplexer Code. Ich habe es irgendwie geschafft, es in Teile zu zerlegen und es meinen Anforderungen entsprechend nutzbar zu machen. Ich werde auf jeden Fall einen Ihrer Ansätze ausprobieren.!
Flugzeuge

Viel Spaß :) Die Verwendung eines RTOS macht das Leben in vielen Situationen auf jeden Fall einfacher. Meiner Ansicht nach erleichtert die Verwendung eines Threads (einer Task) den Programmieraufwand in gewisser Hinsicht erheblich, da Sie vermeiden können, Ihre Task in eine Zustandsmaschine aufteilen zu müssen. Stattdessen schreiben Sie Ihren Taskcode einfach so, wie Sie es in Ihren C # -Programmen tun würden. Dabei wird der Taskcode so erstellt, als wäre er das einzige, was vorhanden ist. Es ist wichtig, beide Ansätze zu untersuchen, und wenn Sie mehr Embedded-Programmierung durchführen, bekommen Sie ein Gefühl dafür, welcher Ansatz in jeder Situation am besten ist.
Trevor Seite

Ich bevorzuge auch Threading-Option. :)
Flugzeuge
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.