Hallo, ich versuche schon die ganze Zeit einen Timer0 Interrupt mittels CTC Modus hinzubekommen, um einen Takt von 1us für mein Programm zu erzeugen. Die Initialsisierung und der Interrupt funktioniert an sich schon, jedoch ist der kleinste Wert, den ich erreiche 2us! Bei einem Systemtakt von 16MHz (ohne Prescaler) muß das OCR0 Register mit 16 vorgeladen werden. Der Timer0 zählt bis 16 (bei 16MHz = 1us) und wird durch den CTC Modus wieder zurückgesetzt und gleichzeitig wird der SIG_OUTPUT_COMPARE0 Interrupt ausgelöst. Zum Test Toggle ich im Interrupt den PortC. Aber ich messe High bzw. Low Zeiten von genau 2us. ABER: Lade ich das OCR0 Register mit z.B. 64 vor, so messe ich High/Low Zeiten von genau 4us! Dieser Wert ist richtig. Auch für 128 stimmt es. Für 16 erhalte ich auch nur wieder 2us! 2. Versuch: Im Normalmodus von Timer0 muß jedes mal wenn ein SIG_OVERFLOW0-Interrupt ausgelöst wird das Register mit TCNT0=240 vorgeladen werden. Damit verbleiben 16 Takte (= 1us) bis zum nächsten Interrupt. Aber nein, er wird nur aller 2us ausgelöst, auch mit TCNT0=247. Woran kann das liegen??? Folgende Situation: CPU: ATMEGA32-16PU mit 16MHz getaktet Sprache: C (gcc) Der Timer0 (im CTC Modus) wird wie folgt initialisiert: OCR0 = 16; TCCR0 |= (1<<WGM01); // CTC Mod, TCCR0 |= (1<<CS00); // CPU Takt = 16 MHz Danke für eine schnelle Antwort. Stefan
> ich versuche schon die ganze Zeit einen Timer0 Interrupt mittels CTC > Modus hinzubekommen, um einen Takt von 1us für mein Programm zu > erzeugen. Die Initialsisierung und der Interrupt funktioniert an > sich schon, jedoch ist der kleinste Wert, den ich erreiche 2us! Wenn ich deine CPU wäre, würde ich auch nicht mehr erreichen wollen. ;-) Hast du dir schon einmal überlegt, dass die komplette Interruptannahme und -ausführung dann keine 16 Takte Zeit hat? Davon gehen wimre. bereits 4 Takte für die Annahme drauf, weitere Takte für das Retten und Rückspeichern des aktuellen Prozessorstatus. Nicht jeder Befehl ist in einem Takt ausgeführt... Was bitte willst du denn da noch Sinnvolles 1.) innerhalb der ISR und zweitens in den wenigen verbleibenden CPU-Zyklen im Hauptprogramm anstellen?
Hallo, danke für die schnelle Antwort, ich brauche die 1us Auflösung für die Ansteuerung eines Multiplexers, mit dem ich mehrere Spannungen hin und her schalten kann, um eine Art einfachen Pulsgenerator zu bauen. Im Restprogramm oder in der ISR soll nur noch eine Variable gezählt werden und bei bestimmten Werten den Multiplexer entsprechend schalten Stefan
Ich denke fast, dass ein Controller für dich die falsche Lösung ist und du eher nach einem FPGA oder sowas suchst... Anyway, codier' die ISR zu Fuß in Assembler. Reserviere für alle Dinge, die du in der ISR retten musst, Registervariablen im C-Code. Dann hast du vielleicht gerade mal so eine Chance. Du solltest es in jedem Falle mit der Hand durchrechnen. Wenn du pro Mikrosekunden noch einen Befehl frei hast für das main(), sollte das ja fast genügen... ;-)
Hallo, ja, ein FPGA wäre für diese Sache besser geeignet, aber der AVR übernimmt noch andere Steueraufgaben, so daß ich auf ihn angewiesen bin. Ich werde erstmal meine Anforderungen herunterschrauben und mich mit einer Zeitauflösung von 10us begnügen. Und wenn mein Kopf wieder etwas freier ist an die 1us heranwagen. Trotzdem Danke! Stefan
"Und wenn mein Kopf wieder etwas freier ist an die 1us heranwagen." Besser als 5µs wirds aber kaum werden. Selbst in Asembler kostet ein nackter Interrupt 10 Zyklen, also ohne was zu tun oder zu sichern. Ich hab mal nen Assemblerinterrupt alle 64 Zyklen gemacht, nie wieder ! Sämtliche anderen Interrupts mußten auch in Assembler gemacht werden, um eine 2. Prioritätsstufe zu simulieren. Sowas ist echt haarig. Wenn ich das nächste mal kurze Interrupts benötige, dann nehme ich wieder den 8051, da habe ich 4 Prioritäten. Die sollen mal mit dem AT89LP4051 endlich aus die Puschen kommen, der ist immer noch nur Sample-Status. Peter
Hatte ähnliche Probleme, hab einen Ausgang gesetzt und wollte ihn nach eine 1 µs reseten. Allerdings in Basic - hat aber mit den wait Befehl gejittert. Hab dann die µs mit nop erzwungen. Genau 14 nops plus set und reset ergaben am Ausgang 1µs! Microkontroller: Atmega32 mit 16 MHZ crystal!
Da staune ich, was in Basic alles möglich ist. Ist bestimmt BASCOM :-)
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.