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
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)
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.
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..
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?
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.
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.
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
intmain(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