Forum: Mikrocontroller und Digitale Elektronik Schnelles Schalten mit Interrupt


von patrick b. (calalex)


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
}

von Fabian (Gast)


Lesenswert?

Was soll das?
1
cnt==0;
2
cnt++;

und was soll das?
1
while(cnt<0.0002) //Wenn zähler größer 200us, dh.kein neuer Puls dann
2
{
3
PORTA |= (1<<PA0)   //aktiviere PORTA PA0
4
5
}

von Georg G. (df2au)


Lesenswert?

cnt hast du als Integer definiert, also ganze Zahl. Du fragst aber auf 
0.0002 ab.

Du willst auf "größer" testen, schreibst aber "<"

Was soll das Statement c==0 bewirken?

(Dass das Konzept noch nicht schlüssig ist, lassen wir mal außen vor)

von Fabian (Gast)


Lesenswert?

Ich sehe nirgends einen Timer, den Du als Zeitbasis verwendest.

Außerdem: Wenn das Signal plötzlich schneller als 5kHz ist, ist es für 
dich okay?!

von H.Joachim S. (crazyhorse)


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.

von patrick b. (calalex)


Lesenswert?

Fabian schrieb:
> Ich sehe nirgends einen Timer, den Du als Zeitbasis verwendest.
>
> Außerdem: Wenn das Signal plötzlich schneller als 5kHz ist, ist es für
> dich okay?!

ja mich interessiert nur der Fall, ob im 5kHz Takt immer ein Signal 
kommt und wenn nicht, soll direkt PA0 geschaltet werden..

von Wusel D. (stefanfrings_de)


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?

von patrick b. (calalex)


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.

von M. N. (Gast)


Lesenswert?

Ohne Dich vom ATmega32 abbringen zu wollen, aber wenn Du nur diese eine 
Überwachungsfunktion brauchst, kann man dazu auch ein nachtriggerbares 
Monoflop (CD4538, 74HC4538) verwenden oder auf einen kleinen ATtiny 
zurückgreifen.

von patrick b. (calalex)


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
}

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.