Hallo.
Ich bin gerade dabei, mit Hilfe mehrerer 2313er für unseren
Bogensportverein eine Turnierampel zu bauen. Ich stehe aber momentan vor
dem Problem, wie ich jetzt am günstigsten drei Taster an den
Mikrocontroller kriege, die alle einen Interrupt 0 auslösen sollen. Das
Entprellen habe ich bereits über Monoflops realisiert, aber ich weis
jetzt einfach nicht, wie ich die beiden Taster, die an Pin PD0 und PD1
liegen, auch an den Interruptpin PD2 kriege, ohne daß ich bei einem
Signal nur an PD2 auch eines an PD0 und PD1 kriege.
Zur Entprellung: ich habe (mußte) sie per Hardware machen, da ich den
Timer bereits für ein exaktes 1sek-Signal brauche.
Falls jemand 'n Vorschlag hat, wäre ich sehr dankbar, ich habe im Moment
irgendwie eine Denkblockade und mir fällt nix ein @_@
MfG,
Maik Schmidt
Hallo,
wenn die Eingänge mit Pullups belegt sind und die Taster/Treiber das
einfach nur auf Masse ziehen, brauchst Du nur vom Int-Pin je eine Diode
zu den Schaltern zu führen um diesen parallel mit auszulösen. So kommst
Du also auf je einen Eingang pro Taster und einen gemeinsamen
Interrupt-Eingang.
Gruß,
Arne
Bis jetzt liegen die Ausgänge der Monoflops (74LS123) direkt an den
Portpins des 2313... aber auf die Idee mit den Dioden bin ich natürlich
sinnigerweise wieder mal nicht gekommen. Dabei sind 5V - 0,7V immer noch
TTL'ige 4,3V high.
Was wäre ein Vorschlag für die Pullups? 1kOhm okay?
Dankend,
Maik Schmidt
Hallo Maik,
es ist schade um die Monoflops.
Der 2313 hat übrigens 2 Timer. Solltest Du aber den anderen Timer
eingesetzt haben, spielt auch das keine Rolle.
Sinnigerweise lässt Du den Timer 0 mit z.B. 10 ms laufen.
Im Timer0-Interrupt läßt Du eine Registervariablen zaehlen.
Von 100 - 0 ergibt dann 1000ms.
Weiterhin kannst Du im Timer-Interrupt deine Tasten einlesen und
entprellen. Das Sekundensignal, wird dadurch nicht ungenauer.
Anmerkung: Genaue Zeiten lassen sich grundsätzlich mit diesen Timern nur
realisieren, indem man den Timer durchlaufen lässt. Da das Aufrufen des
Interrupt nicht immer gleich lange dauert, würde sonst der Reladwert
eventuell 1 oder 2 Takte zu spät in das Timer-Register geschrieben.
Bernhard
Okay, das iss natürlich auch 'ne Lösung, wenn ich noch zusätzliche eine
Zählvariable nutze. Aber was genau iss jetzt mit "Timer durchlaufen
lassen" gemeint? Ich fürchte, da fehlt es mir jetzt an Durchblick. Soll
ich den immer GANZ durchlaufen lassen? Alle 256 Zählstufen und dann auf
den Overflow reagieren?... Da kann ich doch ebenso gut 'n Reload in den
Interrupt packen und als erstes aufrufen.
Ich denke mal, bei maximal 999Sekunden Laufzeit der Uhr und 4MHz Takt
sollte man da doch noch nichts merken.
MfG,
Maik
Hallo Maik,
es ist richtig, bei 1000 Sekunden ist es nicht wichtig, da Du ja nicht
die Relativitätstheorie beweisen willst.
Mit "Durchlaufen lassen" meine ich "nicht reloaden".
Im Interrupt muss du als erstes, die zu nutzenden Register retten.
Spielt aber keine Rolle für das Problem.
Wenn ein Interrupt aufgerufen werden soll, wird erst noch der letzte
Befehl abgearbeitet. Dieser kann aber mehr als einen Zyklus dauern.
Dadurch ist es nicht vorhersehbar wann Du wieder im Interrupt ankommst.
Bei 4 MHz sind das ggf. 2x250ns.
Als kommt dieser Interrupt mit einer Verspätung von immerhin 5%.
Außerdem können sich bei diesem Controller Interrupts nicht gegenseitig
unterbrechen. Folge: Dein externer Interrupt kann den
Timer-Interrupt-Aufruf erheblich verzoegern.
Bernhard
Hallo,
kennt denn der Timer vom 2313er keinen Auto-Reload? Wenn es manuell
machen muß, ist die unberechenbare Zeitverzögerung ja klar.
Entschuldigt die Frage, aber ich kenn bislang nur MCs-51er und die haben
das Problem einfach nicht. Aber man will sich ja weiterbilden... ;-)
Gruß,
Arne
Also, wie ja schon richtig gesagt wirde, kann ein Timer alles machen,
man braucht nicht für jeden Scheiß einen eigenen.
Mann muß nur einen kleinsten gemeinsamen Takt haben, aus dem man dann
mit Registern alle benötigten Vielfachen erzeugt.
Wenns genau sein soll, gibt es prinzipiell 3 Möglichkeiten:
- Timer ohne Reload (Überlauf bei 255 bzw. 65535)
- Timer mit Clear-On-Compare-Match (T1)
- Timer mit Software Reload
Beim Software-Reload ist nur zu beachten, daß man es mit einer Addition
macht, um die variierende Interrupt-Aufruf-Zeit zu berücksichtigen
(Timer läuft ja weiter), z.B.:
in ia, tcnt0
subi ia, timer_reload
out tcnt0, ia
@Arne,
auch beim 8051 braucht man Software-Reload, wenn man einen 16-Bit Timer
haben will und kein T2 da ist:
push psw
clr ea ;no additional delay by other interrupts
clr tr0 ;no overflow during addition
xch a, tl0
add a, #low(8-T0_reload) ;stop for 8 cycle
xch a, tl0
xch a, th0
addc a, #high(8-T0_reload)
xch a, th0
setb ea ;other interrupts enabled after next instr.
setb tr0
pop psw
Peter
@Bernhard
Auch beim AVR ist es möglich, dass weitere Interrupts innerhalb einer
Interrupt-Routine ausgeführt werden können. Dafür gibt es ja den SEI
Befehl.
Und hier die Entprellung mit Timer:
http://www.mikrocontroller.net/forum/read-4-20435.html
Das exakte Software-Reload funktioniert aber nur, wenn man keinen oder
einen sehr großen Vorteiler nimmt.
Ohne Vorteiler muß man beim Reload 1 abziehen.
Mit Vorteiler muß er so groß sein, daß er nie während des Reloads
überlaufen kann, d.h. größer als die Ausführungszeit der anderen
Interrupts oder einer Interruptsperre.
Peter
@Peter
Nicht verfügbarer Timer2 ist der Punkt!
Dennoch würde ich kein Reload wie Du machen, wenn ich die 16Bit des
Timers nicht auswerten muß, sondern einfach eine weiter Variable nehmen
und dann mit
"DJNZ HilfsByte, TimerEnd"
arbeiten. Ebenso läßt sich im Event ZERO das Hilfsbyte auch wunschgemäß
setzen, sowie alg. der Reload-Wert des Timers bis zu einem gewissen
Minimum besser anpassen. Geht schneller und ist genauer.
Gruß,
Arne
@Arne
"Geht schneller und ist genauer."
Weder noch.
Du hast ja im 8-Bit-Mode bis zu 256 mal häufigere Interrupts. D.h. 256 *
DJNZ ist auf alle Fälle langsamer als 1 * 16-Bit Addition.
Genauer ist die 16-Bit-Addition außerdem.
Bei Deiner Variante kann es nämlich zu Problemen kommen, wenn das Reload
des Low-Byte einen Uberlauf bewirken kann.
D.h. nur bei meiner Routine kann man den Reloadwert bequem per
EQU-Anweisung auf wirklich jeden Wert zwischen 256...65535 exakt
einstellen.
Ich benutze sehr oft den AT89C4051 und der hat keinen T2.
Peter
@mikki merten,
die Behauptung Bedarf aber einer genaueren Erläuterung.
Der SEI-Befehl setzt das Global-Interrupt-Flag und ermöglicht es alle
Interrupts ein- bzw. abzuschalten.
Damit kann ich noch lange keinen Interrupt unterbrechen!!
Bernhard
@bernhard
Wenn du innerhalb einer Interrupt-Routine nach dem Retten des SREG
mittels SEI die Interrupts wieder freigibst, kann die gerade
abzuarbeitende Interrupt-Routine von einem weiteren Interrupt
unterbrochen werden. In der Praxis bedeutet dies zum Beispiel ein
Timer-Interrupt, der z.B. jede ms einmal aufgerufen wird und zu
Bearbeitung etwa 30 µs benötigt, kann jederzeit von einem RX/TX
Interrupt der z.B. bei 250 kBit alle 40/44 µs auftritt aber zur
Bearbeitung nur 3-5 µs benötigt unterbrochen werden.
@mikki
Warum soll im Interrupt das Global Interrupt Flag geloescht sein? Der
aktuellen Interrupt wäre dann gar nicht ausgelöst worden!!
Ausserdem habe ich mir gerade die beiden Befehle sei und cli noch einmal
genauer angeschaut. Ich sehe dort keinen Hinweis der in die Richtung
geht.
Wo hast Du diese Information her???
Bernhard
@Bernhard
Wenn die AVR keine verschachtelten Interrupts unterstützen würde, hätte
ich diese wohl schon lange entsorgt. Aber schau mal in den Datenblättern
unter dem Abschnitt "Reset and Interrupt Handling". Dort findest du eine
recht gute Beschreibung.
@mikki
Asche auf mein Haupt.
Du hast recht und das ist auch gut so. Ich habe bisher in den
unkritischen Interrupt immer fast nichts ( oft eigentlich zu wenig )
getan, um die wichtigen nicht zu verzögern.
Danke für den Hinweis.
Bernhard