Forum: Mikrocontroller und Digitale Elektronik Interrupt-Zeitdauer


von Paul (Gast)


Lesenswert?

Hallo zusammen,

ich bin gerade dabei, mit meinem Mikrocontroller Infrarotsignale zu 
empfangen. Ich benutze dazu einen ATMEGA16 16PU mit internem Quarz, der 
auf 4 Mhz eingestellt ist. Die verwendete LG-Fernbedienung sendet im 
NEC-Format, das am Anfang aus einem 9ms High-Pegel und einem 4,5ms 
Low-Pegel besteht und anschließend 32 Bit überträgt, die alle jeweils 
mit einem 562,5µs High-Pegel beginnen und dann abhängig vom übertragenen 
Bit entweder mit einem ebenfalls 562,5µs Low-Pegel (Bit = 0) oder einem 
1687,5µs Low-Pegel (Bit = 0) enden.
Um diese Signale abzufangen, habe ich einen Prescaler von 1 eingestellt.
Das Timer_Register TCNT0 hatte ich auf -10 eingestellt, um die 
Flankenwechsel so schnell wie möglich detektieren zu können und die 
Genauigkeit des internen Quarzes zu testen. In einem Array habe ich die 
Anzahl der Overflow-Triggerungen während eines Signals gespeichert. Der 
erste Wert gehört quasi zur Wartezeit, der erste zu der Anzahl der 
Overflow-Trigger während des 9ms High-Pegels usw.
Ich würde erwarten, dass bei dieser Konstellation die Anzahl der 
Overflow-Triggerungen bei 0,009s * 4000000Hz / 10 = 3600 liegt.
Es werden allerdings nur 400 Overflow-Triggerungen für den 9ms 
High-Pegel gemeldet, die zusätzlich nicht mit einer Veränderung von 
TCNT0 bis über 50 variiert. Kann mir jemand erklären woher das kommt. 
Dauert die Interrupt-Routine zu lange? Kann der Sensor nicht mehr (TSOP 
4838)?
1
#define XTAL      1e6
2
#define F_CPU      XTAL
3
4
#include <avr/io.h>
5
#include <util/delay.h>
6
7
unsigned char i_lo;  // intermediate storage variable
8
unsigned char nec_bit;
9
int16_t timeArray[70];
10
int16_t iCounter;
11
static int16_t time;
12
13
int main (void)
14
{
15
  mode = NONE;
16
  DDRB = 0xFF;
17
  DDRB = ~(1 << PB0);    
18
19
  TIMSK |= (1<<TOIE0);  // output compare A match interrupt            
20
  TCCR0  = (1 << CS00);  // prescaler 1
21
  TCNT0  = 0;
22
                      
23
  while(1)         
24
  {
25
                cli();
26
    i_lo = RemCo_data;
27
    sei();
28
  }
29
  return 0;
30
}
31
32
ISR (TIMER0_OVF_vect)
33
{    
34
  TCNT0 = -10;
35
36
  time++;
37
38
  if((nec_bit ^(!PINB & (1 << PB0))) & 1)          // edge detection @ PB0
39
  {
40
41
    nec_bit = ~nec_bit;  // toggle bit
42
43
    timeArray[iCounter] = time;
44
    iCounter++;
45
    if(iCounter > 67)
46
      nec_bit = 0;
47
    time = 0;
48
  }
49
}

Viele Grüße
Paul

von holger (Gast)


Lesenswert?

TCNT0 = -10;

Was ist das denn für ein Blödsinn?
Ein Counter kann keine negativen Werte.

von Markus W. (Firma: guloshop.de) (m-w)


Lesenswert?

holger schrieb:
> TCNT0 = -10;
>
> Was ist das denn für ein Blödsinn?
> Ein Counter kann keine negativen Werte.

Doch, kann er - quasi. -10 wird als 246 interpretiert und erzeugt 
dadurch einen Overflow-Interrupt nach 10 Takten.

Ich bin mir aber nicht sicher, ob ein Timer-Interrupt hier das Mittel 
der Wahl ist, um das Signal abzutasten. Man könnte auch den Timer 
dauernd laufen lassen - als Zeituhr - und die Flankenwechsel per 
Pin-Change-Interrupt erkennen. Dann "interruptet" der Mikrocontroller 
ein bisschen weniger und kann nebenher noch andere sinnvolle Aufgaben 
erledigen.

von Karl H. (kbuchegg)


Lesenswert?

holger schrieb:
> TCNT0 = -10;
>
> Was ist das denn für ein Blödsinn?
> Ein Counter kann keine negativen Werte.

Blödsinn schon, aber nicht die -10 (also von der Idee der negativen 
Zahlen her)

Wie soll denn bitteschön der µC bei ganzen 10 Takten die du ihm Zeit 
gibst (wegen Prescaler 1) die ISR abarbeiten? Das dein Zahlen hinten und 
vorne keinen Sinn ergeben, wundert mich nicht.

Für dieses Timing brauchst du doch die zeitliche Auflösung überhaupt 
nicht.

>  und die Genauigkeit des internen Quarzes zu testen.
Da wirst du Pech haben. So etwas hat dein µC gar nicht.

von Peter D. (peda)


Lesenswert?

Um die 500 und 1600µs zu unterscheiden, reicht eine Zeitbasis von z.B. 
100µs dicke aus (400 Zyklen bei 4MHz).


Peter

von Paul (Gast)


Lesenswert?

Hallo zusammen,

viele Dank für die Antworten.

Karl Heinz Buchegger schrieb:
>>  und die Genauigkeit des internen Quarzes zu testen.
> Da wirst du Pech haben. So etwas hat dein µC gar nicht.
Stimmt, ich meinte den internen RC-Oszillator.

Karl Heinz Buchegger schrieb:
> Wie soll denn bitteschön der µC bei ganzen 10 Takten die du ihm Zeit
> gibst (wegen Prescaler 1) die ISR abarbeiten? Das dein Zahlen hinten und
> vorne keinen Sinn ergeben, wundert mich nicht.
Genau das war ja auch meine Frage.

Markus W. schrieb:
> Ich bin mir aber nicht sicher, ob ein Timer-Interrupt hier das Mittel
> der Wahl ist, um das Signal abzutasten. Man könnte auch den Timer
> dauernd laufen lassen - als Zeituhr - und die Flankenwechsel per
> Pin-Change-Interrupt erkennen. Dann "interruptet" der Mikrocontroller
> ein bisschen weniger und kann nebenher noch andere sinnvolle Aufgaben
> erledigen.
Das ist eine gute Idee, daran hatte ich noch nicht gedacht.

Peter Dannegger schrieb:
> Um die 500 und 1600µs zu unterscheiden, reicht eine Zeitbasis von z.B.
> 100µs dicke aus (400 Zyklen bei 4MHz).
Das stimmt natürlich, aber ich wollte primär die mögliche Zeitauflösung 
des Mikrocontrollers testen.

Viele Grüße
Paul

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.