Schnelles Schalten mit Interrupt

#3164071
Lesenswert?

Hallo, ich würde gerne 5kHz Pulse überwachen und falls einer ausfällt 
sofort einen Ausgang schalten. Dafür hab ich den Atmega32 ausgewählt. 
Ich hab mir überlegt, dass die Pulse am INT0 angelegt werden, durch die 
steigende Flanke wird der Interrupt ausgelöst und dort soll ein Zähler 
starten, kommt die nächste Flanke soll der Zähler wieder auf 0 
zurückgesetzt werden, fehlt die nächste Flanke allerdings, und der 
Zähler überschreitet 200us, soll der Port PA0 auf high geschaltet 
werden.

kann ich das wie folgt umsetzen?
wie genau zählt der Timer?
gibt es vielleicht eine bessere Möglichkeit?
hab den code noch mit keinem simulator geprüft..

vielen Dank für Feedback!
1
#include <stdint.h>
2
#include <avr/io.h>
3
#include <avr/interrupt.h>
4

5
voltaile uint16_t cnt=0;
6

7
ISR(INT0_vect)
8
{
9
cnt==0;
10
cnt++;
11
} 
12

13

14
int main (void){ 
15

16
DDRD &= ~(1<<2);   //PD2 als Eingang
17
PORTD|= (1<<2);   //Pullup aktivieren
18
DDRA = (1<<DDA0);  //PA0 als Ausgang
19

20
MCUCR |= ((1<<ISC01)|(1<<ISC00)); //interrupt bei steigender Flanke an INT0
21
GICR = (1<< INT0);    //IRQ an INT0 aktivieren
22

23
sei();       //Interrupts global aktivieren
24

25
while(cnt<0.0002) //Wenn zähler größer 200us, dh.kein neuer Puls dann
26
{
27
PORTA |= (1<<PA0)   //aktiviere PORTA PA0
28

29
} 
30

31
return 0;
32

33
}
#3164086
Lesenswert?

naja, mit 0.002 wird das nichts :-)

Grundsätzlich würde ich das auch so ähnlich machen, die Auswertung aber 
mit dem Output-compare des Zählers.
Angenommen, der Zähler zählt in 1µs-Takten:

OCR auf 200, wird der Zählerstand erreicht hast du deine Aktion 
(entweder direkt mit Hardware (clear oder set on compare, bist damit 
aber auf feste Pins angewiesen) oder mittels OCR-Interrupt.
Der externe Trigger setzt den Zähler immer wieder auf 0, so dass der 
compare-Wert normalerweise nie erreicht wird.
#3164219
Lesenswert?

Wenn nur auf die Impulse reagierst, passiert nichts, wenn die Impulse 
ausbleiben.

Irgenwo musst Du noch prüfen, ob ein Impuls fehlt. Das wirft die Frage 
auf: Was genau heisst, ein Impuls fehlt? Wenn der erste Impuls heute 
kommt, und der nächste morgen, wann willst Du feststellen, dass ein 
Impuls fehlt?

Ein Beispiel, wie man die Aufgabe klarer fomulieren könnte:

Eine Leitung liefert positive Impulse mit normalerweise 5khz Frequenz. 
Die Frequenz darf beliebig höher sein aber maximal 10% niedriger.
Es soll ein Alarm ausgelöst werden, wenn für eine Zeitdauer von mehr als 
0,22ms keine steigende Flanke mehr vorliegt.

Entspricht das deiner Anforderung?
#3164242
Lesenswert?

ja das ist so klarer formuliert. meine idee war halt die, dass es einen 
timer gibt der hochzählt und durch jeden neuen puls, wieder auf 0 
gesetzt wird, tritt dieser nicht ein, soll wenn der Timer einen Wert von 
0,22ms zb hat der port aktiviert werden.. die Idee mit dem OCR find ich 
gut, ich versuche den code umzuschreiben.
#3172717
Lesenswert?

hallo, ich hab den Code verändert und bin auf Feedback gespannt, ob er 
nun mehr Sinn ergibt!
Bei jeder Flanke soll der Timer auf 0 gesetzt werden, anschließend 
hochgezählt werden, sofern dann der compare Wert erreicht wird, soll PA0 
aktiviert werden. Kommt vorher die nächste Flanke, wird der timer wieder 
rechtzeitig zurückgesetzt. So meine Theorie.
Vielen Dank für nützliches Feedback!
1
#ifndef F_CPU
2
#define F_CPU 16000000UL
3
#endif
4

5
#define IN_PORT  PORTD
6
#define IN_DDR  DDRD
7
#define IN_PIN  PD6
8

9
#define OUT_PORT  PORTA
10
#define OUT_DDR    DDRA
11
#define OUT_PIN    PA0
12

13
#include <avr/io.h>
14
#include <util/delay.h>
15
#include <avr/interrupt.h>
16

17

18
ISR (TIMER1_COMPA_vect)
19
{
20
  PORTA |=(1<<PA0);          // falls kein Puls PA0 aktivieren
21
}
22

23
ISR(INT0_vect)
24
{
25
    TCCR1B |= (1 << WGM12)|(1 << CS10);    // timer setzen, ohne prescale
26
    TCNT1 = 0;                // counter init
27
    OCR1A = 3199;              // compare modus init: flck=16MHz => tclk=62.5ns,
28
                        // 200ns Pause + 20ns Toleranz = 220ns
29
                        // 220ns/62.5ns =3200 Zählschritte -1 = 3199
30
    TIMSK |= (1 << OCIE1A);          // compare modus aktivieren
31
  
32
}
33

34
int main(void)
35
{
36
  
37
  DDRD &= ~(1<<PD2);         //PD2 als Eingang
38
  PORTD|= (1<<PD2);         //Pullup aktivieren
39
  DDRA = (1<<PA0);        //PA0 als Ausgang
40
  
41
  sei();              //global interrupts
42
    
43
                
44
  MCUCR |= ((1<<ISC01)|(1<<ISC00));    //interrupt bei steigender Flanke
45
  GICR |= (1<<INT0);            //interrupt modus aktivieren
46
  
47
  
48
  
49
  
50
  while(1)
51
  {
52
    
53
  };
54
  
55
}

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