Forum: Mikrocontroller und Digitale Elektronik Atmel Timer1 nicht regelmäßig


von Benjamin (Gast)


Lesenswert?

Hallo ihr,
für ein Projekt verwende ich den Timer1 meines Atmega644p, um die Zeit 
seit Start einer Messung zu speichern. In der Messung werden 
nacheinander Daten von externen ADCs und Chips ausgelesen und auf eine 
SD Karte gespeichert. Das funktioniert auch recht fix mit 650 
Datenpunkten / Sekunde.

Nun mein Problem - die Zeit scheint manchmal für 4 Schleifendurchläufe 
den selben Wert zu haben und dann manchmal für 2 Schleifen oder auch nur 
eine. Ich dachte jedoch, dass der Timer1 bei richtiger Einstellung jeden 
Takt hochgezählt wird. Die Zeit wird im long run auch richtig gemessen, 
Fehler treten jedoch nun in den sehr kleinen Zeitabständen auf. Fällt 
euch ein, wo der Fehler liegen könnte, oder stoß ich hier tatsächlich 
schon an die Grenzen des Atmels ?

Hier noch der Code:
1
typedef union {  // union erlaubt einen effektiven, seperaten Zugriff auf Teile der Variable
2
        unsigned long i32;
3
        struct {uint8_t i8l;  // low
4
                uint8_t i8m;  // mid
5
    unsigned int high; // high, soft timer                
6
               };
7
              } convert32to8;
8
        
9
volatile uint16_t softtimer;
10
11
ISR(TIMER1_OVF_vect)     // Timer Überlauf
12
{ 
13
  ++softtimer;     // zählen der Überläufe
14
  //stdmsg("Overflow Int");
15
16
}
17
18
//returns elapsed time since chip started in ms
19
inline float time_ms()
20
{
21
  convert32to8 cap;     // Variablendeklaration
22
   
23
  cap.i8l = ICR1L;      // low Byte zuerst, high Byte wird gepuffert
24
  cap.i8m = ICR1H;
25
  
26
  cap.high = softtimer;  // obere 16 Bit aus Software Zähler
27
  //zeitdifferenz = cap.i32 - timestamp;
28
29
  return (cap.i32 / ( (float)F_CPU ) );
30
} 
31
32
33
void timer_init()
34
{
35
  //TIMER STUFF
36
  softtimer = 0;   // wird für Zeitdifferenzmessung nicht mal gebraucht,
37
          // denn Differenz geht auch über Überlauf bei Softtimer  
38
39
  // Timer1 initialisieren:
40
   TCCR1A = 0;    // normal mode, keine PWM Ausgänge
41
   
42
  TCCR1B = (1<<CS10);
43
        
44
   TIMSK1 = (1<<TOIE1) ;   // overflow und Input-capture aktivieren, Mega32: TIMSK
45
  
46
   sei();
47
}

von spess53 (Gast)


Lesenswert?

Hi

>  cap.i8l = ICR1L;      // low Byte zuerst, high Byte wird gepuffert
>  cap.i8m = ICR1H;

Hast du ein Input Compare Ereignis?

>The Input Capture is updated with the counter (TCNTn) value each time an >event 
occurs on the ICPn pin...

TCNT statt ICR.

MfG Spess

von Benjamin (Gast)


Lesenswert?

Hallo Spess,
vielen Dank für deine Antwort. Der Hinweis ist SEHR gut und ich werd es 
gleich morgen ausprobieren, hoffe es klappt. Ansonsten meld ich mich 
nochmal.
Vielen Dank nochmal.
Gruß
Benjamin

von Peter D. (peda)


Lesenswert?

Benjamin schrieb:
>
1
> typedef union {  // union erlaubt einen effektiven, seperaten Zugriff
2
> auf Teile der Variable
3
>

Da Du hinterher durch float teilst, brauchst Du Dir um Effizienz keine 
Sorgen mehr zu machen. Die Union reißt da nichtmal ein klitzekleines 
Promille raus.

Aber um race conditions mußt Du Dir wirklich Sorgen machen.
Ich hab da schonmal was vorbereitet:

Beitrag "AVR Timer mit 32 Bit"


Nochn Tip:
Der CPU ist es vollkommen wurscht, ob der Timertick 1ms oder sonstwas 
ist.
Erst zur Ausgabe an den Menschen muß man in s umrechnen. Das könnte dann 
einige float-Rechnungen einsparen.


Peter

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.