Hallo, hab folgendes Problem: möchte mit meinem 90S4433 bei zwei Signalen jeweils die Abstände zwischen zwei steigenden Flanken "parallel" erfassen. So parallel ,dass man sie mehr oder weniger gleichzeitig auf einem LCD Display anzeigen kann. Jetzt hab ich nur einen Pin für Timer Capture :-( Signal 1 läuft an dem Port und es klappt bestens. Ein schnelles Umschalten zwischen den Signalen per Multiplexer klappt nicht (weiss nicht warum).Jetzt dachte ich mir für das zweite Signal: lass den Timer0 laufen , löse einen externen Interrupt bei steigender Flanke von Signal2 aus, sichere den Zählerstand und fertig. Klappt aber auch nicht :-( Hat jemand eine Idee wie man die zwei Signale doch messen kann ? Danke, Maciek
das klappt schon mit dem externen Int. Auch kannst du dafür Timer1 nehmen, wenn du ihn durchlaufen lässt. Der externe Int liest den Zählerstand des Timer1 und schreibt den in eine Variable, beim nächsten wird wieder der Zählerstand gelesen und die Differenz der beiden Werte ist die Zeit zwischen den Ereignissen. Genauso verfährst du beim ICP-Int, nur dass nicht der Zählerstand, sondern das ICP-Register gelesen wird. Differenz bilden, fertig. Solange der Timer max. 1mal überläuft, brauchst du dich auch darum nicht kümmern, das Ergebnis stimmt. Für längere Zeiten kannst du auch die Timer1-OV mitzählen und so aus der 16bit-Zahl eine 24bit-Zahl machen (oder auch noch mehr bei Bedarf). Die Zeit, die von EX0 bis zum tatsächlichen Lesen der Zählerstandes vergeht (Anspringen der ISR, Sichern von Registern/PSW, Lesen des Zählers) verursacht keinen Fehler, da jedesmal diesselbe Verzögerung entsteht. Kritisch kann es dann werden, wenn während des EX0-Ereignisses ein anderer Int läuft, dann wird eine längere Zeit gemessen.
Hallo Maciek, Welche Zeit vergeht zwischen den Signalflanken, Ist die Zeit kleiner als 20 Takte kannst du das IMHO vergessen. ansonsten: ICP = Signal1 XOR Siganl2 Digitalpin = Signal1 Jetzt kannst du am Digitalpin die Flankenrichtung bestimmen und am ICP erhälst du einen Impuls. In der ISR des ICP wertest du einmal die Steigende und einmal die fallende Flanke aus und bildest die Differenz. @horse Der ISR-Aufruf dauert nicht immer gleich lang, durch die unterschiedliche Ausführungszeit der verschiedenen Befehle entsteht ein fehler von +-3 Takten. mfg werner
vom Aufruf bis zum Lesen dauert es immer gleich lang, ein Fehler kann entstehen, bis der Aufruf erfolgt, insofern hast du recht, +-3 Takte stimmt aber nicht, sondern 1-3 Takte. Aber wollen wir mal keine Erbsen zählen.
@horse Ich denke die +- 3Takte sind für eine Zeitmessung richtig. Die AVR-Befehle dauern zwischen 1 und 4 Takten. folgende Fälle sind möglich: INT0 INT1 Fehler 1. Flanke +1Takte, 2. Flanke +1Takte Durchschnitt 2. Flanke +4Takte, 2. Flanke +1Takte -3 Takte 3. Flanke +1Takte, 2. Flanke +4Takte +3 Takte 4. Flanke +4Takte, 2. Flanke +4Takte Durchschnitt Bei der Verwendung von ICP für die eine und einem normalen Interrupt für die andere Flanke geb ich dir recht: 0-3 Takte Fehler zwischen verschiedenen Messungen. Ist natürlich Erbsenzählerei, aber wenn wir schon dabei sind: Muß man eigentlich nicht sogar noch einen oder gar zwei Takte dazuzählen weil das Ereignis ja sowohl am Anfang des uC-Taktes als auch am Ende des uC-Taktes auftreten kann? uC_clk: 000000000000111111111111111100000000000001111111111 Ereignisübernahme: ^^^^ ^^^^ event1: 000000000011111111111111111111111111111111111111111 event2: 000000000000001111111111111111111111111111111111111 event2 wird erst einen Takt später übernommen, obwohl Die Differenz zwischen event1 und event2 nahezu null werden kann. PS: Dieser Fehler tritt auch bei der ICP Methode auf. mfg werner
Hallo, danke für die Antworten ,werde ich gleich ausprobieren. Wenn noch jemand Lust hat : Wieso klappt das hier nicht? Es soll bei jedem Interrupt der Zählerstand gesichert werden. Die Interrupts kommen abwechselnd von zwei verschiedenen Signalen (maximal 160Hz).Zwischen den Signalen wird mit einem MUX gewechselt. Kommt ein Interrupt, so werden die Interrupts erstmal global abgeschaltet ,eine Berechnung durchgeführt ,der MUX auf das andere Signal geschaltet und die Interrupts global wieder angeschaltet. So immer hin und her.Der Mux arbeitet richtig. In der Praxis klappt es nicht. Es werden abenteuerliche Werte angezeigt ,die ich mir überhaupt nicht erklären kann. So ändert die Variable für Signal2 ihre Werte obwohl Signal2 keinen Interrupt ausgelöst hat. Bin ratlos ,probiere jetzt mal Eure Tipps. Grüsse, Maciek SIGNAL(SIG_INPUT_CAPTURE1) { TIMER_L = TCNT1L; // Unteren Bits des Zählers retten TIMER_H = TCNT1H; // Oberen Bits des Zählers retten TCNT1H=0; TCNT1L=0; // Zähler auf Null setzen interrupt=1; overflow=0; // Kein overflow } . . . while(1) { if(interrupt) { asm volatile("cli"); // Interrupt global aus if(bit_is_set(PORTB,2)) // MUX Pin1 { RPM = (unsigned int)(60*(31250/(float)((TIMER_H*256)+TIMER_L))); outp (0x03,PORTB); // MUX auf Pin0 schalten delay50us(); } else // MUX Pin0 { KMH = (unsigned int)(62500/(float)((TIMER_H*256)+TIMER_L)); outp (0x07,PORTB); // MUX auf Pin0 schalten delay50us(); } interrupt = 0; asm volatile("sei"); // Interrupt global an } . . .
Hallo nochmal, habs jetzt mit dem externen interrupt (INT1) versucht. Geht nicht :-( Hab probeweise an ICP gemessen und dann an INT1 (mit nur einem Signal) Die Interruptroutinen machen in beiden Fällen das gleiche. Die Messung an ICP klappt an INT1 bekomme ich abwechseln ca 25500 und 9200. Wenn das an INT1 klappen würde gäbe es doch keinen Unterschied zu pin ICP. Ist INT1 vielleicht langsamer ? Tips? Ich probier jetzt noch den zweiten Tip mit dem XOR. Den Digitalpin brauche ich am festzustellen welches Signal grade anklopft , oder ? Nur , wie kann ich mir das merken ,wenn gleichzeitig ein Interrupt kommt und kurz danach der Impuls wieder weg ist? Grüsse, Maciek
Hallo Maciek, [2 Signale mit 160 Hz] mir scheint wir haben uns mißverstanden: Du willst 2 Frequenzen von 2 verschiedenen Signalen messen? Ich habe verstanden, du willst die Differenz zwischen 2 Signalflanken messen. Also Flanke Signal1 bis Flanke Signal2. Du solltest dir Gedanken über deinen Programmablauf machen. Ich zeichne das mal auf: Signal1: _______----------------__________________----------- Signal2: ____________-----------------_________________------- Beschr:_________1_2__3_____A______________________4_5__6_____ Der Multiplexer steht auf Signal1. 1. - Durch die Steigende Flanke wird TCNT1 in die ICR1 Register kopiert. - In deiner ISR kopierst du TCNT1 in die TIMER-Variable, löschst TCNT1, interrupt wird gesetzt. Welcher Wert steht eigentlich in TIMER? TIMER enthält die Zeit die seit dem letzten Löschen vergangen ist (steigende Flanke von Signal2 bis steigende Flanke Signal1). 2. Wir haben die ISR verlassen und sind jetzt im Hauptprogramm. - Du deaktivierst alle Interrupts. - Du berechnest RPM (bist du sicher das TIMER den Wert enthält den du haben wolltest? s.o.) - Du schaltest den Mux auf Signal2 um. - Du aktivierst alle Interrupts Was würdest du sagen, wieviel Zeit ist seit dem Zeitpunkt 2 vergangen? Du hast immerhin eine höchst komplizierte Berechnung mit float durchgeführt. Sind wir auf der Zeitachse noch for (3) oder schon etwa bei (A)? Angenommen wir sind bereits bei (A)? Und du hast die Interrupts reaktiviert. Das Interrupt Flag ist ist zum Zeitpunkt (3) gesetzt worden und die ISR Routine wird zum Zeitpunkt (A) ausgeführt. Damit enthält TIMER den wert, der zwischen (1) und (A) vergangen ist. Den Rest kannst du ja selber durchspielen. uint16_t timer SIGNAL(SIG_INPUT_CAPTURE1) { if (interrupt) return; if (ERSTEFLANKE) timer= ICR1; /* Wert speichern */ ERSTEFLANKE=0; else { timer= ICR1-timer /* Zeitdifferenz ermitteln */ interrupt=1 ERSTEFLANKE=1; } }; while(1) { if(interrupt) { INTERRUPT ABSCHALTEN; if (MUX_AUF_SIGNAL1){ RPM = (uint32_t) 60*31250/timer; MUX_AUF_SIGNAL2; } else { KMH = (uint32_t) 62500/timer; AUF_MUX1_UMSCHALTEN; } ICP_INTERRUPT LÖSCHEN; interrupt = 0; asm volatile("sei"); // Interrupt global an } }
Hallo Werner, vielen Dank ,dass du dir die Mühe gemacht hast :-) Jetzt sehe ich auch ,dass mein Programm nicht laufen konnte. Kommt davon wenn man sich freut ,dass es mit einem Signal funktioniert und nicht merkt ,dass es eigentlich Zufall war ;-) Ich hatte den Timer und den Interrupt gar nicht verstanden... Werde morgen mal meine Signalquelle bemühen (ist ein Auto) und schauen wie es klappt. Es sollen zwei Frequenzen gemessen werden. Wenn eine Flanke mal verloren geht oder die Messung nicht 100% genau ist,ist auch nicht schlimm. Danke und Grüsse, Maciek (dersichjetzthoffentlichmehrgedankenmacht)
Na ja, jeder steht mal auf dem Schlauch. wie kannst du dir sonst erklären, daß ich die Zeit zwischen den steigenden Flanken der beiden Signale messen wollte obwohl du im Ursprungsposting deine Anforderungen eigentlich klar angegeben hattest? mfg werner life is stupid
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.