Ich hab nun einiges ausprobiert. Leider alles ohne den erwünschten Erfolg. Es muss ein Rechteck erzeugt werden, bei dem sich die Frequenz ständig erhöht. Die Frequenz läuft aber leider nicht linear, sondern nach einer e-Funktion. Die immer aktuell berechnet werden muss. T=1/(10*2^(t/60)) Kann mir da jemand Möglichkeiten nennen.?
10-500 Hz und das ganze soll über 340 sek. langsam hochlaufen. Das grösste Problem ist, das Die Berechnung schon 3mS in Anspruch nimmt. Im Moment berechne ich einfach die Impulsdauer in einen Timerinterrupt. Funktioniert auch ganz gut, aber ich sehe halt diese 3mS immer als Pause in meinen Signal.
Ich würde die gar nicht aktuell berechnen, sondern EIN mal berechnen und in einer Tabelle (im Flash oder ext. EEPROM) ablegen. Dann brauchst du nur noch einen Timer mitlaufen zu lassen, der dafür sorgt, dass du jeweils den korrekten Wert aus deiner Tabelle liest. Ein Flash-Zugriff dauert ein paar ns; das ist ja schon ein ziemlicher Gewinn gegenüber deinen 3ms ... ;-)
Hab auch schon über eine Tabelle nachgedacht, aber es wäre schon eine ganze Reihe an Werten. 340S lang ist die Reihe. Es sollten wohl 3 Aktualisierungen pro Sekunde sein. Das macht dann ca. 1000 Werte. Du meinst also die Werte sollten im Programm berechnet werden, oder eher extern von Hand berechen und dann in das Programm eingeben? Wie lege ich die denn in den Flash/EEPROM.
vorher berechnen und im Flash ablegen. Kann man prima mit Excel machen. Geht aber auch mit Berechnung zur Laufzeit. Wenn du sagst, 3 Aktualisierungen/s hast du doch 333ms Zeit, den nächsten Wert zu berechnen.
3 Aktualisierungen pro Sekunde bedeuten, da0 du 300ms Zeit für die berechnung hast. Wo ist denn dein Problem? Michael
Ich lasse im Main aber eine Schleife laufen. Diese NOP-Schleife bestimmt einfach die Länge des Impulses. Im Timerinterrupt wird die Länge berechnet. Und währende die Berechnung im Timerinterrupt läuft geht eben nix in der Schleife. Siehe Anhang
tschuldigung, oben das ist der falsche Source Code - hier der aktuelle
Mach doch die Frequenz auch mit einem Timer. Dann musst du nur noch alle 330ms das Timerregister aktualisieren.
Mit einem AVR würde ich folgendes machen: Timer0 auf PWM einstellen,der läuft dann alleine. Timer2 Interrupt:output compare register 0 mit Werte aus Tabelle oder berechnete Werten füttern. Arno
Du solltest es genau umgekehrt machen: Die Impulserzeugung mit dem Timer, Berechnung des nächsten Wertes in der Main, dann warten. Ich würde soagar 2 Timer benutzten: Timer0 für die Erzeugung des update-Taktes, Timer1 für die eigentliche Erzeugung des Signals. Timer0: 333ms Interrupt, bewirkt nichts weiter, als einen (vorher berechneten) Wert in eine Variable zu schreiben (nennen wir sie mal reload) und ein Bit (timer_ready) zu setzen. Timer1: Modus toggle OC1 on compare, Interrupt bei compare. Der compare-int macht auch nichts weiter, als den Timer zurückzusetzen und das OCR-Register mit dem reload-Wert zu laden. Ganz einfach, und noch jede Menge Zeit für den MC, sich zu langweilen. main: warten, bis das timer_ready-Bit gesetzt ist, das Bit wieder löschen, den nächsten Wert (reload_next) berechnen, und dann von vorne.
@ crazy horse Wo ist denn der Modus "toggle OC1 on compare" im Danteblatt beschrieben. Es geht um einen ATMEGA8. Ich hab leide nix im Datenblatt gefunden. Sorry, wenn ich heute viel Frage, aber die Zeit drückt extrem.
Mit dem Mega8 wirds noch einfacher (war nicht irgendwo die Rede von 90S2313?), da kannst du noch die CTC-Funktion nutzen (automatisches Rücksetzen des Zählers bei OCR1A). TCCR1A=1<<COM1A0; TCCR1B=(1<<WGM12 | 1<<CS11); TIMSK =1<<OCIE1A; Timer 1 läuft mit clk/8, toggle on OCR1A, Int on OCR1A Den OCR-Int brauchst du eigentlich gar nicht mehr (timer1 reset wird automatisch durchgeführt), die neuen Werte nach OCR1A könntest du von der Timer0-ISR aus reinschreiben. Allerdings musst du dann aufpassen (Zähler liegt bereits über dem neuen OCR-Wert, aber unter dem alten -> in diesem Zyklus wird der Ausgang gar nicht angesteuert). Besser mit OCR-Interrupt, dann kann gar nichts passieren.
TCCR1A=1<<COM1A0; // Toggle OC1A/OC1B TCCR1B=(1<<WGM12 | 1<<CS11); // CTC & clk/8 Takt=2.17014µS TIMSK =1<<OCIE1A; // Timer/Counter Output compare a Match Interrupt enable OCR1AL=943; sollte mir eigentlich 500 Hz bringen - stimmt das?
nö. Der Timer erzeugt ja jeweils nur eine halbe Periode des Ausgangssignals. Willst du 500Hz, brauchst du eine Peridendauer von 2ms, OCR muss also nach 1ms kommen. 1000µs/2.17014µs=475.
1000µs/2.17014µs=460 sagt mir zumindest mein Taschenrechner. Ich messe eine Frequenz von 1124 Hz ---> sagt mir mein MC und das Ozsil. Seltsamer Weise erhalte ich auch bei einem doppeltem Wert von 920 nicht die halbe Frequenz, sondern 1504 Hz.
Nunja, das wird wohl daran liegen, daß für OCR1AL bei 0xFF schluss ist ;) OCR1AL = (460 & 0xFF); OCR1AH = (460 >> 8); Oder bin ich da jetzt auf dem Holzweg?
Achso: Du kannst auch OCR1A = 460; Schreiben, wenn ich das grad richtig gelesen habe...
jo, 460 ist korrekt, hatte ich wohl einen Tipfehler. Hast wahrscheinlich noch einen Fehler beim Laden des OCR1A-Registers. Du musst einen 16bit-Wert schreiben, dabei unbedingt die Reihenfolge beachten (ganz beliebter Anfängerfehler), erst OCR1AH (0x01), dann OCR1AL (0xCC) für 460dez. Einige Compiler unterstützen direkt den 16bit-Zugriff: unsigned int reload; OCR1A=reload;
"ganz beliebter Anfängerfehler" !!!! Was ich gerade damit bewiesen hab!! Dachte ich köönte einfach in das L Byte reinschreiben und es wird dann in H Byte weitergeschreiben. 500 Hz sind da!! Juhu Dann geben ich mich nun mal an die Berechnung meiner Werte. Neben bei mal ganz herzlichen Dank für die Info`s hier.
Nun hab ich Trouble mit dem Timer0. Er läuft nur kurz an und stop anschliessend. weiss einer woran das liegen kann?
Anscheinend stören sich die beiden Timmer. Wenn ich den Timer1 deaktiviere, läuft Timmer 0 durch
Ok die Teimer laufen nun, aber ich erhalte leider keinen Wert aus dem Timer0 zurück. Ich möchte damit die Programmlaufzeit bestimmen um den Wert (t) in die Berechnung der aktuellen Frequenz einfliessen zu lassen. Aber der Wert n_overflows, der mir die Anzahl der der Overflows zurück geben soll, ändert sich nicht. Kann mir da nochmal jemand weiterhelfen?
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.