Hallo zusammen,
ich habe mich gefragt ob ich nicht die _delay_ms und _delay_us
Funktionen in meinem C-Code nicht ersetzen könnte mit einer IRS. Wie
funktioniert das genau in meinen Anwendungsbeispiel ?
1
#include<avr/io.h>
2
#include<util/delay.h>
3
4
#define taster PB1
5
6
intjj=0;
7
8
intmain(void)
9
{
10
DDRB&=~(1<<taster);
11
DDRD|=0xff;
12
13
while(1)
14
{
15
PORTD=jj;
16
jj++;
17
_delay_ms(200);// ERSETZEN
18
if(PINB&(1<<taster))
19
{
20
_delay_ms(1000);// ERSETZEN
21
if(PINB&(1<<taster))
22
{
23
jj=0;
24
}
25
}
26
}
27
}
ich hatte mir überliegt den Timer 0 zu benutzen um ein spezielles
"delay" selber zu programmieren. Allerdings verstehe ich nicht wie ich
das delay in der if Bedingung ersetzen soll. Er dürfte ja erst eine IRS
auslösen wenn die If Bedingung wahr wäre und somit eine Laufvariable
stacken, aber die IRS wird ja eigentlich immer ausgelöst.
Muss ich etwa sei() und cli() in die Ausführung der If Bedigung setzten?
Aber würde dies nicht auch hohen stromverbrauch bedeuten für den µC.
Daher: mich würde allgemein interessieren wie sowas in der Praxis
gemacht wird.
@ M. S. (ekkie)
>ich habe mich gefragt ob ich nicht die _delay_ms und _delay_us>Funktionen in meinem C-Code nicht ersetzen könnte mit einer IRS.
Kann man, auch wenn es ISR heißt, siehe Interrupt.
> Wie>funktioniert das genau in meinen Anwendungsbeispiel ?
Siehe Multitasking.
M. S. schrieb:> Aber würde dies nicht auch hohen stromverbrauch bedeuten für den µC.
Warum?
Lass deiner Timer regelmäßig einer Interrupt auslösen. In der
Interruptroutine zählst du einen Zähler hoch.
In deinem Hauptprogramm kannst du dir zu Anfang deiner Wartezeit den
Zählerstand holen und machst mit deinem Ablauf erst weiter, wenn sich
der Zählerstand gegenüber dem Anfangswert um die gewünschte
Verzögerungszeit geändert hat.
Das ganze packst du in eine FSM, damit der Prozessor nicht dumm rum
warten muss, sondern nebenbei noch andere Dinge erledigen kann.
Du meinst mit IRS einen Interrupt ? Die Abkürzung ist mir noch nicht
unter gekommen.
Der Witz dabei wäre ja eben, dass die Ausführung Deines Programms nicht
sinnlos in einer Schleife hängt, bis eine gewisse Zeit verstrichen ist.
Ein erster Ansatz wäre also mit einem Timer Zeitdauern bestimmen zu
können. Dann kannst Du dich anderen Dingen widmen und nur immer mal
wieder abfragen, ob es Zeit für eine Tasteraktion ist.
Willst Du die ganze Tasterabfrage in Interrupts verschieben, würde ich 2
Stück nehmen : einer, wenn sich am Tastereingang was ändert; einer wenn
der Timer abgelaufen ist.
Dabei lädt ersterer den Timer und startet ihn. Zweiterer stoppt den
Timer.
Alle Interrupts sperren in der Tasterabfrage ist aber etwas über das
Ziel hinaus geschossen.
Man kann meist auch einzelne Interrupts sperren. Oft funktionieren dann
die Flags, ob ein Interrupt aufgerufen würde trotzdem. Wenn Du nicht
willst, dass so eine olle Kamelle zum Zug kommt, musst Du das Flag
löschen, bevor Du das Enable setzt.
Und dann Feuer frei für den Knoten im Hirn, wann welcher Interrupt in
welcher Reihenfolge wen unterbricht und was dabei verbosselt gehen kann.
M. S. schrieb:> Wie> funktioniert das genau in meinen Anwendungsbeispiel ?
Gar nicht.
Eine Mainloop, die 1,2s warten muß, wir Dir sehr schnell das Genick
brechen. Die kann niemals was sinnvolles tun.
Vermutlich willst Du eine oder mehrere Taste(n) entprellen und das macht
man komplett im Timerinterrupt. Die Mainloop fragt dann nur nur die
Flags ab, die die ISR setzt.
Peter D. schrieb:> Vermutlich willst Du eine oder mehrere Taste(n) entprellen und das macht> man komplett im Timerinterrupt. Die Mainloop fragt dann nur nur die> Flags ab, die die ISR setzt.
Sorry Peda, dies wird von einem Anfänger nicht verstanden.
Nicht von jemanden der einen Code wie der TO produziert.
Auch sind ihm die Prinzipien der Interrupt-Programmierung
überhaupt nicht geläufig, jedenfalls wird das nichts wenn man
es so erklärt wie hier in diesem Thread.
Bei mir etabliert sich allmählich die Regel: die grössten
Koryphäen sind die miesesten Didaktiker. Einfühlungsvermögen
für Anfänger: null.
(wobei ich dich noch nicht zu den Koryphäen zählen möchte)
M. S. schrieb:> Daher: mich würde allgemein interessieren wie sowas in der Praxis> gemacht wird.
Leider verstehe ich nicht genau, was dein Programm tun soll....
Darum zeige ich dir ein Programm, welches bei jedem Tastendruck hoch
zählt, und das Ergebnis an PORTD ausgibt.
Für die Zeiten wird Timer0 verwendet. Ist Arduino Standard.
Auch wenn es dir nicht unmittelbar weiter hilft, zeigt es doch, dass es
"Alternative Wahrheiten" gibt.
Themaverfehlung schrieb:> (wobei ich dich noch nicht zu den Koryphäen zählen möchte)
Bedenke:
Es gibt Themaverfehler, welche nur blähen, und nichts sachliches
beitragen.
Bei denen der Name auch das Programm ist.
Nur auf Krawall aus sind.
Themaverfehlung schrieb:> Sorry Peda, dies wird von einem Anfänger nicht verstanden.
Also lieber voll ins Messer laufen lassen und auf die harte Tour lernen
zu lassen, wie man es nicht macht?
Wenn man schonungslos die Wahrheit sagt, wird das zumindest zum
Nachdenken anregen und viel Zeit und Enttäuschung sparen.
Arduino Fanboy D. schrieb:> Leider verstehe ich nicht genau, was dein Programm tun soll....> #include <CombiePin.h>> #include <CombieTimer.h>> #include <CombieTools.h>
Geht mir mit Deinem Beispiel auch so.
Wo findet man diese Libs und das Manual dazu?
Peter D. schrieb:> Wo findet man diese Libs und das Manual dazu?
Die Libs kann ich dir liefern.
Findet sich auch hier im Forum schon ein paar mal.
Ein Manual nicht wirklich, aber sind reichlich Beispiele bei.
Ist noch nicht ganz fertig/aufgeräumt, aber was da ist, funktioniert.
Arduino Fanboy D. schrieb:> Die Libs kann ich dir liefern.
Es wäre wünschenswert, wenn man Beispiele gleich so postet, daß sie auch
compilierbar sind.
Zumindest sollte man dazu schreiben, daß es keine Standard-Libs sind
oder sie in "" einfassen, statt in <>.
Ich bin ja nicht so der C++ Crack, um sowas sofort zu erkennen.
Das hab ich hier schon öfter erlebt, daß man unter C++ gerne Code mit
privaten Libs postet, um den Leser dumm aussehen zu lassen.
fop schrieb:> Du meinst mit IRS einen Interrupt ? Die Abkürzung ist mir noch nicht> unter gekommen.
er meinte ISR, InterruptServiceRoutine, alte Bezeichnung heute wird das
ja IRQ genannt InterruptReQuest
komisch ich wusste sofort was gemeint war
https://www.wort-suchen.de/wortwissen/wortkognition-macht-buchstabendreher-lesbar/1675031M. S. schrieb:> _delay_ms(200); // 1*. Uhrzeit notieren> if( PINB & (1<<taster) ) // 1*.> {> _delay_ms(1000); // 2*. Uhrzeit notieren> if( PINB & (1<<taster) )> {> jj=0;> }> }> [/c]>> ich hatte mir überliegt den Timer 0 zu benutzen um ein spezielles> "delay" selber zu programmieren. Allerdings verstehe ich nicht wie ich> das delay in der if Bedingung ersetzen soll.> Daher: mich würde allgemein interessieren wie sowas in der Praxis> gemacht wird.
1*. Uhrzeit notieren weiterarbeiten, dabei immer mal wieder auf die Uhr
schauen wenn 200 um sind, deswegen der Notizzettel (Variable1), den
Taster befragen, evtl. Unterprogramm anspringen.
2*. Uhrzeit notieren weiterarbeiten, dabei immer mal wieder auf die Uhr
schauen wenn 200 um sind, deswegen der Notizzettel (Variable2 oder 1
wenn die wieder frei ist), den Taster befragen, evtl. Unterprogramm
anspringen.
dann jj hochzählen.
3. fertig, Notizzettel entsorgen.
wie im echten Leben
es klingelt an der Tür
du guckst auf die Uhr, notierst die Zeit und machst weiter was anderes,
nebenbei guckst du auf die Uhr und wenn du genug gewartet hast gehst du
zur Tür.
Joachim B. schrieb:> wie im echten Leben> es klingelt an der Tür> du guckst auf die Uhr, notierst die Zeit und machst weiter was anderes,> nebenbei guckst du auf die Uhr und wenn du genug gewartet hast gehst du> zur Tür.
Und du machst das im echten Leben wirklich so ?
willste wieder stänkern?
ich lasse nicht den Hammer fallen wenns klingelt, kann durchaus
abschätzen wann es Zeit ist zu gehen und vorher den Hammer ablegen,
Brain 1.0 merkt sich noch wann es Zeit ist.
So ein doofer Compi muss die Zeit notieren damit er wunschgemäß 200ms
(1000ms) seinen Dienst an der gewünschten Stelle aufnimmt.
Alternativ könnte der Compi einen Timerinterrupt starten für 200ms.
hast du persönlich Probleme mit Analogien oder mit mir?
Peter D. schrieb:> Arduino Fanboy D. schrieb:>> Die Libs kann ich dir liefern.>> Es wäre wünschenswert, wenn man Beispiele gleich so postet, daß sie auch> compilierbar sind.> Zumindest sollte man dazu schreiben, daß es keine Standard-Libs sind> oder sie in "" einfassen, statt in <>.> Ich bin ja nicht so der C++ Crack, um sowas sofort zu erkennen.> Das hab ich hier schon öfter erlebt, daß man unter C++ gerne Code mit> privaten Libs postet, um den Leser dumm aussehen zu lassen.
Offensichtlich scheinen auch dich die Libs nicht so zu interessieren...
Bis jetzt null Downloads.
In etwa so wie ich es erwartet habe.
Zusätzlich:
Mir anzulasten, wenn andere dich dumm aussehen lassen wollen, ist
mindestens ungerecht.
Marc V. schrieb:> Und du machst das im echten Leben wirklich so ?
Auf meinen Arduinos, ein ganz klares JA!
Ganz klar: JA!
Das ist die billigste Variante von kooperativem Multitasking auf AVRs.
Hat jedenfalls einen gewissen Anspruch, die Diskussion. Gefällt mir
fast.
--
Zurück zum fachlichen (Ja - hier lesen noch mehr mit)
Womit ich persönlich nun garnicht klarkomme, sind solche Dinge:
Äxl (geloescht) schrieb:> Womit ich persönlich nun garnicht klarkomme, sind solche Dinge:
Ich nenne das für mich die "Daten-Fluss-Schreibweise"
Die Information fließt von rechts nach links.
Angelehnt an die typischen Datenflussdiagramme.
Marc V. schrieb:> Und du machst das im echten Leben wirklich so ?
Ich kenne das eigentlich auch nicht so, das ich erst mal "bis 20 zähle"
(neutraler gesagt: erst mal bewust eine gewisse Zeit verstreichen lasse)
bevor ich zur Klingel gehe (als "beklingelter"). Und als "klingelnder"
hätte ich bisher nicht angenommen, das da jemand hinter der Türe erst
mal "bis 20 zählt", bevor derjenige sich zur Türe bewegt.
Bei mir hat ein Klinkel-Interrupt immer eine recht hohe Priorität.
Joachim B. schrieb:> willste wieder stänkern?> ...> hast du persönlich Probleme mit Analogien oder mit mir?
hm, und warum willst du hier gleich das Klima aufheizen? Ist doch gar
nicht nötig. Es war eine ruhige, sachliche Frage. Du schaffst es
bestimmt, darauf auch ruhig und sachlich zu antworten.
Ich hatte mal einen Artikel über Multitasking auf Mikrocontrollern
geschrieben. Die obere Hälfte davon wäre hier relevant:
http://stefanfrings.de/net_io/protosockets.html
Wenn man das verstanden hat, müsste eigentlich offensichtlich sein, wie
man delays() ersetzt. Ein Beispiel:
Joachim B. schrieb:> Alternativ könnte der Compi einen Timerinterrupt starten für 200ms.
Meist nach der dritten Task, die so mit den Resourcen umgeht, kommt dann
"das geht nicht, ich habe keinen Timer mehr frei".
Nicht ohne Grund generiert man einen Zeittakt, den dann alle nutzen
können.
Wolfgang schrieb:> Joachim B. schrieb:>> Alternativ könnte der Compi einen Timerinterrupt starten für 200ms.>> Meist nach der dritten Task, die so mit den Resourcen umgeht, kommt dann> "das geht nicht, ich habe keinen Timer mehr frei".
der TO ist Anfänger, verschieben wir das doch auf spätere Zeitpunkte bis
der TO programmiertechnisch weiter ist.
Klar nimmt man für sowas und mehrere Task periodische Timer, PeDa hat
dafür hier was geschrieben
kooperatives Multitasking.
Wir reden aber schon immernoch von den "kleinen" 8-Bit AVR's? bekommen
die dabei nicht "dicke Backen" bei diesem OOP-'Zeuchs'(sry)? würde ich
ja im Leben nicht drauf kommen, das "sowas" auch nur ansatzweise laufen
würde.
Ihc habe früher(tm) Visual Components für Delphi geschrieben, weil ich
mich damit am PC gern und oft beschäftigt hatte.
Das jetzt auf nen kleinen AVR zu portieren, macht ja Spaß und scheint
tatsächlich zu funktionieren. Also vom Grunwissen über Vererbbarkeit usw
mal plattformübegreifend aufgefasst. Delphi ist Pascal und C++ ist C++,
schon klar.
--
(hört mal auf, euch da anzugiften - menno. Tauscht eure PLZ aus und geht
was trinken! [14478, Cuba-Libre nehm ich])
73, DG1RTO
Äxl (geloescht) schrieb:> Wir reden aber schon immernoch von den "kleinen" 8-Bit AVR's? bekommen> die dabei nicht "dicke Backen" bei diesem OOP-'Zeuchs'(sry)?> Ich habe früher(tm) Visual Components für Delphi geschrieben
Kann es sein, dass du im falschen Thread gelandet bist?
Äxl (geloescht) schrieb:> Wir reden aber schon immernoch von den "kleinen" 8-Bit AVR's? bekommen> die dabei nicht "dicke Backen" bei diesem OOP-'Zeuchs'(sry)? würde ich> ja im Leben nicht drauf kommen, das "sowas" auch nur ansatzweise laufen> würde.
Nöö...
Eigentlich nicht.... also: Keine dicken Backen
Sicherlich kann man Mist bauen!
In C++ sogar recht viel Mist.
Und dann gibts auch u.U. die dicken Backen.
Aber im Grunde, gerade bei den IO Klassen habe ich mir Mühe gegeben,
dass sie so effizient sind, wie man das auch in Assembler kaum besser
hin bekommt.
1
#include<CombiePin.h>
2
3
Combie::Pin::OutputPin<LED_BUILTIN>led;
4
5
voidmain()
6
{
7
led.init();
8
for(;;)led.toggle();
9
}
Die Anwendung nimmt 6 Byte im Code (gegenüber einem leeren Rumpf)
0 Byte Ram
Effizienter kann man das in keiner Sprache hinbekommen.
Marc V. schrieb:> Joachim B. schrieb:>> wie im echten Leben>> es klingelt an der Tür>> du guckst auf die Uhr, notierst die Zeit und machst weiter was anderes,>> nebenbei guckst du auf die Uhr und wenn du genug gewartet hast gehst du>> zur Tür.>> Und du machst das im echten Leben wirklich so ?Joachim B. schrieb:> willste wieder stänkern?
Wie kommst du darauf, es war eine ganz normale Frage ?
Wer schreibt sich die Zeit auf wenn es klingelt, macht etwas anderes
... und geht erst dann zur Tür ?
> hast du persönlich Probleme mit Analogien oder mit mir?
Weder noch, aber du scheinst Probleme sowohl mit Analogien als auch
mit mir zu haben.
Wegstaben V. schrieb:> hm, und warum willst du hier gleich das Klima aufheizen? Ist doch gar> nicht nötig. Es war eine ruhige, sachliche Frage. Du schaffst es> bestimmt, darauf auch ruhig und sachlich zu antworten.
ich fand diese Frage provokativ, ist sie das nicht?
Marc V. schrieb:> Und du machst das im echten Leben wirklich so ?
aber nun gut,
natürlich mache ich das nicht, ich kann klingeln ignorieren und zur
gegebener Zeit reagieren, einem Compi muss man erklären wann er was zu
machen hat.
Die Schwierigkeit die viele beim Programmieren haben ist ja das sie
Dinge nicht fein aufschlüsseln kann.
Joachim B. schrieb:> er meinte ISR, InterruptServiceRoutine, alte Bezeichnung heute wird das> ja IRQ genannt InterruptReQuest
Jetzt wird es ganz konfus.
Interrupt Service Routine ist, wie die Bezeichnung schon sagt, die
Routine, die ausgeführt wird, nachdem ein Interrupt Request, also die
Anforderung einer Unterbrechung, oft kurz als Interrupt bezeichnet,
stattgefunden hat.
Wolfgang schrieb:> Jetzt wird es ganz konfus.
wieso?
der TO schrieb doch er meinte
M. S. schrieb:> *ISR
IRS war (s)ein Tippfehler und ob nun ISR oder IRQ richtiger ist
was stört dich und wo behindert es die Frage vom TO zu beantworten?
Joachim B. schrieb:> und ob nun ISR oder IRQ richtiger ist
Das ist ein himmelweiter Bedeutungsunterschied. Eine ISR ist eine Stück
Code. Ein IRQ ist ein spezieller Zustand eines Stücks Hardware.
Wer nicht einmal begreift, wie relevant solche Bedeutungsunterschiede in
der Sprache sind, sollte die Sprache schlicht nicht benutzen. Oder
kürzer ausgedrückt: shut up.
an c-hater:
> Bedeutungsunterschiede in der Sprache
Eigentlich geht es mich nichts an, aber:
Ihr erster Absatz war gut, richtig und wichtig für das Thema.
Mit dem zweiten Absatz allerdings verbauen Sie ihm die Chance, den
Irrtum einfach zuzugeben und damit die Angelegenheit in Ehren
beizulegen.
S. Landolt schrieb:> Mit dem zweiten Absatz allerdings verbauen Sie ihm die Chance, den> Irrtum einfach zuzugeben und damit die Angelegenheit in Ehren> beizulegen.
Nicht wirklich. Er braucht sich doch von mir nicht den Mund verbieten zu
lassen. Ich lasse mir doch von den vielen Hirnies hier auch nicht
einfach den Mund verbieten. (Obwohl sie es, sogar mit Zensorenhilfe,
immer wieder versuchen).
Nach solcher Schmähkritik hätte er nur die Möglichkeit, 'zu Kreuze zu
kriechen' - wer tut sich sowas freiwillig an, also schweigt er lieber
(vermutlich grollend).
Wie gesagt, eigentlich geht's mich nichts an, aber als Forumsmitglied
deprimieren mich diese ständigen Kleinkriege hier.
Es ist nicht zu verstehen, warum die Moderation Soziopathen*1 wie
c-hater herumtoben lässt. Allerdings können auch die normalen User
etwas tun, indem sie solche Leute konsequent ignorieren und ausgrenzen.
[1]
https://de.wikipedia.org/wiki/Soziopath
Bernie schrieb:> Es ist nicht zu verstehen, warum die Moderation Soziopathen*1 wie> c-hater herumtoben lässt. Allerdings können auch die normalen User> etwas tun, indem sie solche Leute konsequent ignorieren und ausgrenzen.>> [1]> https://de.wikipedia.org/wiki/Soziopath
Befolge bitte deinen eigenen Vorschlag.
Oder bist du kein normaler User.
(und nein, das ist keine Frage)
(vielleicht liest der Thread Starter ja noch mit)
Ich bastel schon länger mit dem Arduino Uno rum und versuche gerade mich
in die C und Assembler Programmierung der ATmegas einzuarbeiten. Dabei
nehme ich die "Hacks" aus dem Arduino Buch (3. Aufl.) von Bartmann als
Vorlage und beschäftige mich gerade zufälligerweise mit dem
angesprochenen Thema.
Hack 4.3: LED2 blinkt vor sich hin, per Taster soll eine weitere LED1
(sofort) ein/ausschaltbar sein.
Arduino delay bzw C _delay_ms geht nicht, weil blockierend.
Also wird die Arduino millis Funktion zum Erfassen der Millisekunden
seit Start und Berechnung von Zeitintervallen verwendet. Die
Implementierung von millis kann man in Netz finden. Ich habe mir eine
vereinfachte Variante geschrieben.
Im Hintergrund zählt der 8-Bit Timer/Counter0.
fsys = 16MHz, Prescaler 64 -> 1,024 ms bis Overflow (TCNT0 = 255).
Um den Zyklus auf 1,000 ms zu bringen soll der Tiomer0 im CTC Modus
arbeiten mit Überlauf bei TCNT0 = 250 (Eingestellt mit OCR0A)
Bei jedem Compare Match wird ein Interrupt ausgelöst und der
Millisekunden-Zähler inkrementiert.
Hier der Code:
1
// *** nonblockingdelaydemo.c ***
2
3
// Taster mit Pulldown Widersand (aktive low) an Pin PB0 (Arduino D8)
4
// LED 1 (gelb) mit Vorwiderstand an Pin PC5 (Arduino A5)
5
// LED 2 (rot) " Pin PC0 (Arduino A0)
6
// LEDs Current Source angeschlossen
7
8
9
#include<avr/io.h>
10
#include<avr/interrupt.h> // sei(), cli(), ...
11
12
13
volatileunsignedlongtimer0_millis=0;// Zeit in ms seit Reset
14
unsignedlongtime_prev;
15
inttime_interval=1500;// LED Blink-Periode 3 s
16
17
18
unsignedlongmillis()
19
{
20
// The function millis () returns an unsigned long, which is the number of milliseconds
21
// since the processor was reset (until it overflows nach 49 Tagen)
22
23
unsignedlongm;
24
uint8_toldSREG=SREG;
25
26
// disable interrupts while we read timer0_millis or we might get an
27
// inconsistent value (e.g. in the middle of a write to timer0_millis)
> und versuche gerade mich in die C und> Assembler Programmierung der ATmegas einzuarbeiten.
Das ist an sich eine gute Idee...
Bedenke aber, dass Arduino C++ ist, und kein C.
Volker A. schrieb:> Arduino delay ... geht nicht, weil blockierend.
Das ist nicht wahr!
Denn zu dem behufe wurde yield() eingeführt.
Der Gegenbeweis:
(Ein Blinker, welcher nur blinkt, wenn eine Taste gedrückt wird)