AVR-Timer zählt negativ?

OP #1576935
Lesenswert?
• ▲
▼
Hi,

ich muss für ein Projekt den Timer benutzen. Ansich soll die 
ICP-Funktion genutzt werden. Die Register zu laden geht offenbar, nur 
stürzt der Timer nach 9 Durchläufen ab und startet das Hauptprogramm 
neu.

In der Ausgabe äußert sich das so, dass nach 9 Durchläufen wieder mit 
"1" und "2" begonnen wird.

Zum Debuggen habe ich entsprechend Marken bzw. Timer-Ausgaben in den 
Code eingebunden und war dann sehr überrascht, dass auf einmal "-2631" 
ausgegeben wurde. Möglicherweise ist es auch nicht richtig formatiert 
etc., an dem Programm sitze ich schon ein paar Stunden und da kommen 
öfter Fehler rein als raus.

Grundsatzfrage: kann ich das so laufen lassen, wie es aussieht, oder 
muss ich, um das ICP-Ereignis auszuwerten über die ISR gehen?

Was mir auch komisch vorkommt: immer nach 9 Ausgaben bricht er ab und 
startet ja offenbar main neu, da entsprechende Marken wieder erscheinen. 
Hängt das vielleicht mit einem Overflow zusammen? - So weit ich dem 
Datenblatt entnommen habe setzt das den Timer, nicht aber den AVR 
zurück. Auf Overflow zu "warten" hat dann kein Sinn, denn sobald das 
Flag gesetzt wird, startet das Programm neu und damit kann ich wenn das 
TOV1 aus  TIFR1 gelesen wird nichts mehr machen.

1
#include <stdlib.h>
2
#include <avr/io.h>
3
#include <avr/interrupt.h>
4
#include <avr/signal.h>
5
#include <avr/pgmspace.h>
6
#include <util/delay.h>
7
#include "uart.h"
8

9

10
#define UART_BAUD_RATE      38400
11

12

13
int main(void)
14
{
15

16
uint16_t timerinhalt =0; //fuer ICP-Timer
17

18
uint16_t timerinhalt2 =0; //fuer normalen Timer
19
char timer[6]; //5 Ziffern + \0
20

21
// Richtungsdefinitionen:
22
 DDRB = 0;        // Alles Eingänge, PB0 ist ICP
23
 PORTB = 0xFF;    // Pullups an Eingängen
24
 DDRC = 0xFF;     // Port C als Ausgang
25

26

27
 uart_init( UART_BAUD_SELECT_DOUBLE_SPEED(UART_BAUD_RATE,F_CPU) );
28
 sei();
29

30
 uart_puts("1");
31

32
// Timer1-Init:
33
 TCCR1A = 0x00;                      // normaler Modus
34
 TCCR1B = (1<<CS12) | (1<<CS10) | (1 << ICES1);    // ICP auf steigende Flanke
35
 TIMSK1 = (1<<TOIE1) | (1<<ICIE1);   // ICP und Overflow aktivieren
36

37
 uart_puts("2");
38

39

40
 for(;;)
41
 {
42

43
    timerinhalt = ICR1L;  //lese vom ICP-Timer
44
    timerinhalt += (ICR1H<<8);
45

46
    timerinhalt2 = TCNT1L; //lese vom normalen timer
47
    timerinhalt2 += (TCNT1H<<8);
48

49
  if (TIFR1 & (1<<ICF1)) // wenn ICP ausgeloest
50
   {
51
    uart_puts("3");
52

53
    if (timerinhalt > 0) //und Zeit nicht gerade "0"
54
     {
55
       uart_puts("6");
56
     }
57
    }
58
  else { itoa(timerinhalt2, timer, 10); //sonst gebe aktuellen Timer-wert aus
59
         uart_puts(timer);
60
         uart_putc( "\n");
61
         _delay_ms(1000);}
62

63
 }
64
}
#1576957
Lesenswert?
• ▲
▼
Zu den Interrupts wurde alles Nötige schon gesagt,  Du darfst einen 
Interrupt nur dann erlauben, wenn es eine Routine dafür gibt.  Sonst 
gibt es Reset.

Die negative Zahl ergibt sich aus itoa(), das eine int erwartet.  Du 
aber willst eine unsigned int ausgeben.  3mal darfst Du raten, wie die 
Funktion dann heißt.
Gast #1577337
Lesenswert?
• ▲
▼
> Ah, danke, das wusste ich nicht, dass Interrupts explizit definiert
> werden müssen, wenn sie verwendet werden sollen.

Ach so, was ich vergessen hab: Es ergibt keinen Sinn, einen Interrupt 
verwenden zu wollen, ohne einen dazugehörigen Handler zu schreiben, denn 
der Aufruf dieses Handlers ist ja der Zweck des Interrupts.

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