Hallo, ich habe ein Programm geschrieben, das eine 5-ton folge filtert und einen b.z.w. mehrere Ausgänge schaltet. Wie programmiere ich eine art Timer, der den programmablauf nicht stört, und einen Ausgang nach 10 Sec. auf 0 setzt ? Das Programm ist mit Bascom für einen 2313 geschrieben. Danke !!!
Dein Programm hat doch sicherlich irgendein "Zeitnormal", also eine Stelle im Programm, die rythmisch in gleichbleibenden Zeitabständen erreicht wird (bei mir ist das immer ein Timer-Interrupt, allerdings in ASM). An dieser Stelle zählt man eine Variable hoch, die von allen Programmteilen als "Softwaretimer" oder "Uhr" gesehen werden kann. Beim Setzen des Ausgangs (nach Empfang der gültigen Tonfolge) wird nun der Stand der "Uhr" (als Kopie) geholt, soviele Einheiten dazu addiert, wie 10 Sekunden entsprechen und dieser Wert in einer Variablen gemerkt. Für jeden Schaltausgang gibt es dann diese Variable. In der Mainloop (dein Programm hat doch eine, oder?) werden dann in regelmäßigen Abständen die Ausschaltzeitpunkte mit dem Stand der Uhr verglichen und bei Ablauf (Gleichstand) der jeweilige Ausgang zurückgesetzt. In BASCOM kann ich das aber leider nicht, mit BASCOM komme ich nicht klar, ich schreibe in ASM. ...
$crystal = 4000000 config timer1= timer, prescale= 1024 start timer1 sei on timer1 t1isr const t1x= $676a 'blaaaaaaaaaaah.... set ausgang timer1 =t1x enable timer1 'blaaaaaaaaaaah.... end t1isr: reset ausgang disable timer1 return
Danke für die Antworten. Also mein Programm sieht wie folgt aus.... Das problem ist, das die Ports D5 und D6 nach dem einschalten nach 10 s abschalten sollen, der programm ablauf aber nicht gestört werden darf.
Du lässt also Timer1 frei durchlaufen und nutzt derzeit nur den ICP-Interrupt. Das ist schonmal gut. (es sind alle Wege offen...) Da du mit 8MHz und Vorteiler 1 arbeitest, läuft der Timer alle 8,192ms über. Dies kannst du in einem weiteren Interrupt nutzen (ein Timer1OVF-Interrupt), in dem du eine weitere Variable (Byte) erhöhst, und bei 122 (entspricht 1 Sekunde) auf 0 setzt und einen Sekundenzähler (Byte) erhöhst. Das ist im Int schon alles. Denn die ISR soll ja so kurz wie möglich sein, damit der Capture-Int nicht blockiert wird. In Main wird dann der Sekundenzähler mit den "Weckzeiten" (für jeden abzuschalteten Kanal getrennt) verglichen und bei Gleichstand der betreffende Ausgang abgeschaltet. Wird ein Ausgang eingeschaltet, dann setzt du "seine Weckzeit" auf den momentanen Stand des Sekundenzählers + 10. Somit wird 10 Sekunden später Gleichstand erreicht und der Port abgeschaltet. Mir ist aufgefallen, dass du in der ISR "oncapture" den Timer1 einliest (Zaehler=Timer1). Wird damit der aktuelle Timerstand eingelesen, oder der Stand des ICP-Registers von Timer1? Falls möglich, dann solltest du das ICP-Register einlesen (ich weiß aber nicht, wie das in BASCOM heißt, in ASM heißt es ICR1H/ICR1L), da dann die Messung bedeutend genauer wird. Schau dir mal die Architektur des Timers im AVR-Datenblatt an, dann weißt du was ich meine. Andere Variante: Da du in der Mainloop "in jeder Runde" 2ms wartest, kannst du die Verzögerung auch aus der Mainloop generieren (also ohne OVF-Int). Zähle einfach eine 16-Bit-Variable (unsigned-int) hoch, das dauert etwa 131s bis zum Überlauf. Eine Sekunde entspricht etwa 500, für 10 Sekunden müsstest du also 5000 zum aktuellen Stand addieren. Der Vergleich geht wie oben beschrieben, nur dass es mehr RAM verbraucht und mehr Maschinencode (Flash) erzeugt, da mit 16 Bit gearbeitet wird. Viel Erfolg... ...HanneS...
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.