Forum: Mikrocontroller und Digitale Elektronik Verzögerungsfunktion


von semo (Gast)


Lesenswert?

Hi!

Wollte eine kleine Verzögerung zwecks Schalter-Entprellung
einbauen...aber hab so den eindruck als würde es nicht unbedingt
(richtig) funktioneren!

Vielleicht kanns sich ja wer kurz zeit nehmen und sich den code gach
anschaun!

===== Anfang =====

#define F_CPU 4000000
#define USART_BAUD_RATE 19200  // 19200
#define USART_BAUD_SELECT ((F_CPU/(USART_BAUD_RATE*16l))-1)

SIGNAL(SIG_INTERRUPT0) {
 delay_ms(50);      // Verzögerung von 500ms
 USART_transmit('x');
}

void InitSFRs(void)
{
  //Timer0 initialization:
  // Clock source: System Clock
  TCCR0=0x04; //  set prescaler to 1:256 (bei 4MHz, 10ms step)
  TCNT0=0x62;  //  Preload Timer0 value for 10ms steps (0x62 = 98)
  TIMSK=0x00;  //  disables timer0 overflow bit (T0IE0=1)

  // External Interrupt initialization:
  // INT0: ON
  MCUCR=0x0F;  // Rising Edge of INT0 + INT1 generates an
                // interrupt  request
  GICR=0x40;  // enables External Interrupt Request of INT0
}

void delay_ms (unsigned short x) {
  int c=0;
  TCNT0=0x62;  //  Preload Timer0 value for 10ms steps (0x62 = 98)
  TIFR &=  ~(1<<TOV0);    //Lösche Timer Overflow Flag in TIFR
                          //(Timer Interrupt Flag Register)
  while (c < x) {
   if (TIFR & (1<<TOV0)) {    //Kontrolliere, ob TOV0-Bit in TIFR
                              //gesetzt ist
  c++;
  TIFR &=  ~(1<<TOV0);
    }
  }
}

===== Ende =====

Falls ich net irgendwo einen Fehler gemacht haben sollte, müsste doch
alle 10ms das Overflow Flag gesetzt werden -> das heisst in diesem Fall
- beim ext. Interrupt ergibt sich doch eine Verzögerungszeit von 500ms,
oder?


gruß,
semo

von Fritz Ganter (Gast)


Lesenswert?

TIMSK=0x00;  //  disables timer0 overflow bit (T0IE0=1)

Und wo enabled du den interrupt?

von semo (Gast)


Lesenswert?

das mach ich erst später, nach einer abfrage (wenn ich was bestimmtes
empfangen habe...hab den code net vollständig gepostet).

Aber eigentlich brauch ich doch im moment dieses overflow bit nicht für
die "verzögerung", oder!? (mit dem aktiviere ich ja nur den
enstprechenden interrupt nach einem overflow - wenns stimmt...)

gruß,
semo

von Peter D. (peda)


Lesenswert?

> SIGNAL(SIG_INTERRUPT0) {
>  delay_ms(50);      // Verzögerung von 500ms


Oh, oh, oh, ganz, ganz böses Foul !
In einem Interrupt warten ist streng verboten, erst recht nicht für
jahrelange 500ms !

Es sieht ja vielleicht aus, als obs nicht schadet, aber sobald Dein
Programm etwas mehr machen soll, krachts.
Z.B. wenn über die UART was empfangen werden soll, gehen Dir bei jedem
Tastendruck haufenweise Zeichen verloren.


Ich weiß nicht, warum Tastenabfragen immer so kompliziert und
Ressourcen verschlingend gemacht werden müssen.

In meinen diversen Beispielen in der Codesammlung verwende ich eine
super einfache Tastenroutine für bis zu 8 Tasten, die so ganz nebenbei
im Timerinterrupt mit ausgeführt wird.

Dazu werden im Interrupt nur etwa 10µs benötigt und keine 500000µs !


Peter

von Stefan Kleinwort (Gast)


Lesenswert?

Hör auf Peter!
Auf den Anwender zu warten ist wie mit einer Schnecke spazierengehen zu
wollen.

Stefan

von semo (Gast)


Lesenswert?

@Peter
dachte es wäre net so schlimm da der tastendruck nicht oft verwendet
wird und erst danch (wenns abgeschlossen ist)soll UART was empfangen!
danke für den hinweis...!

gruß,
semo

von semo (Gast)


Lesenswert?

ähm, hätte da noch eine ("blöde") frage bzw. weiss net obs net auch
verboten is..
Wäre zum Beispiel folgendes möglich (auch wenns keine "elgante"
lösung ist):

SIGNAL(SIG_INTERRUPT0) {
  GICR=0x00;  // disables External Interrupt Request of INT0
  <"wait 4ms">
  GICR=0x40;  // enables External Interrupt Request of INT0
  <"weiter im programm">
  USART_transmit('x');
}


gruß,
semo

von Stefan Kleinwort (Gast)


Lesenswert?

@Peter:
habe gerade eine leichte Doppeldeutigkeit in meinem Post gesehen. Ich
meinte natürlich, semo soll auf Dich hören, nicht dass Du aufhören
sollst, sorry.

@semo:
Verboten ist erstmal nix.
Aber es macht ja keinen Sinn, sich an einem Programm mit winziger
Funktionalität eine falsche Programmierweise anzugewöhnen, die einem
dann im Weg ist, wenn es mal aufwändiger wird.

In Deinem Programm willst Du den aktuellen IR disablen, damit andere
zwischenreinfunken dürfen, korrekt?
Dann musst Du das globale IR-Flag freischalten (nach dem disable vom
aktuellen IR).
Später musst Du globale IR wieder sperren, und erst DANACH den
aktuellen IR wieder freigeben.
Und Du musst daran denken, den Stack groß genug zu haben, dass mehrere
IR-Aufrufe Platz finden.

Das Ganze ist nicht ganz untrivial. Und ein Fehler im IR-Handling
gehört zu einem der ekligsten Dinge. Deshalb würde ich sowas nur
machen, wenn es garnicht anders geht.

Die sauberste Lösung: Tasten im Timer-IR auswerten und dem HP zur
Verfügung stellen (siehe Peters lib dazu). Genauso UART-In und
UART-Out, die ein- und ausgehenden Zeichen in Ringpuffern
zwischenspeichern. Das funktioniert auch dann noch, wenn Dein Programm
richtig kompliziert wird.

Stefan

von semo (Gast)


Lesenswert?

danke Stefan!

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.