Ich habe einige Fragen zu Software-Timern und Interrupts auf einem Mikrocontroller. Nur zur Information, ich verwende einen dsPIC33E-Mikrocontroller.
Das Endziel ist die Implementierung eines seriellen Kommunikationsprotokolls: RS485 mit Modbus. Ich habe es geschafft, eine Nachricht zu senden und zu empfangen, und jetzt muss ich einen Teil der Nachrichtenverarbeitung durchführen.
Da ich eine Reihe von Timern für alle möglichen Aufgaben benötige (z. B. 3,5-Zeichen-Verzögerung für die serielle Kommunikation, eine gewisse Verzögerung für das Entprellen von Tasten usw.), plane ich, Timer in einer Software mit einem einzigen Hardware-Timer zu implementieren. Beispielsweise wird die Hardware-Timer-Periode auf 100 us eingestellt, und bei jedem "Überlauf", dh alle 100 us, wird ein Interrupt erzeugt. In der ISR aktualisiere ich nur globale Zähler, die im Grunde Software-Timer mit einer Auflösung von 100 us sind, während die Hardware-Timer-ISR die höchste Priorität hat. Ist dies ein guter Weg, dies zu tun, oder gibt es einen besseren Weg?
Jeder Zähler (dh ein Software-Timer) hat seine eigene Periode definiert, und sobald der Zähler seinen "Periodenwert" erreicht, möchte ich eine Funktion aufrufen. Nun ist es keine sehr gute Idee, diese Funktion innerhalb der Hardware-Timer-ISR aufzurufen, da diese Funktion mit der höchsten Priorität verarbeitet wird, da die aufrufende Routine die Hardware-Timer-ISR ist. Was ich möchte, ist eine Funktion zu definieren, sagen wir:
void Modbus_Protocol(void);
und ihn als Interrupt definieren zu können, der nicht die höchste Priorität hat. Nur der Main-Hardware-Timer hat in diesem Konzept die höchste Priorität. Auf diese Weise würde der Zähler im Hardware-Timer ISR, sobald er seinen Periodenwert erreicht, seine Funktion nicht aufrufen, sondern nur ein Flag setzen, um einen Interrupt auszulösen (z. B. void Modbus_Protocol(void) ), was sein wird ausgelöst, nachdem die Haupt-ISR zurückgekehrt ist, abhängig von ihrer Priorität. Ist so etwas möglich, dh kann ich Software-Interrupts definieren?
Ich weiß, dass es eine Möglichkeit gibt, Hardware-Interrupts zu verwenden, die nicht verwendet werden, und einfach ein Interrupt-Flag innerhalb der Software zu setzen. Aber ich denke nicht, dass dies eine elegante Möglichkeit ist, Interrupts zu implementieren, wenn benutzerdefinierte Software-Interrupts möglich sind.
Sie benötigen keine speziellen "Software-Interrupts". Sehen Sie sich den folgenden Code an. Aus Gründen der Übersichtlichkeit habe ich einige technische Dinge wie die Variablendeklaration vernachlässigt.
Verwenden Sie Ihre ISR, um einfach einen Timer (Tick) zu zählen. In main() warten Sie darauf, mit diesem Timer zu synchronisieren. Verwenden Sie für jede Aufgabe, die Sie bearbeiten müssen, einen eigenen Timer. Alle diese Timer werden bei jedem ISR-Tick inkrementiert.
Wenn der Aufgabenzeitgeber abläuft, wird die dedizierte Aufgabe verarbeitet. Bei dieser Art der Implementierung gibt es einige Besonderheiten. Wenn Sie die EXPITED-Zeit von Ihrem Timer subtrahieren, anstatt sie auf 0 zu setzen, ist Ihre Software robuster, wenn eine der Aufgaben länger als 100 µs dauert. Es ist eine Art Soft-Realtime-Kriterium.
Sie erhalten ein Pseudo-Multitasking-System.
isr() //100µs
{
tick++;
}
main()
{
while(true)
{
while(tick == last_tick);
last_tick = tick;
modbus_timer++;
task1_timer++;
task2_timer++;
if(modbus_timer >= MODEBUS_TIMER_EXPIRED)
{
modbus_timer -= MODEBUS_TIMER_EXPIRED;
Modbus_Protocol();
}
if(task1_timer >= TASK1_TIMER_EXPIRED)
{
task1_timer -= TASK1_TIMER_EXPIRED;
Task1();
}
if(task2_timer >= TASK2_TIMER_EXPIRED)
{
task2_timer -= TASK2_TIMER_EXPIRED;
Task2();
}
}//forever-loop
}// main()
Nach einigem Googeln und Diskutieren wurde mir klar, dass ich versucht habe, priorisierte Aufgaben zu erreichen, was im Grunde ein RTOS (Echtzeitbetriebssystem) ist. Obwohl ein RTOS auf einem Mikrocontroller implementiert werden kann, erfordert es eine enorme Menge an Ressourcen (RAM usw.).
Die andere Möglichkeit besteht darin, einen Planer zu verwenden, wie Batuu erklärt hat. Auf diese Weise können Aufgaben nicht priorisiert werden (es gibt kein Multitasking), und alle Aufgaben sollten innerhalb eines einzigen Ticks abgeschlossen werden.
Nick B
Mark Gulin
Oldtimer
Oldtimer
Mark Gulin