Forum: Mikrocontroller und Digitale Elektronik 10 s Timer


von Mr-400-Volt (Gast)


Lesenswert?

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 !!!

von Hannes L. (hannes)


Lesenswert?

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.

...

von André K. (andre-)


Lesenswert?

$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

von Mr-400-Volt (Gast)


Angehängte Dateien:

Lesenswert?

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.

von Hannes L. (hannes)


Lesenswert?

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
Noch kein Account? Hier anmelden.