Forum: Mikrocontroller und Digitale Elektronik delay Funktion mit IRS ersetzen


von M. S. (ekkie)


Lesenswert?

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
int jj=0;
7
8
int main(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.

von Wolfgang (Gast)


Lesenswert?

M. S. schrieb:
> ersetzen könnte mit einer IRS

Vielleicht erklärst du erstmal, was eine IRS ist.

von M. S. (ekkie)


Lesenswert?

*ISR

von Falk B. (falk)


Lesenswert?

@ 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.

von Wolfgang (Gast)


Lesenswert?

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.

von fop (Gast)


Lesenswert?

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.

von Peter D. (peda)


Lesenswert?

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.

von Themaverfehlung (Gast)


Lesenswert?

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)

von Einer K. (Gast)


Angehängte Dateien:

Lesenswert?

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.

von Einer K. (Gast)


Lesenswert?

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.

von Peter D. (peda)


Lesenswert?

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.

von Peter D. (peda)


Lesenswert?

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?

von Einer K. (Gast)


Angehängte Dateien:

Lesenswert?

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.

von Peter D. (peda)


Lesenswert?

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.

von Joachim B. (jar)


Lesenswert?

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/1675031


M. 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.

: Bearbeitet durch User
von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

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 ?

von Joachim B. (jar)


Lesenswert?

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?

von Einer K. (Gast)


Lesenswert?

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.

von Einer K. (Gast)


Lesenswert?

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.

von Äxl (geloescht) (Gast)


Lesenswert?

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:
1
void loop() 
2
{
3
   PORTD = counter = flankenerkennung = entprellen = taster;
4
}
Das ist der Grund, mir mal die Quellen der Libs zu ziehen und mir das 
mal anzusehen.
Achso: weitermachen!
Gruß, 73 Äxl, DG1RTO

von Einer K. (Gast)


Lesenswert?

Ä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.

von Wegstaben V. (wegstabenverbuchsler)


Lesenswert?

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.

: Bearbeitet durch User
von Stefan F. (Gast)


Lesenswert?

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:
1
void led_blinker()
2
{
3
    static uint8_t state=0;
4
    unsinged long waiting_since;
5
    switch (state)
6
    {
7
        // LED ein schalten
8
        case 0: 
9
            led_ein_schalten(); 
10
            waiting_since=millis();
11
            state=1;
12
            break;
13
14
        // 500ms warten
15
        case 1: 
16
            if (millis()-waiting_since > 500)
17
            {
18
                state=2;
19
            }
20
            break;
21
22
        // LED aus schalten
23
        case 2: 
24
            led_aus_schalten(); 
25
            waiting_since=millis();
26
            state=3;
27
            break;
28
29
        // 200ms warten
30
        case 3: 
31
            if (millis()-waiting_since > 200)
32
            {
33
                state=0;
34
            }
35
            break;
36
    }
37
}
38
39
void main()
40
{
41
    ...
42
43
    // main loop
44
    while (1)
45
    {
46
        led_blinker();
47
    }
48
}

von Wolfgang (Gast)


Lesenswert?

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.

von Joachim B. (jar)


Lesenswert?

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.

: Bearbeitet durch User
von Stefan F. (Gast)


Lesenswert?

> unsinged long waiting_since;
Da fehlt das Schlüsselwort "static", ganz wichtig!

von Äxl (geloescht) (Gast)


Lesenswert?

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

von Stefan F. (Gast)


Lesenswert?

Ä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?

von Einer K. (Gast)


Lesenswert?

Ä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
void main() 
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.

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

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.

von Joachim B. (jar)


Lesenswert?

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.

von Wolfgang (Gast)


Lesenswert?

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.

von Joachim B. (jar)


Lesenswert?

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?

von c-hater (Gast)


Lesenswert?

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.

von Wolfgang (Gast)


Lesenswert?

Joachim B. schrieb:
> wieso?

DU hast es nicht begriffen.
Der TO hat gleich klar gestellt, dass er ISR meinte.

von S. Landolt (Gast)


Lesenswert?

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.

von c-hater (Gast)


Lesenswert?

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).

von S. Landolt (Gast)


Lesenswert?

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.

von Bernie (Gast)


Lesenswert?

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

von Einer K. (Gast)


Lesenswert?

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)

von Volker A. (Gast)


Lesenswert?

(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
   volatile unsigned long timer0_millis = 0;   // Zeit in ms seit Reset
14
   unsigned long time_prev;
15
   int time_interval = 1500;                   // LED Blink-Periode 3 s
16
17
18
   unsigned long millis()
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
      unsigned long m;
24
      uint8_t oldSREG = 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)
28
      cli();
29
      m = timer0_millis;     // timer0_millis: globale Variable
30
      SREG = oldSREG;
31
      
32
      return m;
33
   }
34
35
36
   ISR(TIMER0_COMPA_vect)
37
   {
38
      // Millisekunden-Zähler inkrementieren
39
      timer0_millis ++;
40
   }
41
42
43
   int main (void)
44
   {
45
      uint8_t  buttonstate;
46
47
      // setup
48
49
      // I/O Ports
50
      DDRB &= ~(1 << 0);                // PORTB.PB0 Input         (Arduino D8)
51
      DDRC |= ((1 << 0) | (1 << 5));    // PORTC.PC0, .PC5 Output  (Arduino A0 und A5)
52
53
54
      // Timer/Counter0 konfigurieren + starten
55
      // Prescaler 64 und OCR0A = 250
56
      // ->  Interrupts alle 1,000 ms
57
      TCCR0A |= (1 << WGM01);              // Set the Timer Mode to CTC
58
      OCR0A = 0xFA;                        // Endwert 250
59
      TCCR0B |= (1 << CS01 | 1 << CS00);   // Prescaler 64
60
61
      // Interup aktivieren
62
      TIMSK0 |= (1 << OCIE0A);     // Set the ISR COMPA vect
63
      sei();                       // Enable Interrupts global
64
65
      time_prev = millis();        // 1. Zeitstempel
66
   
67
68
      // loop
69
70
      while(1) 
71
      {
72
         // Tasterstatus an Pin PB0 über die LED 1 (gelb) an
73
         // Pin PC5 ausgeben
74
75
         if (PINB & (1 << 0))
76
         {
77
            // pin is high
78
            PORTC |= (1 << 5);
79
         }
80
         else
81
         {
82
            // pin is low
83
            PORTC &= ~(1 << 5);
84
         }
85
86
87
         // Blinken der LED 2 (rot) an Pin PC0 unter Verwendung der
88
         // nicht-blockierenden millis Funktion
89
90
         if ((millis() - time_prev)  > time_interval)
91
         {
92
            time_prev = millis();
93
            // LED 2 (rot) toggeln
94
            PORTC ^= (1 << 0);
95
         }
96
 
97
      }
98
    
99
      return 0;
100
   }

von Einer K. (Gast)


Lesenswert?

> 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)
1
const byte taster     = 3;
2
const byte led        = LED_BUILTIN;
3
bool BlinkAnforderung = false;
4
5
6
7
//---------------------------------------------
8
9
10
void yield()
11
{
12
  BlinkAnforderung = !digitalRead(taster);
13
}
14
15
16
17
//---------------------------------------------
18
19
20
void setup() 
21
{
22
  pinMode(led,OUTPUT);
23
  pinMode(taster,INPUT_PULLUP);
24
}
25
 
26
void loop() 
27
{
28
  if(BlinkAnforderung) digitalWrite(led,!digitalRead(led));
29
  delay(500);
30
}



Und Interrupts gibts ja auch noch...

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.