Forum: Mikrocontroller und Digitale Elektronik I/O-Operationen via Timer-Interrupt - gut oder überflüssig?


von Roth (Gast)


Lesenswert?

Ich bin ja gerade dabei, mein 25J nicht genutztes C wieder auf 
Vordermann zu bringen. und wozu? Um ein Spielzeug wie den Arduino zum 
fliegen zu bringen. Ich mag den Arduino trotzdem :-)

Wegen 25J Nichtstun gelte ich ja wieder als Anfänger. Bevor ich 
programmiere, will ich ein Konzept haben. Ein Konzept, das (später) auch 
größere und komplexe Aufgaben easy+locker bewältigen kann.

Was haltet ihr davon, alle I/O-Operationen im Interrupt abzuarbeiten? 
Jedenfalls das "Grobe", z.B. valide Portabfrage, simutaneous sampling, 
Entprellung, Dämpfung ....

Das Mainprogramm greift dann gar nicht mehr direkt auf die Ports zu, 
sondern nur auf aufbereitete (und damit validen) korrespondierenden 
Speicherstellen (Variablen).

Ich könnte mir vorstellen, dass es ausreicht, z.B. 25 x pro Sek. die 
Eingangsports abzufragen, diese ggf. zu entprellen und dem Hauptprogramm 
als einen validen Wert global zur Verfügung zu stellen.

Damit wären viele Problem gelöst, mit der sich ein Anfänger 
üblicherweise rumplagen muss, wie z.B. ein nicht oder nicht korrekt 
entprellter Schalter/Taster.

Ich habe das früher in MCUs/Embedded gerne realisiert, was eigentlich 
immer nützlich war. So richtig erinnere ich mich leider nicht mehr. 25 
Jahre, viel vergessen ... :(

von Andreas S. (Firma: Schweigstill IT) (schweigstill) Benutzerseite


Lesenswert?

Ja, so etwas ist eine sehr gute Vorgehensweise, die sich in der Tat als 
äußerst robust gegen Störungen erweist. Man sollte nur darauf achten, in 
solch einem Interrupthandler keine großen Verzweigungen des 
Programmablauf oder irgendetwas mit nicht vorhersagbar geringem 
Rechenzeitbedarf einzubauen.

Gerade bei hochauflösenden A/D-Wandler kann man auf diese Art und Weise 
auch sicherstellen, dass deren Leistungsaufnahme auch nicht durch die 
Firmware beeinflusst wird, sondern konstant und reproduzierbar ist. 
Hierdurch kann man thermische Drift reduzieren.

Ich arbeite derzeit an einem FPGA, bei dem insgesamt 110 
A/D-Wandler-Kanäle in Hardware angesteuert und ausgelesen werden. Die 
zugehörige Microblaze-Firmware verarbeitet all die Daten auch in einem 
Timerinterrupt, der mit einstellbarem Zeitversatz synchron zur 
Ausleselogik erzeugt wird. Für die Software im Vordergrund bleibt auch 
nur ein Bruchteil der Gesamtrechenleistung übrig, was aber völlig 
ausreicht.

Auch aus dem Bereich der Telefonanlagen kenne ich genau diese 
Vorgehensweise, d.h. die gesamte Sprachvermittlung, Tonerzeugung und 
-erkennung läuft in einem (ISDN-synchronen) 8kHz-Handler und wird "von 
außen" gesteuert, d.h. teils sogar über selbstmodifizierenden 
Programmcode. Letzteres ist aber nur sinnvoll, wenn man wirklich das 
allerletzte Bisschen an Rechenleistung herausholen muss.

: Bearbeitet durch User
von georg (Gast)


Lesenswert?

Roth schrieb:
> Was haltet ihr davon, alle I/O-Operationen im Interrupt abzuarbeiten?

Für die Entprellung ist das in jedem Fall sinnvoll, ebenso bei der 
Ausgabe von Daten an multiplexte Anzeigen, weil beides sowieso in einem 
festen Zeitraster erfolgen sollte. Ich erledige Tastaturabfrage und 
Anzeige normalerweise in einem 1ms-Timerinterrupt, wobei z.B. die 
Tastenverarbeitung einschliesslich Entprellung nicht in jedem 1ms-Takt 
erfolgen muss, bei ein paar Tasten genügt auch jedes 2. oder 4. Mal, 
ebenso für die Anzeige, das kann man zur besseren Lastverteilung dann 
durch einen zusätzlichen Zähler gegeneinander verschachteln.

Praktisch gibt es für eine 8stellige Anzeige einen 8stelligen Puffer, in 
den schreibt das Hauptprogramm rein was angezeigt werden soll und die 
Timerroutine befördert das auf die Anzeige, umgekehrt erkennt die 
Timerroutine Tastendrücke und speichert sie in einen Eingabepuffer.

Serielle Daten können ebenso behandelt werden, allerdings begrenzt ein 
1ms-Takt die Baudrate auf 9600 Baud. Braucht man es schneller, kann man 
einen kürzeren Zeitttakt wählen oder man benutzt für Seriell-I/O eigene 
Interrupts. Ähnliches gilt für ADC-Daten.

Sehr wichtig: keine Verzögerungen im Interrupt, nur die nackte 
Rechenzeit. D.h. z.B. ist ein Zeichen am seriellen Port angekommen, wird 
es in einen Eingangspuffer gelegt, sonst passiert NICHTS - auf keinen 
Fall wird auf irgendetwas gewartet.

Da die Verarbeitung asynchron erfolgt, muss man sich Gedanken machen 
über konkurrierende Datenzugriffe. Im Interrupt ist das normalerweise 
kein Problem, weil das Hauptprogramm den Interrupt nicht unterbricht, 
aber wenn das Hauptprogramm ein Zeichen von einem Puffer holt und den 
Zeiger eins weiter setzt darf dazwischen kein Interrupt auftreten, z.B. 
schliesst man das mit Enable/Disable Interrupt aus oder durch atomare 
Operationen, wenn es die gibt. Bei Systemen mit mehreren IRQ-Prioritäten 
wird es komplizierter.

Georg

von Roth (Gast)


Lesenswert?

Andreas S. schrieb:
> Timerinterrupt, der mit einstellbarem Zeitversatz synchron zur
> Ausleselogik erzeugt wird.
Das könnte man theoretisch auch in Main unterbringen. Ich habe das mal 
in einem PIC umgesetzt, der keine Timer hatte. Dem Hauptprogramm habe 
ich den "Timer"-Block einfach vorangestellt, und das ganze mit ein paar 
Steuer-Variablen zeitlich synchronisiert. Das lief tatsächlich 
funktionell wie ein echter Timer, und das Mainprogramm konnte völlig auf 
die aufbereiteten und validen I/O-Results des "Timers" zurückgreifen.

Das wichtigste ist, wie du schon geschrieben hast, sich mit den 
Laufzeiten SEHR GUT auseinanderzusetzen. Sonst ist der Crash 
vorprogrammiert. Such mal Fehler in einen Timer-Interrupt ... Für mich 
gilt daher: Code in einem Timer-Interrupt (gilt für alle Interrupts) 
sollte so kurz wie möglich sein. Wenn der Timer neu triggert, während 
ein alter Prozess noch am laufen ist, kann sich jeder vorstellen, was 
dann passiert ;)

von Roth (Gast)


Lesenswert?

georg schrieb:
> Da die Verarbeitung asynchron erfolgt, muss man sich Gedanken machen
> über konkurrierende Datenzugriffe. Im Interrupt ist das normalerweise
> kein Problem, weil das Hauptprogramm den Interrupt nicht unterbricht,
> aber wenn das Hauptprogramm ein Zeichen von einem Puffer holt und den
> Zeiger eins weiter setzt darf dazwischen kein Interrupt auftreten
Das ist völlig richtig. Ich erinnere mich. Eine Z80-Maschine hatte dazu 
eine DI- und EI-Anweisung (Disable/Enable Interrupt) implementiert, die 
im Hauptprogramm den Timer für die Auslesezeit der Variablen temporär 
blocken konnte (etwaige verlorene Interrupts wurden nach EI komplett 
nachgeholt).

von Route_66 H. (route_66)


Lesenswert?

georg schrieb:
> Bei Systemen mit mehreren IRQ-Prioritäten
> wird es komplizierter.

Du meinst mit mehreren INT-Ebenen, d.h. sich gegenseitig unterbrechbare 
Ineterrupts?

Dann wird es nach meiner Erfahrung einfacher!

von W.S. (Gast)


Lesenswert?

Roth schrieb:
> Was haltet ihr davon, alle I/O-Operationen im Interrupt abzuarbeiten?
> Jedenfalls das "Grobe", z.B. valide Portabfrage, simutaneous sampling,
> Entprellung, Dämpfung ....
>
> Das Mainprogramm greift dann gar nicht mehr direkt auf die Ports zu,
> sondern nur auf aufbereitete (und damit validen) korrespondierenden
> Speicherstellen (Variablen).

Ersteres ist eine ausgesprochen dusslige Idee und aus Letzterem könnte 
man etwas Sinnvolles machen.

Also: Portabfragen eben bloß so per Interrupt tun zu wollen, ist blanker 
Unsinn. Interrupts sind dazu da, den gewöhnlichen Lauf der Abarbeitung 
zum Behandeln von zeitlich nicht vorhergesehenen Ereignissen mal eben zu 
unterbrechen - und nicht zum Port-Polling.

Zweitens:
Die Idee, nicht alles durcheinander zu wurschteln, sondern sauber zu 
unterscheiden zwischen den Algorithmen, also den höheren 
Programmstrukturen und den Lowlevel-Ebenen, also den Hardware-Treibern, 
ist sehr vernünftig. Aber sowas in irgendwelche "korrespondierenden 
Speicherstellen" münden zu lassen, ist albern. Was soll daraus werden? 
Sowas geht bestenfalls für die Systemuhr, die im Hintergrund die Uhrzeit 
seit dem Einschalten in Millisekunden zählt, weswegen man eben auf diese 
Uhrzeit als long Variable von überall her LESEND zugreifen kann.

Ich geb dir mal ein paar Beispiele, wie man die Schnittstellen zwischen 
Lowlevel und dem Rest der Firmware gestalten kann:

Unit Motor (eine separate C Quelle, hier nur das, was in die zugehörige 
.h kommt):
bool InitMotor(void);
void MotorEin(void);
void MotorAus(void);

Unit Serial (für UART's und dergleichen)
bool InitSerial(long Baudrate);
bool IsPlatzImSendepuffer(void);
char CharOut(char C);
bool IsCharAvailable(void);
char ReaChar(void);

Unit I2C:
bool InitI2C(void);
bool I2C_OpenSlave(byte Addr, bool toRead);
bool I2C_ByteOut(byte B);
byte I2C_ByteIn(bool GibACK);
void I2C_CloseSlave(void);

und so weiter. Merke: Die Lowlevel-Treiber sollen sich tatsächlich um 
die jeweilige Hardware kümmern und nicht die höheren Schichten mit 
Hardwaredetails belästigen. Ebenso soll in den zugehörigen .h auch nur 
so viel drinstehen, wie "von oben" tatsächlich benötigt wird - und nicht 
jeder lowlevelinterne Krempel. Dabei werden die Treiber sicherlich 
diverse Interrupts benötigen und die entsprechenden Interrupthandler 
beinhalten. Ebenso werden sie öfters auch Datenflüsse zwischenpuffern, 
z.B. bei den seriellen kanälen (UART, USB etc.) Aber das alles soll die 
höheren Schichten nichts angehen und folglich auch nicht aus dem 
jeweiligen Treiber herausgrinsen. Und für simple Portangelegenheiten 
solltest du auch nicht versuchen, sowas zu generalisieren, sondern du 
solltest dir einen treiber für die dahintersteckende AUFGABE schreiben, 
also nicht SetzePort(port,bit) sondern SchalteLampeEin(void) oder 
RelaisAus(void)

W.S.

von Roth (Gast)


Lesenswert?

W.S. schrieb:
> Ersteres ist eine ausgesprochen dusslige Idee und aus Letzterem könnte
> man etwas Sinnvolles machen.
Warum schreibst du so etwas? Deinem Kommi nach zu folgen hast du doch 
Ahnung.

Selbstverständlich werden Timer-Interupts zum zum Port-Polling genutzt. 
Bevorzugt sogar. Wie denn sonst? Zeichen von der Tastatur werden in den 
Puffer geschrieben, wo sie das Programm bzw. die Firmware auf Main-Ebene 
dann auslesen kann. Es gibt noch weitere "999 Beispiele".

von my2ct (Gast)


Lesenswert?

Roth schrieb:
> Ich könnte mir vorstellen, dass es ausreicht, z.B. 25 x pro Sek. die
> Eingangsports abzufragen, diese ggf. zu entprellen und dem Hauptprogramm
> als einen validen Wert global zur Verfügung zu stellen.

Das kommt drauf an, was an deinen Eingangsports für Signale anliegen. 
Wenn das irgendwelche quasistatischen Signale sind, kannst du das 
machen. Aber sobald die Signale ein bisschen dynamischer sind, wird man 
evtl. sogar auf entsprechend schnelle Hardware zurück greifen.

von Dirk B. (Gast)


Lesenswert?

W.S. schrieb:
> Interrupts sind dazu da, den gewöhnlichen Lauf der Abarbeitung
> zum Behandeln von zeitlich nicht vorhergesehenen Ereignissen mal eben zu
> unterbrechen
Sobald ihr im Unterricht auch Timer-Interrupts kennenlernt die aufgrund 
von zeitlich "vorhergesehenen" (Programmierer würden von 
"vordefinierten" schreiben)  Bedingungen den 'gewöhnlichen' Lauf (was 
bei euch auch immer ein 'gewöhnlicher' Lauf im Gegensatz zu 
programmierten Anweisungen bei konventioneller Programmierung sein mag) 
"mal eben unterbrechen", könnt ihr lernen, dass Interrupts nicht nur zum 
'Behandeln' zeitlich nicht vorhergesehenen Ereignisse "da sind".

von Egon D. (Gast)


Lesenswert?

W.S. schrieb:

> Aber sowas in irgendwelche "korrespondierenden
> Speicherstellen" münden zu lassen, ist albern. Was
> soll daraus werden?

Eine SPS.

Nur haben Hobby-Mikrocontroller-Bastler selten Ahnung
davon, wie eine SPS funktioniert -- deswegen gilt dann
dort: "Was der Bauer nicht kennt, das frisst er nicht."

Das die Industrie das millionenfach so macht, interessiert
dann nicht.

von Wolfgang (Gast)


Lesenswert?

W.S. schrieb:
> Interrupts sind dazu da, den gewöhnlichen Lauf der Abarbeitung
> zum Behandeln von zeitlich nicht vorhergesehenen Ereignissen mal eben zu
> unterbrechen.

Wer hat dir den Floh ins Ohr gesetzt? Gerade wenn es auf zeitlich genau 
vorhersehbare Abläufe an kommt, die unabhängig vom aktuellen Status des 
Programms sein müssen, sind Interrupts das Mittel der Wahl - ausgelöst 
durch einen Timer. Etwas vorhersehbareres als den Timertakt gibt es 
eigentlich nicht, wenn man mal von externen Zeitnormalen absieht.

von Egon D. (Gast)


Lesenswert?

Roth schrieb:

> Was haltet ihr davon, alle I/O-Operationen im Interrupt
> abzuarbeiten?

Übertreibung. :)


> Jedenfalls das "Grobe", z.B. valide Portabfrage, simutaneous
> sampling, Entprellung, Dämpfung ....
>
> Das Mainprogramm greift dann gar nicht mehr direkt auf die
> Ports zu, sondern nur auf aufbereitete (und damit validen)
> korrespondierenden Speicherstellen (Variablen).

Das geht aber auch anders als mittels Interrupt. Die SPS
bündelt die Portzugriffe, d.h. sie fertigt erst ein
Speicherabbild der Eingaenge an, fuehrt dann eine Runde
des Hauptprogrammes aus und schreibt dann das Speicher-
abbild der Ausgaenge heraus. Das vereinigt beide Vorteile --
das Hauptprogramm muss sich nicht mehr mit Portzugriffen
herumaergern, aber es koennen auch keine Synchronisations-
probleme auftreten wie bei timergesteuertem Polling.

Deine Idee ist grundsaetzlich nicht schlecht, aber ich
wuerde vielleicht nicht so weit gehen, ALLES I/O im
Interrupt zu machen.
Man kann die Methoden ja flexibel kombinieren.

von Roth (Gast)


Lesenswert?

my2ct schrieb:
> Das kommt drauf an, was an deinen Eingangsports für Signale anliegen.
Natürlich ist es selten sinnvoll, alles über einen Kamm zu scheren. Aber 
darum ging es mir nicht. Ich beabsichtige, wie beschrieben, ein paar 
(nicht alle) Routinen in einen Interrupt zu verlagern. Mit dem Zweck, 
das Hauptprogramm von Trivialitäten (Entprellung, Dämpfung, ...) zu 
entlasten. Wie schön es sich programmieren lässt, wenn der Programimerer 
valide Signale vorliegen hat, weiß nur der, der das schon mal umgesetzt 
hat.

Egon D. schrieb:
> Eine SPS.
Nicht nur bei SPS wird das umgesetzt. Wieviele Tastaturen ahbe ich schon 
gesehen, die keinen Hilfsprozessor im Gehäuse hatten. Hier bleibt nur 
das Polling, weil passive Tastaturen nun mal kein Interrupt-Signal 
liefern können.

Egon D. schrieb:
> Deine Idee ist grundsaetzlich nicht schlecht, aber ich
> wuerde vielleicht nicht so weit gehen, ALLES I/O im
> Interrupt zu machen. Man kann die Methoden ja flexibel kombinieren.
Das beabsichtige ich und ich hoffe in diesem Thema auf Hinweise. Was ihr 
ja auch tut.

Vielen Dank an alle :´-)

von Roth (Gast)


Lesenswert?

my2ct schrieb:
> Das kommt drauf an, was an deinen Eingangsports für Signale anliegen.
> Wenn das irgendwelche quasistatischen Signale sind, kannst du das
> machen. Aber sobald die Signale ein bisschen dynamischer sind, wird man
> evtl. sogar auf entsprechend schnelle Hardware zurück greifen.
Ich habe heute irgendwo die (Assembler)Sourcen einer kompletten Firmware 
verlinkt. Diese Sourcen sind sowas von durchdacht. 40 Jahre alt, aber 
das ist für mich immer noch wie ein Bibel. Und vor allem: unübertroffen 
in der Effizienz. Die Tastatur wurde erst quantitativ über X- und 
Y-Leitungen gecheckt ("Liegt etwas an?") und nur wenn JA, wurde 
qualitativ ausgewertet: der Code der gerückten Taste in ein Puffer 
eingelesen. (Amstrad 8 Bit Z80 System mit 4 MHz).

von Andreas S. (Firma: Schweigstill IT) (schweigstill) Benutzerseite


Lesenswert?

Roth schrieb:
> Andreas S. schrieb:
>> Timerinterrupt, der mit einstellbarem Zeitversatz synchron zur
>> Ausleselogik erzeugt wird.
> Das könnte man theoretisch auch in Main unterbringen. Ich habe das mal
> in einem PIC umgesetzt, der keine Timer hatte. Dem Hauptprogramm habe
> ich den "Timer"-Block einfach vorangestellt, und das ganze mit ein paar
> Steuer-Variablen zeitlich synchronisiert. Das lief tatsächlich
> funktionell wie ein echter Timer, und das Mainprogramm konnte völlig auf
> die aufbereiteten und validen I/O-Results des "Timers" zurückgreifen.

Das funktioniert nur dann einwandfrei, wenn "Langläufer" im 
Hauptprogramm in mehrere kurze Abschnitte zerlegt werden und pro 
Programmdurchlauf nur einer abgearbeitet wird. Es ist aber wesentlich 
schwieriger, hierbei den Worst-Case-Fall zu berechnen oder zumindest 
abzuschätzen. Außerdem muss man viel zu große Reserven für ggf. selten 
auftretende Vorgänge vorhalten.

Ein typischer Fall, in dem so etwas ohnehin nur schlecht funktioniert, 
ist ein eingebauter Webserver, da ein Webbrowser (oder sonstiger 
HTTP-Client) eine fast beliebig hohe Systemlast verursachen kann.

Bei meinem konkreten Projekt werden in dem Interrupthandler natürlich 
auch noch andere streng zeitsynchrone und hochgradig wichtige Dinge 
erledigt, wie z.B. Schwellwertüberschreitungen, die zur Abschaltung von 
Teilen des Systems führen können. So etwas darf auf keinen Fall durch 
einen "DoS-Angriff" über eine der Schnittstellen ausgebremst werden.

> Das wichtigste ist, wie du schon geschrieben hast, sich mit den
> Laufzeiten SEHR GUT auseinanderzusetzen. Sonst ist der Crash
> vorprogrammiert. Such mal Fehler in einen Timer-Interrupt ...

Mit einem externen Statusausgang und einem Oszilloskop oder 
Logianalysator kann man den Rechenleistungsbedarf des Interrupthandlers 
sehr genau bestimmen, insbesondere auch den Jitter, der z.B. auch durch 
das Hauptprogramm oder gar anderen Interrupthandler verursacht wird. In 
einem FPGA kann man auch sehr einfach einen kleinen Profiler 
implementieren, der diese Überwachung durchführt, d.h. einen Timer, der 
beim Interrupt gestartet und durch einen Registerzugriff beim Verlassen 
des Interrupthandlers wieder gestoppt wird. Wird er bis zum nächsten 
Interrupt nicht gestoppt, kann dies ebenfalls protokolliert werden. 
Diese Funktionalität lässt sich sogar in Richtung eines Watchdogs 
ausbauen.

> Für mich
> gilt daher: Code in einem Timer-Interrupt (gilt für alle Interrupts)
> sollte so kurz wie möglich sein.

Er muss nicht so kurz wie möglich sein, sondern zuverlässig innerhalb 
eines Interruptzyklus ausgeführt werden. Je nachdem, wie viel es zu 
rechnen gibt, kann es große Reserven geben oder eben auch nicht.

> Wenn der Timer neu triggert, während
> ein alter Prozess noch am laufen ist, kann sich jeder vorstellen, was
> dann passiert ;)

Nein, dass kann man sich nicht so allgemein vorstellen, da es ganz 
empfindlich von alle möglichen Randbedingungen abhängt.

von X4U (Gast)


Lesenswert?

Roth schrieb:
> Was haltet ihr davon, alle I/O-Operationen im Interrupt abzuarbeiten?
> Jedenfalls das "Grobe", z.B. valide Portabfrage, simutaneous sampling,
> Entprellung, Dämpfung ....

Wenig. Der Interrupt wird stark aufgebläht und die Variablen müssen 
entweder übergeben werden (was die Latenz erhöht) oder global sein (was 
die Sache unübersichtlich und fehleranfällig macht).

Dann sind Portabfragen selten universell. Das eine Signal braucht nur 1x 
pro Sekunde abgefragt werden, der Debouncer alle 20 ms und schnelle 
Signale evtl. sooft wie geht. Bei Ausgängen kommt es dann meist zum 
totalen Overload.

Das beisst sich alles. Da mache in mir lieber ne loop mit nem Zähler 
(z.B. 0-1000ms) der durch den (timer)Interrupt hochgezählt wird und 
führe die Tasks entsprechend aus.

Das macht den Interrupt schlank und ein Überlauf ist leicht und ohne 
Scope und Analyzer zu erkennen (wenn der Zähler > 1000 wird). Zusätzlich 
kann das ganze dann noch auf Units verteilt werden, was ich bei "alles 
im Interrupt" noch nicht hinbekommen habe. Ist das ganze SPS mäßig 
Zyklus gesteuert wird die Restzeit einfach am Ende in einer Loop 
verbraten (und gemessen).

von X4U (Gast)


Lesenswert?

Andreas S. schrieb:
> Ein typischer Fall, in dem so etwas ohnehin nur schlecht funktioniert,
> ist ein eingebauter Webserver, da ein Webbrowser (oder sonstiger
> HTTP-Client) eine fast beliebig hohe Systemlast verursachen kann.

In so einem Fall wäre imo ein RTOS oder Betriebssystem angesagt.

von Harry L. (mysth)


Lesenswert?

W.S. schrieb:
> solltest dir einen treiber für die dahintersteckende AUFGABE schreiben,
> also nicht SetzePort(port,bit) sondern SchalteLampeEin(void) oder
> RelaisAus(void)
>
> W.S.

ich bewunder deine Geduld!

Aber, es ist so, wie c-hater immer schreibt:
"Dazu muß man zuerst Denken lernen!"....

von Wolfgang (Gast)


Lesenswert?

X4U schrieb:
> In so einem Fall wäre imo ein RTOS oder Betriebssystem angesagt.

Ein RTOS oder ein Betriebssystem ist auch "nur" eine Speicher-/Ablauf- 
und Tasksteuerung, der vielleicht irgend jemand mal einen Namen gegeben 
hat und mit programmiererfreundlichen Schnittstellen ausgestattet ist - 
nichts sonst.

von Markus F. (mfro)


Lesenswert?

"I/O-Operationen via Timer-Interrupt - gut oder überflüssig?"

"gut" ist, wenn man genau den Aufwand betreibt, der notwendig ist, um 
ein bestimmtes Problem zu lösen.

"überflüssig" ist, wenn man mehr (oder auch sehr viel mehr) Aufwand als 
notwendig betreibt, um ein bestimmtes Problem zu lösen.

Ergo gibt es - ohne das eigentliche Problem zu kennen, das Du lösen 
willst - keine vernünftige Antwort auf deine Frage.

von m.n. (Gast)


Lesenswert?

Roth schrieb:
> Die Tastatur wurde erst quantitativ über X- und
> Y-Leitungen gecheckt ("Liegt etwas an?") und nur wenn JA, wurde
> qualitativ ausgewertet: der Code der gerückten Taste in ein Puffer
> eingelesen.

Wie Du selber schreibst, ist das ja auch ein alter Hut, der 
geschickterweise schon immer im Timerinterrupt (nebst Entprellung) 
erledigt wurde. Auch die Pufferung von seriellen Daten und Empfang bzw. 
Versand per Interrupt ist doch nichts Spezielles.
Nur für Arduino-Nutzer dürfte das etwas geheimnisvoll Neues darstellen.

Aber niemand käme auf die Idee, Schieberegister per Portpins anzusteuern 
und jedes Togglen per Interrupt auszulösen. Und niemand kommt auf die 
Idee, einen Schrittmotor im 1 - 10 ms Takt per Timerinterrupt drehen zu 
lassen.
Dafür gibt es ja schließlich "delay()" ;-)

Markus F. schrieb:
> Ergo gibt es - ohne das eigentliche Problem zu kennen, das Du lösen
> willst - keine vernünftige Antwort auf deine Frage.

So sieht es aus!

von A. S. (Gast)


Lesenswert?

Interrupts sind vielfach äquivalent zu einem RTOS ohne wait/sleep etc. 
wie Basic Tasks bei Autosar.


Zudem eefirdern zyklusche Interrupts ähnliche strategien wie 
SPS-loop-nodule.

Die Gefahr von RTOS-Tasks und Interrupts bleibt die notwendige 
Synchronisierung wenn zwischen verschiedenen Tasks/Interrupts Daten 
ausgetauscht werden. Jeder embedded Programmierer sollt das nach ein 
paar Jahren kennen (basics), der TO wird dabei offensichtlich auch viel 
Erfahrung sammeln.

Das wirklich einfachste, robusteste und lesbarste ist die SPS-Loop.

Wer sie nicht kennt, wird das bestreiten.

Wer für die Ausnahmen (z.B. einzelne deutlich schnellere IO -prozesse) 
die intertask-probleme und -Lösungen nicht kennt, wird ein 
Vodoo-Programmierer bleiben (mit 4 nops geht's, ist wohl ein Compiler 
Bug)

von Roth (Gast)


Lesenswert?

So weit wollte ich gar nicht in die Tiefe gehen. Es geht um einen 
kleinen µC, mit ein paar Tastern und ADC-Eingängen. Der Timer Interrupt 
sollte dabei u.a. das Entprellen vornehmen und noch ein paar 
Notwendigkeiten, die keine nenneswerte Rechenleistung verlangen. Mehr 
nicht.

Ein kleiner µC mit Interrupts auszustatten oder einen Webserver, 
dazwischen liegen Welten. Die liebsten Interrupts sind mir die, die ich 
in Assembler schreiben kann. Hohe Transparenz über das Geschehen, 
unabhängig von "Optimierungen" etwaiger Parser oder Compiler.

Es ist stets darauf zu achten, was in einen Interrupt gepackt wird. Es 
ist in jedem Einzelfall zu prüfen, ob es Sinn macht und Vorteile für das 
Hauptprogramm bringt, Routinen in eine zeitkritische Umgebung 
auszulagern. Wie viele schon geschrieben haben: Da gibts kein 
grundlegendes Konzept.

Insgesamt war der Ausflug interessant. Vieln Dank für die Beteiligung.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.