Forum: Mikrocontroller und Digitale Elektronik ATTiny Problem mit Delay


von Michael K. (mmike)


Lesenswert?

Hallo Leute,

ich hab mir ne "eigene" Delay - Funktion für einen ATTiny13 gebaut:

void Delay (uint16_t delay)
{
  uint16_t  del;
  for (del = 0; del < delay; del++)
    asm ("NOP");
}

dabei tritt folgendes Problem auf:
Ich betreibe den ADC im FreeRun Modus und werte die ADC Werte in der ISR 
aus. Soweit funktioniert das ganze auch wunderbar. Nur wenn ich im 
Hauptprogramm, in dem nur ein paar LEDs blinken (dafür verwende ich die 
Delay Funktion) und anzeigen, wie groß die Spannung ist wird der 
Interrupt nicht während der Warteschleife ausgelöst, sondern erst danach 
..... Im Mainloop mit nur einem "sleep_mode()" läuft der ADC mit knapp 
über 330Hz. Wenn ich in den Mainloop nen Delay reinmache, dann reduziert 
sich drastisch die Frequenz !!
Hat da jemand eine Idee ?

Grüße,
Michael

von Falk B. (falk)


Lesenswert?

@ Michael K. (mmike)

>ich hab mir ne "eigene" Delay - Funktion für einen ATTiny13 gebaut:

Warum willst du das Fahrrad neu erfinden? Und dann noch mit eckigen 
Rädern. Nutze sinnvollerweise die bereits fertigen getesteten 
Funktionenn _delay_ms() und _delay_us().

>Interrupt nicht während der Warteschleife ausgelöst, sondern erst danach

Woher weisst du das? Das gleube ich nicht, es sei denn, du sperrst vor 
dem Aufruf der Routine die Interrupts.

MfG
Falk

von Michael K. (mmike)


Lesenswert?

Hallo Falk,

> Warum willst du das Fahrrad neu erfinden? Und dann noch mit eckigen
> Rädern. Nutze sinnvollerweise die bereits fertigen getesteten
> Funktionenn _delay_ms() und _delay_us().

Stimmt schon, aber bis jetzt hatte ich mit meiner Delay - Funktion gute 
Erfahrungen gemacht und da der ATTiny13 nur 1K Flash hat und die von Dir 
genannten delay Funktionen double - Werte verwenden würde der Code zu 
groß werden.....Was genau ist an meinen "Rädern" eckig ? Bzw. was 
kann/sollte/muss ich verbessern ?

> Woher weisst du das? Das gleube ich nicht, es sei denn, du sperrst vor
> dem Aufruf der Routine die Interrupts.

Da bin ich mir eigentlich sicher denn vor dem Hauptprogramm werden 
global die Ints freigegeben und nie gesperrt. Ich hab nen Pin togglen 
lassen wenn in den ADC Interrupt gesprungen wird. Ohne Delay warens rund 
330Hz und mit dem Delay eben der Takt des Delays (rund 1Hz).

Grüße,
Michael

von 2919 (Gast)


Lesenswert?

Es ist unwahrscheinlich dass uint16*NOP 1 sekunde verbratet. Zum einen 
kann man solche dinge mit dem Simulation rausfinden, zum anderen kann 
man einen PIN wackeln und mit dem Scope schauen, und so nicht auf wilde 
Vermutungen angewiesen sein.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Lass den Delay-Mist sein und nimm einen Timer.  Genau dafür sind'se
erfunden worden.  Dann hast du auch keine Sorgen mit dem sleep_mode(),
da der Timerinterrupt den Prozessor auch aus dem Schlaf aufweckt
(falls du ihn überhaupt brauchst und nicht gleich mit einem
Hardware-Toggle am OCx-Pin auskommst).

von Falk B. (falk)


Lesenswert?

@ Michael K. (mmike)

>genannten delay Funktionen double - Werte verwenden würde der Code zu
>groß werden.....

GENAU lesen! Die Funktion arbeitet zwar im Makro mit Double Werten, 
allerding fliegen die durch die Optimierung raus. Das sind dann 
minimale, optimierte Assemblerschleifen.

>Was genau ist an meinen "Rädern" eckig ? Bzw. was
>kann/sollte/muss ich verbessern ?

Dein Delay ist abhängig von der Taktfreqeunz des Oszillators. Der Nutzer 
müsste bei jeder Verwendung neu probieren, wieviele Schleifen pro 
Mikrosekunde/Millisekunde nötig sind. Das alles machen die vorhandenen 
Funktionen automatisch.

>lassen wenn in den ADC Interrupt gesprungen wird. Ohne Delay warens rund
>330Hz und mit dem Delay eben der Takt des Delays (rund 1Hz).

Poste VOLLSTÄNDIGEN, ungekürzten Quelletext als Anhang und wir können 
uns die Sache anschauen. Alles andere ist Glaskugelsport.

MfG
Falk

von Michael K. (mmike)


Lesenswert?

@2919: Das mit der Genauigkeit ist richtig, aber für den Anwendungsfall 
für mich unerheblich. Ich hab eigentlich nur ein Delay gebraucht (kann 
super ungenau sein) damit meine LED's anständig blinken. Gescoped mit 
Pin Toggle habe ich ja sonst hätte ich den "Fehler" gar nicht wirklich 
identifizieren können....

@Jörg Wunsch: Stimmt. Vielen Dank für den Tipp! Genau so hab ichs am WE 
gemacht und funzt super! Ganz ohne Delay .....

@Falk Brunner:
> GENAU lesen! Die Funktion arbeitet zwar im Makro mit Double Werten,
> allerding fliegen die durch die Optimierung raus. Das sind dann
> minimale, optimierte Assemblerschleifen.
Das ist gut zu wissen ! Danke ! Ich werd' mich auf alle Fälle dran 
halten !

> Dein Delay ist abhängig von der Taktfreqeunz des Oszillators. Der Nutzer
> müsste bei jeder Verwendung neu probieren, wieviele Schleifen pro
> Mikrosekunde/Millisekunde nötig sind. Das alles machen die vorhandenen
> Funktionen automatisch.
Das war mir auch bewußt. Wie schon gesagt hab ich einfach nen ungenaues 
Delay gebraucht um ein Blinken der LEDs auch als solches zu erkennen. 
Aber jetzt kenne ich ja den besseren Weg !! ;-)

> Poste VOLLSTÄNDIGEN, ungekürzten Quelletext als Anhang und wir können
> uns die Sache anschauen. Alles andere ist Glaskugelsport.
Du hast Recht. Sorry und vielen vielen Dank an alle, die "mitgeraten" 
haben !

Grüße,
Michael

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.