Mega16 Timer-Start/Stop für Geschwindigkeitsmessung

Gast #1613247
Hallo zusammen,
ich versuch mich schon seit Tagen an einer Geschwindigkeitsmessung mit 
einem mega16.
Es soll die Geschwindigkeit auf 5m berechnet und per rs232 aufn PC 
gegeben werden, allerdings wird hier nur 0.0000000 oder 65536.000 
gesendet...
Timer-Start mit PD2, Stopp mit PD3.
Auch nach einschlägigen Tipps hab ich nen Gerhirnknoten.
Kann mir jemand die betreffende Stelle coden?
Danke schonmal für die Hilfe,
Felix
1
  
2

3
volatile unsigned int  millisekunden;
4
volatile unsigned int sekunden;
5
volatile float geschw;
6
volatile unsigned int i;
7

8

9

10
int uart_putc (volatile char c)        
11
{
12
      while (!(UCSRA & (1<<UDRE)))  //warten 
13
    {
14
    }
15
 
16
    
17
 
18
    UDR = c;                      //senden
19
    return 0;
20
}
21

22

23
void uart_puts (char *s)   //string senden
24
{     
25
while (*s)     
26
  {   
27
   uart_putc(*s);         
28
   s++;     
29
  } 
30
}
31

32

33

34

35
int main(void)
36
{
37

38
 UCSRB |= (1<<TXEN);                // UART einschalten
39
    UCSRC |= (1<<URSEL)|(3<<UCSZ0);   
40
 
41
    UBRRH = UBRR_VAL >> 8;
42
    UBRRL = UBRR_VAL & 0xFF;
43
 DDRD &= ~(1 << PD3);
44
 DDRD |= (1<<PD5);
45
 int i;
46
 
47

48
  while(1)
49
  {
50
     
51
  
52

53
if (PIND & (1<<PD2))
54
{
55
// Global Interrupts aktivieren
56
  sei();
57
  // Timer 0 konfigurieren
58
  
59
  TCCR0 |= (1<<CS00)|(1<<CS01)|(1<<WGM01); // Prescaler 64 
60
  
61
  OCR0 = 250-1; 
62
 
63
 
64
TIMSK |= (1<<OCIE0);
65
}
66

67

68
if (PIND & (1<<PD3))
69
{
70
   
71
  
72
  geschw = 5 / ((millisekunden + sekunden*1000) * 3600) ;   //Ber.
73
  TIMSK &= ~(1<<OCIE0);
74
  cli ();
75
  
76
   char s[8]; 
77
   dtostrf( geschw , 6, 3, s ); 
78
   uart_puts( s );
79

80

81

82

83
  for (i=0;i<5;i++)
84
   {
85
   PORTD |= (1<<PD5);
86
   _delay_ms(100);                    //StatusLed
87
   PORTD &= ~(1<<PD5);
88
   _delay_ms(100);
89
   }
90
  }
91
  }
92
          }
93
   
94

95
// Compare Interrupt Handler 
96

97
ISR (TIMER0_COMP_vect)
98
{
99
  millisekunden++;
100
  if(millisekunden == 2000)
101
  {
102
    sekunden++;
103
    millisekunden = 0;
104
   
105
  }
106
}
Persönliche Seite #1613301
> volatile unsigned int millisekunden;
> volatile unsigned int sekunden;
> volatile float geschw;

Ändere diese Berechnung damit es keinen Integer-Überlauf gibt:

>   geschw = 5 / ((millisekunden + sekunden*1000) * 3600) ;   //Ber.

Z.B. Float Ergebnis = Float Zähler / Unsigned long Nenner

>   geschw = 5.0 / ((millisekunden + sekunden*1000UL) * 3600) ;   //Ber.
                                                  ^^

Die Berechnung kannst du mit gutem Gewissen nach dem Abschalten des 
Timers machen, dann brauchst du dich auch nicht um atomaren Zugriff auf 
millisekunden und sekunden zu kümmern (s. AVR-GCC-Tutorial Variablen 
> 1 Byte). geschw braucht nicht volatile zu sein.

Die Berechnung könntest du bei diesem Verfahren geringfühig genauer 
machen, wenn du den angebrochenen Zählerstand im TCNT0 Register 
berücksichtigst.

Vor dem Start des Timers würde ich noch millisekunden und sekunden 
nullen, wenn mehrere Messungen gemacht werden sollen.

Und ich würde dann auch Umordnen:
1
  // Timer 0 konfigurieren
2
  TCCR0 |= (1<<CS00)|(1<<CS01)|(1<<WGM01); // Prescaler 64 
3
  OCR0 = 250-1; 
4

5
  while(1)
6
  {
7
    if (PIND & (1<<PD2)) // *** Start ***
8
    {
9
      millisekunden = 0;
10
      sekunden = 0;
11
      TCNT0 = 0;
12
      TIMSK |= (1<<OCIE0);
13
      sei();
14
    }
15

16
    if (PIND & (1<<PD3)) // *** STOPP ***
17
    {
18
      cli ();
19
      TIMSK &= ~(1<<OCIE0);
20

21
      // Berechnen...
22
      geschw = 5.0 / ((millisekunden + sekunden*1000UL) * 3600) ;
23

24
      // Ausgabe...
25
      // ...
26
    }    
27
  }
28
}

Antwort schreiben

Eine eigene Frage? Dieser Thread ist über 16 Jahre alt. Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.

Neuen Thread starten

Eine Lösung, Ergänzung oder Rückmeldung zu diesem Thread? Dann antworte hier.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.