Software-Timer abweichung

Gast #4918107
Lesenswert?

Hallo,

wollte eine konstante Zeit vom Timer-Interrupt ableiten, nur stimmt 
irgendwie meine errechnete Zeit mit der realen Zeit nicht überein. Zum 
Ablauf der Timerinterrupt wird alle 4,096 ms aufgerufen dort wird eine 
Variable hochgezählt bis die Zeit von 200,704 ms erreicht wurden.

Dann wird eine globale Variable auf 60000 (soll 1 Min entsprechen) 
initialisiert die dann dekrementiert wird und die LED toggelt von grün 
auf rot.

Tatsächlich wird die LED aber nach 6 sekunden auf rot geschaltet und 
nicht nach 1 min wie ursprüglich berechnet.

Woran kann es liegen?

Über eine Info würde ich mich freuen.


1
void init_timer2 (void)
2
{
3
  TCC1.PER = 2; //Timer top value (overflow at 4µs)
4
  TCC1.CTRLB = TC_TC1_WGMODE_NORMAL_gc; // Mode: Normal mode
5
  TCC1.CTRLA = TC_TC0_CLKSEL_DIV1_gc; // Prescaler 1
6
  TCC1.INTCTRLA = TC_TC1_OVFINTLVL_LO_gc; //Interrupt modus active priority low
7
}
8

9

10
void interrupt_init (void)
11
{
12
  PMIC.CTRL |= PMIC_LOLVLEN_bm; //Interrupt on
13
  sei(); //Interrupt enable
14
}
15

16
s_IO.ulLaufzeit = 60000; 
17

18
int main (void)
19
{  
20
  PORTB.DIRSET = PIN2_bm;  
21
  PORTB.DIRSET = PIN3_bm;
22
  PORTB.OUTSET = PIN3_bm;
23
    
24
  
25
  
26
  
27
  
28
  while (1)
29
  {    
30
    if (s_IO.ulLaufzeit == 0)
31
    {
32
      
33
      PORTB.OUTSET = PIN2_bm;
34
      PORTB.DIRCLR = PIN3_bm;
35
    }    
36
  }  
37
}
38

39

40
ISR(TCC1_OVF_vect)
41
{  
42
  static unsigned char ucMsTimer = 0;  
43
  
44
  
45
  if ( ucMsTimer >= 49 ) //51
46
  {
47
    ucMsTimer = 0;
48
  }
49
  else
50
  {
51
    ucMsTimer++;
52
  }
53
  
54
  if ( ucMsTimer == 0 )
55
  {
56
    if (s_IO.ulLaufzeit > 0)
57
    {
58
      s_IO.ulLaufzeit--;
59
    }
60
  }
61
}
Gast #4918149
Lesenswert?

Rufus Τ. F. schrieb:
> Takt richtig gesetzt? Auch die sogenannten "Fuses"?

ist ein ATxmega256A3BU dort wird der clock software mäßig eingestellt 
nicht über fuses wie beim mega...


läuft mit 32 Mhz
1
void clock_init (void)
2
{
3
  OSC.CTRL = OSC_RC32MEN_bm; //oscillator at 32 MHz
4
  while(!(OSC.STATUS & OSC_RC32MRDY_bm)); //wait for oscillator ready
5
  CCP = CCP_IOREG_gc; //protect I/O register, interrupts are ignored
6
  CLK.CTRL = CLK_SCLKSEL_RC32M_gc; //activate internal oscillator
7
}

Rufus Τ. F. schrieb:
> Wie ist das deklariert? Volatile?

ist eine Variable ausm struct

T_IO s_IO;



muss es unbedigt volatile sein ich veränder die Variable ja nicht 
außerhalb der ISR ?
#4918164
Lesenswert?

Wiz schrieb:
> Stefan E. schrieb:
>> Im Kommentar steht aber 4µS?
>
> stimmt kommentar ist falsch

4ms ist es offenkundig ja aber auch nicht.

Wiz schrieb:
> Tatsächlich wird die LED aber nach 6 sekunden auf rot geschaltet

Das über die Software-Zähler zurückgerechnet würde 20µs pro Interrupt 
bedeuten.

Für dich gilt es jetzt erst mal zu klären, mit welchem Takt der Zähler 
läuft, und mit welchem Abstand der Interrupt nun tatsächlich kommt.
Gast #4918167
Lesenswert?

Stefan E. schrieb:
> Das über die Software-Zähler zurückgerechnet würde 20µs pro Interrupt
> bedeuten.
>
> Für dich gilt es jetzt erst mal zu klären, mit welchem Takt der Zähler
> läuft, und mit welchem Abstand der Interrupt nun tatsächlich kommt.

wenn ich mir sysclock aufm pin ausgeben lasse dann messe ich mit dem 
oszi 32 Mhz als passt das schon mal der Timer hat den Prescaler 1 und 
der Top Wert ist 2 also läuft er mit 244 Hz... oder sehe ich das falsch?
#4918168
Lesenswert?

Und übrigens:

Wiz schrieb:
> muss es unbedigt volatile sein ich veränder die Variable ja nicht
> außerhalb der ISR ?

Ja, muss sie. Es spielt keine Rolle, wo sie verändert, und wo nur 
gelesen wird. Wenn sie sowohl in der ISR, wie auch außerhalb verwendet 
wird, muss sie volatile sein.
Ist aber nicht Ursache deines aktuellen Problems, denn dann würde sie 
nie, statt zu früh angehen.

Du hast aber auch ein Atomic-Problem, und das kann sehr wohl die Ursache 
sein.
Gast #4918183
Lesenswert?

Stefan E. schrieb:
> Jeder Zugriff auf s_IO.ulLaufzeit außerhalb der ISR muss atomar sein.

heißt es ich muss beim zugriff auf die Variable (auch beim 
Initialisieren und bei der If-Abfrage) die intterupts sperren??

Stefan E. schrieb:
> Kann ich nicht nachvollziehen. Was hast du denn da wo eingegeben, um auf
> diese 244Hz zu kommen?

siehe Anhang
Angehängte Dateien:
#4919298
Lesenswert?

Hi

Dein Timer muß 2x überlaufen und dann noch 0 Timer-Takte, damit Du auf 
Deine Zeiten kommst.

NICHT alle 2 Timer-Takte, sondern Überläufe (OVL).

Wobei dann die 6 Sekunden (statt 60 Sekunden) auch nicht hinkommen.
Die Total_Timer-Ticks sind die Timer-Durchläufe, bis die Zeit 
'abgearbeitet' ist - sind halt etwas mehr als 65536 (16 Bit), ziemlich 
genau sogar 2x so viel.

Trotzdem:
Etwas verworren, zur Zeit.

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