Hallo, da ich noch nie einen Timer benötigt habe stehe ich jetzt an dem Punkt, dass ich nicht so recht weiss wie man ihn anwedet. Ich benutzte den Mega8 und werte ein PWM Signal aus, lege Daten in MMC ab und sende über Uart. Senden und speichern ist nicht so schwierig für mich, aber mit der Funktionsroutine für Timer habe ich einige Probleme. Wäre schön wenn sich mal jemand meine Codeschnipsel ansehen könnte, weil es wahrscheinlich falsch sein wird. Kann mir vielleich jemand die Routine beschreiben oder Codeschnipsel posten, wie man das Auslösen der Interrupts auswerten kann (var2-var1). ist die überlegung richtig?: Timer startet -> st.Flanke -> Interrupt -> Timer startet -> st.Flanke2 -> Interrupt2 Danke schon mal #include <avr/io.h> #include <avr/interrupt.h> #include <avr/signal.h> SIGNAL(SIG_INTERRUPT0) { Daten an MMC(frequenz); } void main(void) { GICR = _BV(INT0); //enable int0 for(;;){ TCCR1B = _BV(CS12) //timer starten ...255 MCUCR = _BV(ISC01) | _BV(ISC00) //interrupt bei steigender fl //...steigende Flanke löst interrupt aus var1; MCUCR = _BV(ISC01) | _BV(ISC00) //interrupt bei steigender fl //...nächste Flanke löst interrupt aus var2; Timer zurücksetzen frequenz=var2-var1; } }
Würde ich nicht so machen. Ich würde den input capture interrupt benutzen. Zuerst auf die eine Flanke setzen, beim Interrupt den capture-Wert merken und ihn auf die andere Flanke umschalten. Bei der zweiten Flanke die Differenz bilden. Da müßte doch ungefähr sein, was Du willst, oder? Beim externen Interrupt hast Du immer das Problem, daß die Interrupt-Latenz und insbesondere die mögliche Varianz dieser Latenz das Ergebnis beeinflussen.
Ich glaube das habe ich ungefähr verstanden. 1.TCCR1B = _BV(ICES1) | _BV(CS12) //Timer starten, steigende flanke ICP 2.TIMSK = _BV(TICIE); 3.TIFR = _BV(ICF1); //Bit wird gesetzt, wenn Capture-Ereignis aufgetreten ist 4.var1 = ICR1 //Wert an Variable übergeben Jetzt habe ich doch den ersten Wert var1, doch jetzt ist mir unklar ob der Timer angehalten wurde(neu gestartet werden muss) und wie man den Flankenwechsel in "C" ausdrückt. Timer soll ja weiterlaufen und auf Interrupt2 (fallende Flanke) reagieren. Kennt vielleicht jemand ein Beispiel im Netz? Danke nochmal
Hallo ich habe immer noch (Verständnis-)probleme mit dem Timer/Counter. ICP kann ich nicht nutzen, da ich mehrere (so viele wie möglich) Sensoren (ADXL202) auswerten möchte. Also bleibt mir nur übrig über INT0 und INT1 die Pulsbreiten zu bestimmen. Jetzt habe ich aber ein Problem in der Grundüberlegung. 1. Ich nehme einen Counter mit großer Frequenz (prescale = 1) und lasse ihn mit SIG_OVERFLOW so lange durchlaufen, bis der Interrupt vorbei ist. oder: 2. Ich passe den Counter so an, dass er für einen Durchlauf in etwa die Zeit der Pulsbreite (bzw. etwas mehr) benötigt und lese dann den Zählerstand aus dem TCNT0-Register. Also bräuchte ich dann doch SIG_INTERRUPT!? Jetzt würde mich interessieren, was falsch ist bzw. wie man es nicht machen sollte. Wie gesagt ICP kann ich leider nicht nutzen.
Was ich ausserdem nicht ganz verstehe ist, wann genau der Zähler startet. Entweder beim ausgelösten Interrupt oder bereits wenn man den AVR mit Strom versorgt. Bei 1. hab ich das Problem, dass mir u.U. 1 Durchlauf fehlen können (wenn der Zähler schon auf 254 z.B. steht, dann würde schon ein Zähler einen Durchlauf bedeuten (1=255). Mit 2. funktioniert das sowieso nicht, da die Sensorperiode 10ms beträgt und ich nur auf 0,512ms pro Counterperiode komme. Sehe ich das jetzt richtig, dass ich ein SIG-OVERFLOW benötige?
Ich verstehe nicht, warum Du einerseits ICP nicht nutzen kannst, aber andererseits mit den blöden externen Interrupts zufrieden bist. Vielleicht ist es ja eine Option, den ATmega8 durch einen ATmega88 zu ersetzen? Dort hast Du die Möglichkeit, pin change interrupts zu benutzen. Einen Zähler adaptieren würde ich nicht, sondern ICP in Software simulieren: der entsprechende Interrupthandler muß den Wert des Timers auslesen und irgendwo notieren, danach setzt er ein Flag, daß er getriggert worden ist, so daß die Hauptschleife das Ereignis verarbeiten kann. Wenn die PWM-Eingangssignale beinahe gleichzeitig auftauchen, hast Du aber notgedrungen ein Jitter in Deiner Interpretation, d. h. die interpretierten PWM-Werte weichen (bedingt durch die schnell nacheinander eintreffenden Interrupts) von den tatsächlichen Werten ab. Ein übergelaufener 16-bit Zähler ist übrigens gar kein Problem, sofern sichergestellt ist, daß maximal ein Überlauf zwischen den beiden Ereignissen stattfand: Du liest den jeweiligen Zählerstand einfach als uint16_t aus und subtrahierst den älteren vom jüngeren, das Ergebnis wird dank 2er-Komplement auch dann noch korrekt, wenn der ältere Zählerwert größer als der jüngere ist.
"Wenn die PWM-Eingangssignale beinahe gleichzeitig auftauchen, hast Du aber notgedrungen ein Jitter in Deiner Interpretation, d. h. die interpretierten PWM-Werte weichen (bedingt durch die schnell nacheinander eintreffenden Interrupts) von den tatsächlichen Werten ab." Ich dachte so ein Fall wäre nicht möglich, da der erste Interrupt zuerst abgearbeitet wird, bis wieder ein Interrupt möglich ist. Also der zweite, der deiner Meinung nach beinahe auftaucht, erst gar nicht erkannt wird. Aber ich lese hier schon länger und vertraue deiner Meinung. "Ich verstehe nicht, warum Du einerseits ICP nicht nutzen kannst, aber andererseits mit den blöden externen Interrupts zufrieden bist." Ich bin auch immer davon ausgegangen das die Pins INT0, INT1 und ICP dazu gedacht sind, digitale Signale zu verarbeiten, im Gegensatz zu anderen Pins wie die ADCs. Ist es möglich, 4 digitale Signale an einem einzigen ICP abzuarbeiten? Wie müsste da die Beschaltung aussehen?
Wäre es also besser, wenn ich z.B. die vier digitalen Signale über vier UND-Gatter mit µC verbinde und die Gatter dann mit µC steuere. Gatter1=High + PWM Gatter2=Low +PWM Gatter3=Low +PWM Gatter4=Low +PWM danach Gatter1=Low +PWM Gatter2=High +PWM Gatter3=Low +PWM Gatter4=Low +PWM usw. Sowas wollte ich eigentlich vermeiden, weil ich mir nicht sicher bin ob dann nicht andere effekte auftreten können. Leider gibt es hier nicht so viele gute Beispiele in "C" wie man die Pulsbreite eines PWM-Signals verarbeiten kann. Viele benutzen dann einfach die ADC, davon gibt es ja immer mehr als man brauchen kann - aber nur ein ICP? Ist das noch zeitgemäß, dass man dann noch über externe Gatter schalten muss, wenn man mehrere Signale verarbeiten möchte? Fast alle guten Sensoren liefern ja inzwischen ein digitales Signal.
Nein, ich würde das nicht über externe Gatter machen. Das mit dem Jitter bezog sich auf verschiedene Interrupts. Ist aber richtig, Du würdest wohl in der Tat nur einen pin changed interrupt bekommen, in dessen ISR mußt Du dann alle möglichen Ereignisse auswerten. Dennoch dürfte sich das Timing der ISR zwischen einem und mehreren Ereignissen unterscheiden, damit hast Du keine konstante Interruptlatenz mehr, folglich einen Jitter. Ob der zeitlich für Dich relevant ist, weiß ich natürlich nicht. Meine Bemerkung mit den externen Interrupts bezog sich darauf, daß Du mit diesen ja auch nur genau zwei Kanäle abfragen kannst. Wenn ich Dich richtig verstehe, willst Du aber mehr abfragen können. > Ist das noch zeitgemäß, dass man dann noch über externe Gatter > schalten muss, wenn man mehrere Signale verarbeiten möchte? Fast > alle guten Sensoren liefern ja inzwischen ein digitales Signal. PWM ist aber eher ein digital übertragenes Analogsignal, daher hast Du ja auch den Streß mit der Digitalisierung. Ein digitales Signal wäre eine Übertragung mit SPI.
>Meine Bemerkung mit den externen Interrupts bezog sich darauf, daß Du >mit diesen ja auch nur genau zwei Kanäle abfragen kannst. Wenn ich >Dich richtig verstehe, willst Du aber mehr abfragen können. Ich trete immer noch etwas auf der Stelle herum und komme nicht weiter. -ICP, leider nur einer, der sollte auch für die MMC herhalten -INT0 und INT1, sollen nicht so toll sein -UND-Gatter davor schalten auch nicht so optimal was nun? Es wäre ein Controller gut der über 4-8 ICP verfügt, kennt da jemand einen?
Sorry, dass ich deshalb das Forum so zumüllen muss. Ich werde jetzt nochmal alles mit SIG_OVERFLOW an den etx.Int.Pins testen und melde mich dann wieder. Vielleicht hat hier schon mal jemand gleiches versucht und kann mir links, tips oder codeschnipsel posten. Danke Morgen
Was Du mit einem Interrupt-Handler an externen Pins willst, verstehe ich leider nicht. Was spricht gegen die Verwendung es pin change interrupts beim ATmega88? Der ist ja sogar pinkompatibel zum ATmega8. Du kannst auf Änderungen an bis zu 24 Pins reagieren.
Ich hoffte mehr über die Abarbeitung mehrerer Signale zu erfahren, da ich nicht der einzige bin, der damit Schwierigkeiten hat. Jemand aus dem schönen Brisbane, an der University of Queensland, dem Sunshine State in Australien, hatte auch das Problem mit einem AVR und hat die beiden Sensorsignale gemultiplext, mit einem extra IC. http://innovexpo.itee.uq.edu.au/2001/projects/s369518/thesis2.pdf
Ja, dafür konnte er den Hardware-ISP benutzen. Wie geschrieben, wenn Du möglichst viele dranklemmen willst (und keine extremen Genauigkeitsforderungen hast), wer hindert Dich daran, das mit pin change interrupts und einem ATmega88 zu tun? Darauf bist Du bislang noch nicht eingengangen. Andernfalls, falls Du gute Genauigkeit (Hardware-PWM) bei 2 Kanälen haben willst ohne externe Mimik, ATmega162, ATmega64 und ATmega128 haben zwei 16-bit Zähler und damit zwei ICP-Eingänge.
Hallo, erst mal danke, dass ihr meinen Beitrag weiter verfolgt! Zum ATmega88: Wusste bis gestern gar nicht, dass es einen solchen gibt, hört sich aber gut an, wenn ich auch irgendwo hier im Forum gelesen habe dass es einen AT89.... (bin mir nicht mehr sicher) gibt, der über fünf ICP verfügt. Aber das ist jetzt auch egal - ich hatte gestern nur ein Problem mit der Grundüberlegung (Timer läuft über..., TCNT auslesen oder Polling[so nennt man das doch... count++]...) Habe vor einigen Stunden den ADXL eingelötet und wollte mal ein Signal, wie empfohlen, mit dem ICP auslesen. Aber meine erhaltenen Werte sind zu hoch. Ausserdem erkennt er meine if-Funktion nicht richtig - bzw. die Abfrage ob jetzt gerade eine fallende oder st. Flanke gecaptured wurde. Erkennt nur den LOW-state des PWM-Signals und ist obendrein fast doppelt so lange wie die eingestellte Frequenz am Sensor. Code ist im Anhang und hier er kennt er die steigende flanke irgendwie nicht richtig: ####################################################### SIGNAL(SIG_INPUT_CAPTURE1){ unsigned char *hilf, *hilf2; unsigned int timer_wert1, timer_wert2, flanke; flanke = ((TCCR1B) & 0x40); if(flanke != 0x00){ //ich habs auch schon mit int und "0" probiert //bei steigender flanke... timer_wert1 = ICR1; //wert auslesen ... ######################################################## Zu den berechneten Werten: Clock = 4MHz Prescale = 8 daraus resultiert 0,002ms pro Periode Werte für den LOW-state des Sensors erhalte ich um die 5-6000 (entspricht doch dann 5000*0,002ms ~ 10ms), das würde mich auch nicht stören, wäre meine Sensorperiode nicht bei 7,6ms!
Vielleicht kann es mal jemand brauchen, war ziemlich versteckt hier im Forum: http://www.al-williams.com/pak7.htm Damit sollte man bis zu 8 Signale verarbeiten können.
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.