Blutiger Anfänger mit Timer Problem

OP #2448225
Lesenswert?

Hallo Leute,
ich bin ein blutiger Anfänger und trau mich kaum ne Frage über Timer zu 
stellen, aber ich seh den Wald vor lauter Bäumen wohl nicht mehr. Ich 
hab mal meinen kompletten C Code angehängt, aber ich wollte kurz auf die 
interessanten Teile eingehen:

Ich hab nen externen Crystal mit 16GHz an nem Atmega644


Meine Frage ist nun, wenn ich oben in meinem Timer die Kommentare weg 
mache, dann blinken die LEDs alle 3 bis 4 Sekunden auf einmal 
unregelmäßig, danach für 3 Sekunden wieder normal.

Mach ich was Grundlegendes falsch? Mache ich zu viele Berechnungen im 
Timer?


Ich hab den Timer mit Clear Timer on Compare Match eingestellt:
1
void timerInit(void) {
2
  TCCR0A = (1 << WGM01); //Mode2: CTC Clear Timer on compare match
3
  TCCR0B = (1 << CS01) | (1 << CS00); // prescaler = 64
4
  OCR0A = 250; //250 Takte = 1ms
5

6
//  TCCR1A = 0; // kein pwm
7
  TIMSK0 = (1 << OCIE0A); //Compare Interrupt aktivieren
8
}
9

10
Meine Timer Interrupt Funktion sieht so aus:
11
ISR (TIMER0_COMPA_vect) {
12
  if (led1on)
13
    led1on--;
14
  millisekunden++;
15
/*  if(millisekunden == 1000) {
16
    sekunde++;
17
    millisekunden = 0;
18
  }
19
    if(sekunde == 60) {
20
         minute++;
21
         sekunde = 0;
22
    }
23
    if(minute == 60) {
24
      stunde++;
25
      minute = 0;
26
    }*/
27
}
28

29
Dann hier noch meine main:
30
int main(void) {
31

32
  uint16_t delay;
33

34
  cli();
35
  systemInit();
36
  timerInit();
37
  sei();
38
  while (1) {
39
    if (IN(SWITCH_PORT, SWITCH_PIN))
40
      delay = 500;
41
    else
42
      delay = 1000;
43
    if (!led1on) {
44
      leds();
45
      led1on = delay;
46

47
    }
48
  }
49
}
Angehängte Dateien:
OP #2448361
Lesenswert?

@Coder:
die led1on ist schon volatile! Hatte ich in dem kurzen Abschnitt nicht 
kopiert aber im main.c ist das zu sehen...

@Frank Link
ich hab jetzt mehrere Sachen versucht, aber irgendwie ist das Springen 
der LEDs immer noch da...

Meine main sieht jetzt so aus, oder hatte ich das falsch verstanden mit 
dem sei cli?
1
int main(void) {
2
  cli();
3

4
  uint16_t delay;
5

6
  systemInit();
7
  timerInit();
8
  sei();
9
  while (1) {
10
    if (IN(SWITCH_PORT, SWITCH_PIN)) {
11
      cli();
12
      delay = 500;
13
      sei();
14
    } else {
15
      cli();
16
      delay = 1000;
17
      sei();
18
    }
19
    if (!led1on) {
20
      leds();
21
      led1on = delay;
22

23
    }
24
  }
25
}
#2448490
Lesenswert?

Mario Dejung schrieb:
> Ok, macht Sinn, sind ja 16bit Operationen...
> Aber helfen tut es leider auch nicht :-(

Das reicht nicht.
Du hast ja noch einen Zugriff auf led1on, den du kapseln musst
1
    cli();
2
    uint16_t tmp = led1on;
3
    sei();
4

5
    if (!tmp) {
6
      leds();
7
      cli();
8
      led1on = delay;
9
      sei();
10
    }

Du hast natürlich dadurch, dass du die ganzen Zeitvariablen alle
unsigned int( also 16 Bit) gemacht hast, dem µC jede Menge unnötige
Fleissaufgabe aufgebürdet. Die solltest du (bis auf Millisekunden) alle
als uint8_t führen. Das langt dicke für Sekunden, Minuten, Stunden.
Gast #2449742
Lesenswert?

das Problem ist halt dass led1on an zwei Stellen verändert/benutzt wird.

wenn jetzt im main vielleicht gerade das erste Byte geladen wurde, funkt 
plötzlich der IRQ dazwischen, ändert beide Bytes des Wortes und 
plötzlich passen im main die beiden Bytes aus denen ein Wort besteht 
nicht mehr zusammen
OP #2449755
Lesenswert?

Hätte man da dann nicht einfacher Weise die komplette if Abfrage in cli 
und sei setzen können, anstatt noch mal drumrum in ne andere Variable u 
speichern? So ungefähr:
1
  while (1) {
2
    if (IN(SWITCH_PORT, SWITCH_PIN)) {
3
      delay = 500;
4
    } else {
5
      delay = 1000;
6
    }
7
    cli();
8
    if (!led1on) {
9
      leds();
10
      led1on = delay;
11
    }
12
    sei();
13
  }
#2450200
Lesenswert?

Mario Dejung schrieb:
> Hätte man da dann nicht einfacher Weise die komplette if Abfrage in cli
> und sei setzen können, anstatt noch mal drumrum in ne andere Variable u
> speichern? So ungefähr:

Natürlich kann man.
Wichtig ist nur, dass weder bei Abfrage noch beim Beschreiben der 
Variable ein Interrupt dazwischen funken kann.
Du musst dich eben fragen, wie lange du die Interrupts gesperrt haben 
willst.

Ein Schlüsselnotdienst, der sofort reagiert, hilft dir nun mal nichts, 
wenn wegen Telefonsperre keiner abhebt.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren