Forum: Mikrocontroller und Digitale Elektronik Taster entprellen mit Timer für 1ms und 10ms


von Steffen (Gast)


Lesenswert?

Hallo
Zum entprellen von Taster verwende ich Peter seinen Code, der sehr gut 
funktioniert. Dabei verwende ich diesen Timer:
1
void timer1_init()            // 8MHz, 10ms
2
  {                    // Timer 1 konfigurieren
3
    TCCR1A = (1<<WGM01);          // Auswahl CTC Modus
4
    TCCR1B = (1<<CS01)|(1<<CS00);      // Prescaler auf 64 setzen
5
    OCR1A=1249;              // Wert für 10ms
6
    TIMSK1|=(1<<OCIE1A);          // Interrupt erlauben
7
  }
In einigen Beiträgen wird vorgeschlagen einen Timer mit 1ms zu nehmen 
und hochzuzählen.
Für eine Uhr verwende ich z.B. das:
1
ISR (TIMER0_COMPA_vect)
2
  {
3
  millisekunden++;
4
  if(millisekunden == 1000)
5
    {
6
    sekunde++;
7
    millisekunden = 0;
8
    if(sekunde == 60)
9
      {
10
      minute++;
11
      sekunde = 0;
12
      }
13
    if(minute == 60)
14
      {
15
      stunde++;
16
      minute = 0;
17
      }
18
    if(stunde == 24)
19
      {
20
      stunde = 0;
21
      }
22
    }
23
  }
Wie kann ich am besten einen Timer mit 1ms für beide Aufgaben verwenden?

von Teo D. (teoderix)


Lesenswert?

Steffen schrieb:
> ISR (TIMER0_COMPA_vect)
static tasten-time;
if (++tasten_time>=10){tasten_timer=0;Pedas_Tasten_Dingens() (oder ein 
global_flag für die Main_Loop setzen);}

von N. M. (mani)


Lesenswert?

Nimm halt den 1ms Timer und rufe jedes 10. Mal die Routinen von Peter 
auf.

Taster ist ja im Normalfall nichts mega hochpriores. Also reicht das 
wahrscheinlich sogar über ein polling in Main.

Edit: zu langsam getippt 😄

: Bearbeitet durch User
von Der Opa aus der Muppet Show (Gast)


Lesenswert?

Am übersichtlichsten finde ich:

Eine ISR, die einfach nur die "millisekunden" Variable hoch zählt. Dazu 
für jede Aufgabe eine eigene Funktion. Und eine "main" Schleife, die 
einfach nur reihum alle Funktionen aufruft.

Deine entprellen Funktion fragt dann die "millisekunden" Variable ab. 
Wenn genug Zeit vergangen ist setzt sie eine Variable "taster1" oder 
ähnliches.

Die Funktion, die deine Arbeit macht fragt dann die "taster1" Variable 
ab.

(Das eigentliche Problem - mit der Zeit kommen immer mehr Ideen, die du 
auch noch einbauen willst. Das Programm von vorn herein so anlegen, dass 
die Funktionen einfach und überschaubar bleiben.)

von Teo D. (teoderix)


Lesenswert?

Der Opa aus der Muppet Show schrieb:
> Eine ISR, die einfach nur die "millisekunden" Variable hoch zählt. Dazu
> für jede Aufgabe eine eigene Funktion. Und eine "main" Schleife, die
> einfach nur reihum alle Funktionen aufruft.
>
> Deine entprellen Funktion fragt dann die "millisekunden" Variable ab.
> Wenn genug Zeit vergangen ist setzt sie eine Variable "taster1" oder
> ähnliches.

Wie so für 'jede' Funktion die ms prüfen? Bau dir 'Time-Slots'!
Da bleibst auch übersichtlicher.

von Peter D. (peda)


Lesenswert?

Der Opa aus der Muppet Show schrieb:
> Deine entprellen Funktion fragt dann die "millisekunden" Variable ab.

Nö, die Entprellfunktion muß in einem festen Intervall aufgerufen 
werden, z.B. alle 10ms. Die Lösung dazu wurde ja schon von Teo D. 
genannt.

Der Opa aus der Muppet Show schrieb:
> Die Funktion, die deine Arbeit macht fragt dann die "taster1" Variable
> ab.

Nö, die Mainloop fragt nur ganz bequem die Ereignisbits ab und löscht 
sie.
Ihr ist im Prinzip egal, wer die Ereignisbits setzt. Man kann so ganz 
einfach den Tasten am Gerät eine IR-FB oder Tastenbefehle über die UART 
parallel schalten.

von Georg (Gast)


Lesenswert?

Steffen schrieb:
> Wie kann ich am besten einen Timer mit 1ms für beide Aufgaben verwenden?

Indem du in der ISR beides nacheinander durchführst - das setzt 
natürlich voraus, dass keine der Aufgaben (das können noch einige mehr 
sein) die Ausführung länger blockiert, Delays sind verboten.

Ich führe praktisch alle Hintergrundtätigkeiten in einem regelmässigen 
Time-Interrupt durch, manche auch nur in jedem 2. oder xten. Man muss 
nur überschlagen, ob nicht die Bearbeitungszeit den Timer Tick 
überschreiten kann. Aufgaben, die nicht in jedem Tick bearbeitet werden 
verschachtelt man. So kann man auch auf einen extra 10ms Tick 
verzichten.

bei 1 ms kann man einen Zähler verwenden:
Taster gedrückt:
  ist der Wert < 10, dann um 1 hochzählen, bei 10 Flag für den Eingang
  setzen.
  ist der Wert 10, nichts
Taster nicht gedrückt:
  Ist der Wert > 0, dann um 1 runterzählen, bei 0 Flag für den Eingang 
rücksetzen.
  Ist der Wert 0, nichts

Mit dem Maximalwert bestimmt man die Reaktionszeit - kurz für Gamer, 
lang für Maschinenbediener, ist also sehr flexibel.

Georg

von Der Opa aus der Muppet Show (Gast)


Lesenswert?

> Nö, die Entprellfunktion muß in einem festen Intervall aufgerufen
> werden

Eigentlich nicht wirklich. In diesem Fall kommt es auf eine Millisekunde 
hin oder her nicht an.

In Summe bekommst du die wenigsten Probleme, wenn du in den ISRs nur die 
wirklich zeitkritischen Sachen machst. Na ja, in diesem Fall nicht so 
wichtig, Entprellen braucht ja nur ein paar Taktzyklen.

> Nö, die Mainloop fragt nur ganz bequem die Ereignisbits ab und löscht
> sie.

Kommt drauf an, wie umfangreich das Programm wird. Wenn das Programm 30 
verschiedene Aufgaben gleichzeitig erledigt, wird so ein Ansatz halt 
unübersichtlich, Fehler im Programmablauf suchen wird aufwendig.

> Bau dir 'Time-Slots'!

Ja, eine gute Richtung! Schau dir die Standard Designpattern an sobald 
du genug Erfahrung hast um zu sehen, wie genial so einfach aussehende 
Konzepte wie Time-Slots sind.

von Peter D. (peda)


Lesenswert?

Der Opa aus der Muppet Show schrieb:
> Eigentlich nicht wirklich. In diesem Fall kommt es auf eine Millisekunde
> hin oder her nicht an.

Genau. Deshalb braucht man nicht umständlich die long Variable 
Millisekunden überlauffest zu vergleichen. Es reicht ein simples Byte 
bis 10 zu zählen.

Der Opa aus der Muppet Show schrieb:
> Kommt drauf an, wie umfangreich das Programm wird. Wenn das Programm 30
> verschiedene Aufgaben gleichzeitig erledigt, wird so ein Ansatz halt
> unübersichtlich, Fehler im Programmablauf suchen wird aufwendig.

Im Gegenteil, gerade bei umfangreichen Programmen lohnt es sich 
besonders, daß die Entprellung, Flankenerkennung, Repeat und Lang 
Auswertung im Interrupt passiert. Es sind nur wenige logische 
Operationen, d.h. nur sehr geringe CPU-Last.
Das Main darf sogar heftig beschäftigt sein und das Ereignisbit erst 
auswerten, wenn schon wieder losgelassen wurde.
Die Fehlersuche vereinfacht sich auch erheblich, weil das Main ja mit 
dem Tasten einlesen nichts mehr zu tun hat.
Es ist schon abenteuerlich, welche unübersichtliche und fehlerträchtige 
Konstrukte manchmal erstellt werden, um mehr schlecht als recht im Main 
zu entprellen.

von Der Opa aus der Muppet Show (Gast)


Lesenswert?

> Im Gegenteil

Yeah! Genau deswegen bringen diese Mikrocontroller Projekte Spaß.

Hatte mal Bauing studiert. Da hatte man uns beigebracht, wir müssen 
alles nach DIN Norm machen. Ende der Durchsage. Total langweiliger Job.

Wenn du als Programmierer fragst, wie man es macht, empfiehlt dir jeder 
das Gegenteil. Und du musst selbst herausfinden, wie es am besten 
funktioniert.

von Steffen (Gast)


Lesenswert?

Teo D. schrieb:
> Wie so für 'jede' Funktion die ms prüfen? Bau dir 'Time-Slots'!
> Da bleibst auch übersichtlicher.
Sorry, vor Tastern habe ich keine Angst, aber das habe ich noch nie 
gemacht.

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.