Hallo Ich versuche mit einem ATmega644p (8MHz) den Timer Interrupt zu programmieren. Das funktioniert soweit auch mit dem Code im Anhang. Allerdings brauche ich eine kleinere Genauigkeit. Mit den 84 Zyklen erreiche ich nicht ganz 10us pro Inkrementation. Alles, was darunter liegt, verzögert das Ganze extrem, so dass die gewollte Sekunde zu 5 Sekunden wird. Der Fehler ist an sich nicht zu schlimm, das Ziel, das ich erreichen will, wird auch so funktionieren. Es wäre allerdings schöner mit besserer Auflösung. Gruss Ramon
Du hast nicht unbegrenzt Zeit innerhalb deiner ISR zur Verfügung, wie du ja schon bemerkt hast. Also, Generell: Mehr in Hardware zählen lassen, weniger in Software. Zur Inspiration: AVR - Die genaue Sekunde / RTC
Ramon M. schrieb: > Allerdings brauche ich eine kleinere Genauigkeit. Mit den 84 Zyklen > erreiche ich nicht ganz 10us pro Inkrementation. Alles, was darunter > liegt, verzögert das Ganze extrem, so dass die gewollte Sekunde zu 5 > Sekunden wird. Es sind 85 Zyklen und nicht 84. Auch so verbringt dein Programm 59 Zyklen (von 85) in der ISR, entspricht in etwa 70% der CPU-Zeit. Das ist nicht nur schlecht, es ist katastrophal. Das ist auch schlecht:
1 | if (counter0_250us == 94118) // 1 Sekunde erreicht |
Das ist besser:
1 | if (counter0_250us > 94117) // 1 Sekunde erreicht |
Was mich interessieren würde - wofür braucht man 10us ISR überhaupt ?
Marc V. schrieb: > Das ist auch schlecht: if (counter0_250us == 94118) // 1 Sekunde > erreicht warum findest du das schlecht? Das das ++ direkt darüber steht kann es doch zu keinem Fehler kommen.
Marc V. schrieb: > Das ist auch schlecht: if (counter0_250us == 94118) // 1 Sekunde > erreicht > > Das ist besser: if (counter0_250us > 94117) // 1 Sekunde erreicht Und was ist daran besser?
Thomas E. schrieb: > Marc V. schrieb: >> Das ist auch schlecht: if (counter0_250us == 94118) // 1 Sekunde >> erreicht >> >> Das ist besser: if (counter0_250us > 94117) // 1 Sekunde erreicht > > Und was ist daran besser? Würde mich auch interessieren. Bitte um eine Lehrstunde :-)
Peter II schrieb: > warum findest du das schlecht? Das das ++ direkt darüber steht kann es > doch zu keinem Fehler kommen. Thomas E. schrieb: > Und was ist daran besser? Huh schrieb: > Würde mich auch interessieren. Bitte um eine Lehrstunde :-) Wow. Rudel zusammengekommen.
1 | volatile uint32_t counter0_250us = 0; |
Es ist eine 32bit Variable, geht also bis 4,294,967,295. Falls diese Variable zufällig mit einem Wert´>= 94118 in die ISR reintrudelt, wird noch 4,294,967,294 Mal diese ISR angesprungen und munter weitergezählt, entspricht in etwa 12 Stunden. Deswegen. Wenn Ihr grösser seid und etwas mehr über Steuerungen und Sicherheit gelernt habt, gibt es weitere Stunden.
Marc V. schrieb: > Es ist eine 32bit Variable, geht also bis 4,294,967,295. > Falls diese Variable zufällig mit einem Wert´>= 94118 in die ISR > reintrudelt woher soll der Zufall kommen? Wenn man sich auf den Code nicht verlassen kann ist eh alles zu spät. Was ist wenn counter0_250us++; zufällig mal nicht funktioniert? Am besten noch eine 2 Variabel hochzählen und mit der ersten vergleichen?
"Wenn die Variable zufällig reintrudelt" klingt nicht so, als wenn du weißt, was du programmierst :-) Aber du wirst sicherlich auch größer und lernst, daß eine Variable eher selten die Eigenschaft besitzt "zufällig reinzutrudeln" :-)))
P.S.: Nicht alles, was man an den Haaren herbeizieht, ist ein gutes Beispiel. Bzw. Nicht alles, was hinkt, ist ein Vergleich :-D
Ramon M. schrieb: > Mit den 84 Zyklen > erreiche ich nicht ganz 10us pro Inkrementation. Was wäre, wenn Du die Zählvariable mit 94118 lädst und dann dekrementierst? Womöglich kann der Compiler den Test auf 0 besser optimieren.
Peter II schrieb: > woher soll der Zufall kommen? Wenn man sich auf den Code nicht verlassen > kann ist eh alles zu spät. Das nennt sich defensiver Programmierstil und jeder der schon mal ein nichttriviales Programm debuggt hat, weiß das zu schätzen.
Eigentlich sollte es nie passieren, aber ich mache solche Abfrage ebenfalls so. Nach dem Motto: Wenn es irgend geht, nie auf Gleichheit abfragen.
Axel S. schrieb: > Peter II schrieb: >> woher soll der Zufall kommen? Wenn man sich auf den Code nicht verlassen >> kann ist eh alles zu spät. > > Das nennt sich defensiver Programmierstil und jeder der schon mal ein > nichttriviales Programm debuggt hat, weiß das zu schätzen. Das > hat sogar einen Nachteil, wenn man bei einem Speicherüberschreiber die Variabel "zufällig" erhöht. Dann fällt der Fehler viel schneller auf, als wenn es einfach ignoriert wird. Es mag ja Geschmackssache sein, aber es als falsch oder schlecht zu bezeichnen ist hier nicht richtig.
Sebastian S. schrieb: > Eigentlich sollte es nie passieren, aber ich mache solche Abfrage > ebenfalls so. Nach dem Motto: Wenn es irgend geht, nie auf Gleichheit > abfragen. Sehe ich auch so... Lieber <= oder >= als == == nur wenn es muss Ist mittlerweile ein fester Automatismus. Und fällt mir in fremden Texten sofort auf. Aber wenns an der Stelle kein unmittelbares Problem macht.. Von mir aus .. Jeder ist seines Glückes Schmied.
Axel S. schrieb: > Das nennt sich defensiver Programmierstil und jeder der schon mal ein > nichttriviales Programm debuggt hat, weiß das zu schätzen. dann bitte aber so
1 | counter0_250us++; //Alle 250us Variable incrementieren |
2 | if (counter0_250us == 94118) // 1 Sekunde erreicht |
3 | {
|
4 | counter0_250us = 0; //Timer zurücksetzen |
5 | PORTD ^= 1<<0; //LED toggeln |
6 | }
|
7 | |
8 | if counter0_250us > 94118) { |
9 | while(1); |
10 | //assert usw.
|
11 | }
|
Axel S. schrieb: > Das nennt sich defensiver Programmierstil Das ist ein Thema, was hier schon reichlich mit gefletschten Zähnen durchdiskutiert wurde. Ich lasse ohnehin immer rückwärts zählen und teste auf 0. Vor allen Dingen aber, kann ich die arrogante Art von diesem eingebildeten Fatzke nicht ab: Marc V. schrieb: > Wow. Rudel zusammengekommen. Marc V. schrieb: > Wenn Ihr grösser seid und etwas mehr über Steuerungen und Sicherheit > gelernt habt, gibt es weitere Stunden.
>counter0_250us++; //Alle 250us Variable incrementieren >if (counter0_250us == 94118) // 1 Sekunde erreicht >{ > counter0_250us = 0; //Timer zurücksetzen > PORTD ^= 1<<0; //LED toggeln >} > >if counter0_250us > 94118) { > while(1); > //assert usw. >} Ein bisschen wie Hosenträger plus Gürtel;) Kommt eine solche Abfrage nur gelegentlich vor: Kein Problem Aber bei der anzunehmenden Häufigkeit...
Horst M. schrieb: > Ramon M. schrieb: >> Mit den 84 Zyklen >> erreiche ich nicht ganz 10us pro Inkrementation. > > Was wäre, wenn Du die Zählvariable mit 94118 lädst und dann > dekrementierst? > Womöglich kann der Compiler den Test auf 0 besser optimieren. 10 µs rufen geradezu nach Assemblerprogrammierung. So etwas überlässt man nicht dem C-Compiler.
Olly schrieb: > 10 µs rufen geradezu nach Assemblerprogrammierung. So etwas überlässt > man nicht dem C-Compiler. Vermute eher: Da stimmt grundlegend was am Design nicht. Der AVR hat extra Hardware (Timer) um bei solchen Anforderungen nicht unbedingt ISR-Takte zählen muss. Lässt sich ohne weitere Infos vom TE natürlich nicht sagen, was er (außer dem µS genauen Sekunden-Blinker) eigentlich machen will, aber ich vermute, dass er es unter Einsatz des ICP oder der Ouput-Compare/PWM Hardware stressfreier, exakter, jitter-ärmer hinkriegt, wenn etwas Gehirnschmalz investiert wird.
Olly schrieb: > 10 µs rufen geradezu nach Assemblerprogrammierung. So etwas überlässt > man nicht dem C-Compiler. Klar, aber die Frage ist, ob der TE damit nicht völlig vom Weg abkäme.
Axel S. schrieb: > Das nennt sich defensiver Programmierstil und jeder der schon mal ein > nichttriviales Programm debuggt hat, weiß das zu schätzen. Mit dem Vergleich auf '>=' verdeckst Du aber einen eventuellen Programmfehler, zum Beispiel einen Überschreiber der Variablen. Wenn dieser dann erst viele Monate später wegen einer Neuanordnung der Variablen auffällt, suchst Du Dich dumm und dämlich, denn: "an dieser Stelle habe ich schon eine Ewigkeit nichts mehr geändert!". Lass es lieber sofort krachen. Dann findest Du den Fehler unmittelbar. Unter "defensivem Programmierstil" verstehe ich etwas anderes: Wenn Werte von außen gegeben werden (z.B. durch Nutzerinteraktion oder von einem externen Gerät), dann ist es sinnvoll, vermeintlich niemals auftretende Werte zu prüfen. Aber im eigenen Programm? Marc V. schrieb: > Wenn Ihr grösser seid und etwas mehr über Steuerungen und Sicherheit > gelernt habt, gibt es weitere Stunden. Wenn Du wirklich so programmierst und das noch als "Sicherheit" verkaufst, dann bist Du ein schlechter Lehrer.
:
Bearbeitet durch Moderator
Thomas E. schrieb: > Das ist ein Thema, was hier schon reichlich mit gefletschten Zähnen > durchdiskutiert wurde. Ich lasse ohnehin immer rückwärts zählen und > teste auf 0. Und stehst genauso dumm da wie bei vorwärtszählen... > Vor allen Dingen aber, kann ich die arrogante Art von diesem > eingebildeten Fatzke nicht ab: LOL. Vielleicht wird das nur von dir und deinesgleichen als Arrogant empfunden, eines bin ich aber bestimmt nicht - eingebildet. Im Gegensatz zu dir und deinesgleichen.
Marc V. schrieb: > Vielleicht wird das nur von dir und deinesgleichen als Arrogant > empfunden, eines bin ich aber bestimmt nicht - eingebildet. > Im Gegensatz zu dir und deinesgleichen. https://www.youtube.com/watch?v=2_0zwbNpJvI
Frank M. schrieb: > Wenn Du wirklich so programmierst und das noch als "Sicherheit" > verkaufst, dann bist Du ein schlechter Lehrer. Ja, ich programmiere so und ja, ich nenne das Sicherheit. Verkaufen tue ich allerdings etwas anderes. Die Abfrage auf Gleichheit ist vom Sicherheitsaspekt her viel schlechter als Abfrage auf erreichen/überschreiten des Grenzwertes. > Mit dem Vergleich auf '>=' verdeckst Du aber einen eventuellen > Programmfehler, zum Beispiel einen Überschreiber der Variablen. Nein, mit diesem Vergleich engst du den möglichen Fehler auf +/- 1 Aufruf, anstatt auf +/- 4,294,873,176. Und es geht nicht immer um Programmfehler, es können auch andere Umstände dazu führen, auf welche du als Programmierer zum Zeitpunkt des Programmschreibens gar keinen Einfluss hast. Auf jeden Fall kostet es nichts, weder Code noch Zeit und deswegen ist diese Abfrage besser als blind auf eine einzige Möglichkeit aus gegebenen 4,294,967,295 zu vergleichen. P.S. Mal angenommen, diese Variable zählt die Anzahl der 10us-Abschnitte die vergangen sind, seit in einem Industriekessel die Temperatur die 125 Grad Grenze überschritten hat. Nach zwei Sekunden soll der Alarm losgehen. Wenn man auf die richtige Art prüft, gibt es keine Probleme, auch beim Überschreiben der Variable nicht. Wenn man einen auf AllesBesserWisser macht, (wie einige hier) fliegt die ganze Abteilung und vielleicht Fabrik in die Luft. Etwas klarer ?
:
Bearbeitet durch User
Ramon will aus 8,000 MHz mit CTC-Max = 84 (1/85) alle 10 µs ??? einen Interrupt auslösen. Womöglich noch 86 Befehlstakte in der IRS unterbringen, obwohl nur < 79 maximal möglich sind. Muss man zu so einem Beitrag noch streiten? Der Troll hat sich jedenfalls schon getrollt. ;-)
Peter II schrieb: > woher soll der Zufall kommen? Wenn man sich auf den Code nicht verlassen > kann ist eh alles zu spät. Da frag mal Satellitenbetreiber. Die wissen, warum strahlengehärtete Prozessoren und Fail Save Algorithmen eingesetzt werden. Auf der Erdoberfläche ist es dank einer soliden Atmosphäre schon seltener, das Höhenstrahlung zum Kippen eine Bits führt. Wer das Risiko liebt, vergleicht auf Gleichheit.
Strahlungsgehärtet bedeutet, dass die keinen Strahlungsinduzierten Latch-Up haben können, nicht dass da keine Bits kippen.
Ramon M. schrieb: > Der Fehler ist an sich nicht zu schlimm, das Ziel, das ich erreichen > will, wird auch so funktionieren. Es wäre allerdings schöner mit > besserer Auflösung. Dann wäre es besser, wenn Du mal das Ziel nennen würdest. Dann könnte man feststellen, ob es wirklich einen 10µs Interrupt benötigt oder anders lösbar wäre. Zu beachten ist auch, daß der AVR keine Interruptprioritäten kann, d.h. jede weitere Interruptquelle würde die 10µs zusätzlich verlängern.
Also, ich bin der Ansicht, daß man in einer idealen Welt den uC Programmablauf nicht in eine Zeitzwangsjacke stecken sollte. Das ist immer ein Hinweis, daß besser anwendungspezifische Hardware zeitkritische Funktionen den Job erledigen sollte. Die Auswahl und Funktionen der HW Peripherien, obwahl in manchen uC sehr vielseitig, hat auch ihre Grenzen. Wenn es die nicht alleine sauber schaffen eine Aufgabe ohne Klimmzüge zu erledigen, ist das immer ein Anzeichen, daß in der Richting etwas unternommen werden sollte. Auch wenn tüfteliges Assemblieren es trotzdem schafft, macht man sich nur das Leben unnötig schwer. Wenn es die eingebauten HW Resourcen eines uC eben nicht alleine schaffen, dann sollte man besser externe HW wie CPLD, FPGA oder spezifisch geschaltete Logikbausteine einsetzen. Damit ist das Programm von den Hardware Abläufen entkoppelt und dient lediglich der Steuerung der Randbedingungen einschließlich Datenverbindung mit externen Entitäten. Die Zeit die Manche aufwenden müssen um den uC (und sich) zu quälen um zeitsynchrone Funktion zu erzielen wäre einer besseren Sache wert. Jedenfalls halte ich es so und bin damit immer sehr gut damit gefahren.
:
Bearbeitet durch User
Peter D. schrieb: > Zu beachten ist auch, daß der AVR keine Interruptprioritäten kann, d.h. > jede weitere Interruptquelle würde die 10µs zusätzlich verlängern. "Jacko (Gast)" hat gestern schon angemerkt, dass bereits die ürsprünglichen Annahmen des TO völlig unrealistisch sind (und dabei noch massiv untertrieben, denn tatsächlich stehen bei 8MHz Systemtakt und 100kHz Interrupfolgefrequenz nicht 79, sondern bestenfalls 70 Takte für Nutzcode in der ISR zur Verfügung. Jacko hat hier den Interruptframe mit mindestens 8 Takten vergessen und auch die Tatsache, dass in main() zwangweise eine Schleife laufen muss, die zwangsweise irgendwie geschlossen werden muss, was im worst case eben nicht nur einen, sondern zwei Takte klaut. Und bei regelmäßig erfolgenden Interrupts kann man nunmal nicht darauf hoffen, das der nächste erst später erfolgt und so das Debit ausgeglichen werden kann... Und in C bleiben von diesen schon rein theoretisch maximal 70 nutzbaren Takten nochmal deutlich weniger über. Sogar erschreckend wenig, genau das ist ja, was ich an C ständig kritisiere und warum ich für den AVR praktisch ausschließlich in Assembler programmiere. > Dann wäre es besser, wenn Du mal das Ziel nennen würdest. Dann könnte > man feststellen, ob es wirklich einen 10µs Interrupt benötigt oder > anders lösbar wäre. Ja, das allerdings ist ein sehr guter Einwand. Manche glauben ja einfach nur, solche Zeitauflösung zu benötigen, weil sie letztlich einen dümmlichen Polling-Ansatz mit Hilfe von Interrupts umsetzen wollen...
c-hater schrieb: > "Jacko (Gast)" hat gestern schon angemerkt, dass bereits die > ürsprünglichen Annahmen des TO völlig unrealistisch sind (und dabei noch > massiv untertrieben, denn tatsächlich stehen bei 8MHz Systemtakt und > 100kHz Interrupfolgefrequenz nicht 79, sondern bestenfalls 70 Takte für > Nutzcode in der ISR zur Verfügung. Wie ich gestern schon angemerkt habe: Marc V. schrieb: > Auch so verbringt dein Programm 59 Zyklen (von 85) in der ISR, > entspricht in etwa 70% der CPU-Zeit. > Das ist nicht nur schlecht, es ist katastrophal. Das man in den verbleibenden 24-26 Takten nichts gescheites machen kann, ist wohl klar. Zumindest nichts, ohne ständig unterbrochen zu werden. Und meine Frage (auch von gestern) steht immer noch: Marc V. schrieb: > Was mich interessieren würde - wofür braucht man 10us ISR überhaupt ?
:
Bearbeitet durch User
Sparfüchse können die ISR auch "nacked" machen, sind dann aber für jeden Furz selber verantwortlich.
c-hater schrieb: >> Dann wäre es besser, wenn Du mal das Ziel nennen würdest. Dann könnte >> man feststellen, ob es wirklich einen 10µs Interrupt benötigt oder >> anders lösbar wäre. > > Ja, das allerdings ist ein sehr guter Einwand. Manche glauben ja einfach > nur, solche Zeitauflösung zu benötigen, weil sie letztlich einen > dümmlichen Polling-Ansatz mit Hilfe von Interrupts umsetzen wollen... Ich habe zwei Rechtecksignale mit einer Frequenz von 5 kHz, die phasenverschoben sind. Ich will bei positiver Flanke der beiden Signale die Timervariabel auslesen, um dann die Zeitdifferenz zwischen den beiden positiven Flanken und somit die Phasenverschiebung ausrechnen zu können. Ausserdem wirde noch der Assembler genannt. Ich möchte hier noch sagen, dass ich den Assembler überhaupt nicht beherrsche, und nicht die Zeit dazu habe, diesen noch zu lernen.
Dann gibst du das eine Rechteck auf INT0 und das zweite auf INT1, lässt ab dem ersten Interrupt den Timer loslaufen und stoppst ihn beim Zweiten.
Wie wäre mit zwei CAPTURE Eingängen die von einem gemeinsamen TIMER gespeist werden? Den CAPTURE stellt man auf beiden Kanälen so ein, daß sie auf die positiven Flanken reagieren. Dann braucht man nur zu warten bis die CAPTURE Logik die entsprechende ISR triggert. Danach können die beiden CAPTURE Event Werte nebst etwaigen overflows dann bequem innerhalb von weniger als 200us behandelt werden und kann den Zeitunterschied supergenau erfassen. Bei 1MHz Timer Clock ist die Auflösung immerhin 1us und ist beim AVR bei entsprechender Quarzfrequenz noch nicht einmal die oberste Grenze. Bei dem vorher vorgeschlagenen INT0/1 Methode ist doch ein nicht zu vernachläßigbarer Overhead. Bei 16Mhz Quarzfrequenz stellt man z.B. den Prescaler für 1us Auflösung auf 16 ein damit der 16-bit TIMER mit 1Mhz getaktet wird. Mir ist diese Hardware Methode lieber weil die Messung komplett in Hardware realisiert sein würde. Das läßt sich alles bequem ohne Assembler erledigen. Ich finde man sollte die uC Resourcen diesbezüglich voll ausschöpfen.
:
Bearbeitet durch User
Ramon M. schrieb: > um dann die Zeitdifferenz zwischen den > beiden positiven Flanken und somit die Phasenverschiebung ausrechnen zu > können. Dann kannst Du beide Signale abwechselnd über den analog Multiplexer und analog Comparator an den Capture Input legen. Damit erreichst Du sogar 125ns Auflösung, also 80-mal besser als mit 10µs und hast keinerlei Zeitprobleme mehr. Wichtig ist, im Capture-Mode den Timer durchlaufen zu lassen und die Differenz der Timestamps zu nehmen. Ein SW-Reload oder Start/Stop würde sonst wieder einen Jitter bewirken. Den Fall, daß die Phasenverschiebung klein ist und daher die Signale nur jede 2. Periode triggern, stellt man einfach dadurch fest, daß nun statt 5kHz die Periode eines Eingangs 2,5kHz entspricht.
Ramon M. schrieb: > Ich habe zwei Rechtecksignale mit einer Frequenz von 5 kHz, die > phasenverschoben sind. Ich will bei positiver Flanke der beiden Signale > die Timervariabel auslesen, um dann die Zeitdifferenz zwischen den > beiden positiven Flanken und somit die Phasenverschiebung ausrechnen zu > können. Mit ein bißchen Rechnerei kann man die Phasenverschiebung auch direkt anzeigen. Das Programm wertet die Signale an INT0 und INT1 aus, wobei die jeweilige Flanke einstellbar ist: Beitrag "Stoppuhr – Geschwindigkeit – Pulsweite mit Atmega88"
Gerhard O. schrieb: > Wie wäre mit zwei CAPTURE Eingängen die von einem gemeinsamen TIMER > gespeist werden? Den CAPTURE stellt man auf beiden Kanälen so ein, daß > sie auf die positiven Flanken reagieren. Dann braucht man nur zu warten > bis die CAPTURE Logik die entsprechende ISR triggert. Danach können die > beiden CAPTURE Event Werte nebst etwaigen overflows dann bequem > innerhalb von weniger als 200us behandelt werden und kann den > Zeitunterschied supergenau erfassen. Das klingt schon mal sehr vielversprechend. Allerdings wäre ich jetzt froh um ein Codebeispiel, da ich die Interrupts noch nie benutzt habe. Ich weiss nicht, wie ich die Interrupts konfigurieren und starten muss und wie ich dann den Timer auslöse.
Ramon M. schrieb: > Das klingt schon mal sehr vielversprechend. Allerdings wäre ich jetzt > froh um ein Codebeispiel, da ich die Interrupts noch nie benutzt habe. > Ich weiss nicht, wie ich die Interrupts konfigurieren und starten muss > und wie ich dann den Timer auslöse. Korrektur: INT0 und INT1 auf positive Flanken zu konfigurieren habe ich geschafft, allerdings weiss ich nun nicht, wie ich den Timer starten soll. Muss das in der ISR von INT0 und INT1 geschehen?
Ramon M. schrieb: > Ich versuche mit einem ATmega644p (8MHz) den Timer Interrupt zu > programmieren. Das funktioniert soweit auch mit dem Code im Anhang. Ramon M. schrieb: > Das klingt schon mal sehr vielversprechend. Allerdings wäre ich jetzt > froh um ein Codebeispiel, da ich die Interrupts noch nie benutzt habe. > Ich weiss nicht, wie ich die Interrupts konfigurieren und starten muss ja was nun ? Ist der Timer Interrupt kein Interrupt ? Im Int0 oder 1 einfach den Timer starten und stoppen. Konfigurieren kannst du den ja schon vorher in Ruhe oder er läuft durch und Du gibst nur den Int in der ISR frei. Viele Wege führen nach Rom.
Ramon M. schrieb: > Ramon M. schrieb: >> Das klingt schon mal sehr vielversprechend. Allerdings wäre ich jetzt >> froh um ein Codebeispiel, da ich die Interrupts noch nie benutzt habe. >> Ich weiss nicht, wie ich die Interrupts konfigurieren und starten muss >> und wie ich dann den Timer auslöse. > > Korrektur: INT0 und INT1 auf positive Flanken zu konfigurieren habe ich > geschafft, allerdings weiss ich nun nicht, wie ich den Timer starten > soll. Muss das in der ISR von INT0 und INT1 geschehen? Du brauchst weder INT0 nocht INT1. Du sollst die Capture-Funktionalität der Zähler/Timer im AVR benutzen. Und der Timer wird nur einmal gestartet, wenn dein Programm losläuft. Danach wertest du nur noch die Differenz des Zählerstands zwischen zwei Capture-Ereignissen aus. Lies hier: AVR-GCC-Tutorial/Die Timer und Zähler des AVR und hier: High-Speed capture mit ATmega Timer benutze ruhig auch die Suchfunktion (Stichwort: "capture") des Forums
:
Bearbeitet durch User
Naja, ich habe da einen Mist erzählt. Mittlerweile konnte ich den 16 Bit Timer mit der Capture Funktion zu meinen Gunsten konfigurieren. Allerdings habe ich nun das Problem, dass es nur einen Capture Eingang gibt und ich zwei Signale habe. Ich glaube ich könnte aus den zwei Signalen eines machen mit einer Schaltung, das Problem ist nun aber, dass ich die Interrupts deaktivieren muss, um den Capture Wert auszulesen. Dadurch wird doch auch der Timer angehalten, oder? Mit INT0 und INT1 den Timer starten und stoppen hat noch nicht funktioniert
Ramon M. schrieb: > das Problem ist nun aber, > dass ich die Interrupts deaktivieren muss, um den Capture Wert > auszulesen. Dadurch wird doch auch der Timer angehalten, oder? wenn man die Interrupts deaktivieren laufen die Timer weiter, aber warum musst du ihn überhaupt deaktivieren? Wenn du in einer ISR bist, sind sie schon deaktiviert.
Peter II schrieb: > Wenn du in einer ISR bist, sind sie > schon deaktiviert. Nur bin ich nicht in einer ISR mit der Capture Funktion. Ich habe die Werte im main ausgelesen. Habe ich da was falsch gemacht?
Ramon M. schrieb: > Nur bin ich nicht in einer ISR mit der Capture Funktion. Ich habe die > Werte im main ausgelesen. Habe ich da was falsch gemacht? das müsste richtig sein, aber warum willst du beim auslesen die ISR sperren? Zeig doch mal wie du es genau machst.
Ramon M. schrieb: > In dem Code habe ich auch noch die ISR drin (auskommentiert) Sorry, ich habe ihn (als Mod) versehentlich gelöscht, als ich auf die Codeansicht wollte. Kannst Du ihn nochmal reinstellen?
Ramon M. schrieb: > Ich glaube ich könnte aus den zwei > Signalen eines machen mit einer Schaltung Die Schaltung befindet sich bereits im ATmeg644. Schau mal im Datenblatt unter:
1 | 24.2. Analog Comparator Multiplexed Input |
Du kannst insgesamt 9 Pins auf den Analog Comparator legen und dessen Ausgang auf den Capture-Input. AIN0 legt man auf die Bandgap (1,1V) als Schwelle. Nach jedem Umschalten muß man das ICF1-Bit setzen, damit kein Pseudointerrupt auftritt.
10 µs Interrupt bei 8 MHz. Kann man machen, WENN MAN GENAU WEISS, A) dass man max. 70 Takte zur Verfügung hat B) dass man JEDEN Takt JEDER weiteren ISR (inklusive 10 Takte Aufruf + Rücksprung) von den 70 abziehen muss. C) Der Rest muss für's Hauptprogramm reichen. Ist also machbar. Gibt dann auch plausible Ergebnisse. Aber, so wie du fragst, würde ich mal sagen: Das hast du nicht berechnet. Ergebnis: Mal macht er's, mal nicht...
Peter D. schrieb: > 24.2. Analog Comparator Multiplexed Input Ich habe mir das angesehen und ich verstehe das ehrlich gesagt gar nicht... Entweder nimmt man AIN0 und AIN1 oder man ersetzt AIN1 durch die Analogeingänge. Habe ich das so richtig verstanden? Und so wie ich das verstehe, muss man den Eingang selber mit den MUX Bits auswählen?
Für 2 Eingänge reicht auch schon, zwischen ICP und AIN1 umzuschalten. Den MUX brauchst Du erst für 3..10 Eingänge oder wenns fürs Layout besser paßt.
Peter D. schrieb: > Für 2 Eingänge reicht auch schon, zwischen ICP und AIN1 umzuschalten. Okay. Vielleicht tue ich mich hier schwer, aber wieso jetzt ICP und AIN1 und nicht AIN0 und AIN1? Und sollte dann jede Flanke von beiden Signalen ein Capture Event auslösen?
Ramon M. schrieb: > Und sollte dann jede Flanke von beiden Signalen ein Capture Event > auslösen? Du könntest die erste Flanke als Startbedingung wählen (z.B. über ein Pin-Change-Event) und die zweite als Capture-Event. Schau noch mal was genau Peter hier geschrieben hat, er hat dir oben sicher schon ein paar Tipps gegeben (hab den Fred nicht komplett gelesen).
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.