RC-Reciever und das seltsame Timer Ergebniss

OP (Firma: Hobby) #2702677
Lesenswert?

Hallo,

ich kann mir vorstellen, dass einige bei den folgenden Fragen ihr Gehirn 
sehen und bitte um Verständnis. Ich versuche etwas noch nie da Gewesenes 
zu machen, nämlich einen RC-Reciever auszulesen und kann zumindest einen 
Teilerfolg bieten. Ich wundere mich über die Ausgabe des Timers.

Ich verwende einen ATMega16 mit einem 8MHz Quartz und einen analogen 
Futuba Reciever, angeschlossen an INT0. Derzeit versuche ich, zum 
lernen, nur ein Servosignal auzuwerten und nicht das Summensignal. 
Soweit klappt das auch, doch der Timer gibt mir nicht das gewünschte 
Ergebniss auf meinem LCD aus. Die Fuses habe ich mit _delay_ms(1000) und 
LEDs getestet. Das übliche Servosignal ist 1ms – 2ms.

Hier meine (ausführliche) Rechnung:
8000000 Hz / 64 prescaler = 125000 Schritte pro Sekunde
1 sek / 12500 Schritte * 1000 = 0,008 ms pro Schritt
1 ms / 0,008 ms pro Schritt = 125 Schritte
2 ms / 0,008 ms pro Schritt = 250 Schritte
Auflösung: 125

Bei 1 ms erwarte ich also ein Countervalue (TCNT1) von 125 und bei 2 ms 
250. (Timer0 würde also ausreichen)

Auf dem LCD lese ich aber +/- 5:
1ms = 18608  (Knüppel unten)
1,5ms = 18680  (Knüppel mitte)
2ms = 18760  (Knüppel oben)

Bitte schaut euch dazu meinen Code an:
1
#define F_CPU 8000000UL
2

3
#include <avr/io.h>
4
#include "lcd-routines.c"
5
#include <avr/interrupt.h>
6
#include <stdlib.h>
7

8
//volatile uint16_t starttime = 0;
9
volatile uint16_t signal1 = 0;
10
volatile uint8_t edge_switch=0;
11

12
ISR(INT0_vect) {
13
  if(edge_switch == 0){
14
    //starttime = TCNT1;
15
    TCNT1 = 0;
16
    edge_switch = 1;
17
    MCUCR |= (0<<ISC00);          //Fallende Flanke
18
  }
19
  else{
20
    //signal1 = TCNT1 - starttime;
21
    signal1 = TCNT1;
22
    edge_switch = 0;
23
    MCUCR |= (1<<ISC00);          //Steigende Flanke
24
  }
25
}
26

27
void lcd_string_int(uint16_t tmp_int){
28
  char buffer[20];
29
  utoa(tmp_int, buffer, 10);
30
  lcd_string(buffer);
31
}
32

33
int main(void){
34
  GICR |= (1<<INT0);                     //INT0 enable
35
  MCUCR |= ((1<<ISC01) | (1<<ISC00));    //Steigende Flanke
36
  TCCR1B = ((1<<CS10) | (1<<CS11));      //Prescaler 64
37
  
38
  lcd_init();
39
  sei();
40
  
41
  while(1){
42
    lcd_clear();
43
    lcd_string_int(signal1);
44
    _delay_ms(1000);
45
  }
46
}

1) Kann jemand erkennen wo mein Fehler liegt?
2) Habe ich mich verrechnet?
3) Sind die Einstellungen richtig?
Persönliche Seite #2702795
Lesenswert?

Max Durst schrieb:
> MCUCR |= ((1<<ISC01) | (1<<ISC00));    //Steigende Flanke

Ich weiss nicht, ob das die Ursache ist, aber du setzt MCUCR an 
verschiedenen Stellen, auch in der ISR. Dort ver-oder-st du auch, also 
ändert das nichts an der Konfiguration.

MCUCR scheint mir etwas exotisch zu sein, passt da nicht eher EICRx 
(kuck nohcmals in Datenblatt).

Jedenfalls feuert die ISR bei beiden Flanken, und du weisst nicht, ob du 
gerade die steigende oder fallende beobachtet hast, das könnte eine 
Fehlerquelle sein.
#2702907
Lesenswert?

Max Durst schrieb:
> Danke vielmals. Habe die Zeile geändert und jetzt geht es.
>
1
> MCUCR ^= (1<<ISC00);
2
>

Kann man machen. Persönlich würdeich aber

  MCUCR &= ~( 1<<ISC00);

vorziehen.
Ich finde das klarer, dass hier das Bit dezidiert gelöscht werden soll. 
Bei deiner Lösung muss man ständig im Hinterkopf halten, dass es im 
anderen Zweig gesetzt wird um zu wissen, was hier eigentlich 
beabsichtigt ist.

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