Forum: Mikrocontroller und Digitale Elektronik _delay_ms timer dauert zu lange


von Mark (Gast)


Lesenswert?

Hallo,
ich möchte mit dem ARduino Uno zu beginn eine LED Toggeln lassen. Hier 
gibt es aber schon das Problem, welches ich nicht verstehe. ich habe 
zunächst
#define F_CPU 16000000UL (ist der Quarz auf dem Arduino)
in der while-schleife lasse ich mit _delay_ms(1000); ungefähr eine 
Sekunde warten und danach die LED an PB5 Togglen. Das Problem ist, dass 
die LED nur alle 2 Sekunden ihren Status wechselt.
Aber das _delay_ms benötigt doch nur F_CPU oder?

Mark

von Carl D. (jcw2)


Lesenswert?

_delay_ms berücksichtig nicht eventuell parallel laufende Interrupts. 
Es dauert also immer mindestens die angegebene Zeit. Allerdings wären 
50% Interruptlast schon heftig.

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?

Evtl. läuft der MC mit den internen 8Mhz. Wenn du die Möglichkeit hast, 
lies doch mal die Fuses aus. Du kannst auch mal F_CPU auf 8000000UL 
ändern und schauen, obs dann passt - das wäre der Beweis.

von Mark (Gast)


Lesenswert?

Matthias S. schrieb:
> Evtl. läuft der MC mit den internen 8Mhz. Wenn du die Möglichkeit
> hast,
> lies doch mal die Fuses aus. Du kannst auch mal F_CPU auf 8000000UL
> ändern und schauen, obs dann passt - das wäre der Beweis.

genau so war es auch. alle Fuses waren auf 0x00 (wurde mir zumindes im 
Atmel Studio so angezeigt).

allerdings passt das auch nicht wirklich.


wenn ich jetzt einen Timer initialisiere
1
...
2
// Timer 0
3
TCCR0A = (1 << WGM01); // CTC Modus
4
TCCR0B = (1 << CS01) | (1 << CS00); // clk/64 -> = 125kHz
5
OCR0A = 125-1; // -> 1ms Interrupt
6
7
// Overflow Interrupt allow
8
TIMSK0 |= (1 << OCIE0A);
9
...
10
11
12
13
14
ISR (TIMER0_COMPA_vect){
15
  unsigned int  millisekunde = 0;
16
  unsigned int sekunde = 0;
17
  
18
  millisekunde++;
19
  if(millisekunde == 1000){
20
    millisekunde = 0;
21
    sekunde++;
22
    TOGGLEBIT(PORTB, 5);
23
    if(sekunde == 60){
24
      sekunde = 0;
25
    }
26
  }
27
}

und die LED in der Interrupt Routiene Toggle (dort warte ich 1000 
Aufrufe ab, damit ich eine Sekunde habe), dann ist die ungefähr doppelt 
so schnell.
Wenn ich aber OCR0A auf 250 hochsetze, passiert auch nichts anderes.

von H.Joachim S. (crazyhorse)


Lesenswert?

unsigned int  millisekunde = 0;
unsigned int sekunde = 0;

Da fehlt eigentlich static? Dürfte so überhaupt nicht funktionieren, da 
bei jedem Funktionseintritt auf 0 gesetzt wird.

von Mark (Gast)


Lesenswert?

H.Joachim S. schrieb:
> Da fehlt eigentlich static

Das hatte/habe ich aber im code drinn. Muss wohl beim übertragen 
verloren gegangen sein.

also ich hatte stehen
1
static unsigned int millisekunde = 0;
2
static unsigned int sekunde = 0;

von Frickelfritze (Gast)


Lesenswert?

Mark schrieb:
> // Overflow Interrupt allow
> TIMSK0 |= (1 << OCIE0A);

Du willst einen Compare Match Interrupt, enablest aber
den Overflow Interrupt .....

von Mark (Gast)


Lesenswert?

Frickelfritze schrieb:
>> // Overflow Interrupt allow
>> TIMSK0 |= (1 << OCIE0A);
>
> Du willst einen Compare Match Interrupt,

Das ist nur ein schreibfehler im Kommentar. Im Datenblatt steht:
OCIE0A: Timer/Counter0 Output Compare Match A Interrupt Enable

von Einer K. (Gast)


Lesenswert?

Tipp:
Keine Kommentare im Quelltext, ist ja schon schlimm.
Aber falsche, sind die Hölle. (dann besser keine)

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


Lesenswert?

Mark schrieb:
> genau so war es auch. alle Fuses waren auf 0x00 (wurde mir zumindes im
> Atmel Studio so angezeigt).
 Dann funktioniert auch der Bootloader nicht, wie programmierst du
 deinen Arduino ?

Mark schrieb:
> Wenn ich aber OCR0A auf 250 hochsetze, passiert auch nichts anderes.
 Das kann schon mal nicht sein.

 Nimm deine Variablen aus der ISR heraus, deklariere die als volatile
 und probiere es nochmal.

von Frickelfritze (Gast)


Lesenswert?

Marc V. schrieb:
> Nimm deine Variablen aus der ISR heraus, deklariere die als volatile

Wenn die Variablen nur in der ISR verwendet werden ist
das beides unnötig.

von Frickelfritze (Gast)


Lesenswert?

Mark schrieb:
> TCCR0B = (1 << CS01) | (1 << CS00); // clk/64 -> = 125kHz

16Mhz / 64 = 250KHz !!
 8Mhz / 64 = 125KHz

Tatsächlich kommt in meinem Testablauf der Interrupt mit
2 KHz daher. Mein Arduino 328 läuft mit 16 MHz.

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


Lesenswert?

Frickelfritze schrieb:
> Wenn die Variablen nur in der ISR verwendet werden ist
> das beides unnötig.

 Wenn die Variablen als volatile deklariert werden, sind die Global.
 Auch wenn die Variablen in der ISR als static deklariert werden, sind
 die nur in der ISR sichtbar.
 Beim debugging kann volatile ganz nützlich sein, oder ?

von Frickelfritze (Gast)


Lesenswert?

Marc V. schrieb:
> Beim debugging kann volatile ganz nützlich sein, oder ?

Aber das behebt in keiner Weise sein Problem so wie
du es suggerierst:

Marc V. schrieb:
> und probiere es nochmal.

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


Lesenswert?

Frickelfritze schrieb:
> Aber das behebt in keiner Weise sein Problem so wie
> du es suggerierst:

 Sein Problem besteht darin, dass er Codeschnipsel zeigt, danach
 behauptet, dass das was drin ist in seinem Code ganz anders aussieht,
 dass seine Kommentare falsch sind, dass seine Aussagen, wie z.B:

Mark schrieb:
> genau so war es auch. alle Fuses waren auf 0x00 (wurde mir zumindes im
> Atmel Studio so angezeigt).
 Sicher, mit 0x00 funktioniert deine MEGA problemlos, vor allem geht
 programmieren über ISP klaglos...

> Das hatte/habe ich aber im code drinn. Muss wohl beim übertragen
> verloren gegangen sein.

 Ja, irgendwie rausgefallen und gleich beide...

 EDIT:
 Mit OCR0A auf 249 und 16MHz funktioniert das Ganze bei mir ohne
 Probleme.

von Frank S. (_frank_s_)


Lesenswert?

Mark schrieb:
> zu beginn eine LED Toggeln

passt doch :
1. Durchlauf toggeln -> LED von aus nach ein
   1s warten
2. Durchlauf toggeln -> LED von ein nach aus
   1s warten
3. Durchlauf toggeln -> LED von aus nach ein
   1s warten
...
dauert halt 2s ....

MfG von der Spree

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?

Frank S. schrieb:
> ...
> dauert halt 2s ....
>
> MfG von der Spree

Nö, passt nicht, denn der TE schreibt ja ausdrücklich:

Mark schrieb:
> Das Problem ist, dass
> die LED nur alle 2 Sekunden ihren Status wechselt.

Lies also nochmal das erste Posting.

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.