Eine typische Anwendung für einen Mikrocontroller
ist ein Zeitschalter. Ein Eingangssignal z.B. von einem Schalter wird erkannt,
und darauf ein Ausgang für eine gewisse Zeit eingeschaltet. Ist ja ganz
einfach. Aber was ist, wenn man zwei oder mehr Eingänge hat und mehrere
Vorgänge unabhängig voneinander auslösen will? Der Mikrocontroller müsste dann
quasi gleichzeitig auf alle Eingänge achten, und sich quasi gleichzeitig um
mehrere Ausgänge kümmern. Gebraucht wird also eine Art Multitasking. Hier wird ein ATmega32 verwendet.
Die Aufgabe ist mit einer Timer-Prozedur lösbar. Die Eingänge werden dann zwar auch nicht wirklich gleichzeitig ausgewertet, sondern sehr schnell hintereinander. Aber die Prozedur wird in schneller Folge immer wieder aufgerufen. Wenn dies 100-mal in der Sekunde passiert, ist die Reaktionszeit auf ein Ereignis maximal 10 ms. Für viele Aufgaben geht das als Echtzeit durch.
Im ersten
Versuch soll nur der Timer 0 eingerichtet werden und eine Interruptprozedur mit
100 Hz laufen. Damit man etwas sieht, wird eine LED getoggelt. Sie flackert
dann mit 50 Hz. Zur Überprüfung wird ein Zähler i1 erhöht. Im Hauptprogramm
wird alle 1000 ms der Zählerstand an das Terminal gesendet. Der Zählerstand
erhöht sich jedes Mal um 100. Man weiß also, dass die 10 ms stimmen.
Im nächsten Schritt werden in der Timerprozedur zwei Eingänge abgefragt und zwei Ausgänge beschaltet. Zu jedem Vorgang soll ein Zähler i1, i2 usw. als Zeitgeber gehören. Damit wird eine Art Uhr für jeden Vorgang gebildet. Am Anfang muss ein Eingang für mindestens 30 ms low sein, damit ein gültiges Signal erkannt wird. So wird eine Entprellung erreicht. Dann läuft die Uhr weiter und bestimmt, wie lange ein Ausgang eingeschaltet werden soll. Erst wenn der Vorgang beendet wird, wird der Zähler wieder auf 0 gesetzt und ist dann erst bereit für ein neues Ereignis.
'Bascom ATmega32, Eingänge, Zeitsteuerung, Ausagänge
$regfile = "m32def.dat"
$crystal = 11059200
$hwstack = 16
$swstack = 32
$framesize = 32
Baud = 9600
Dim i1, i2, i3, i4 as Integer
Config Portd = &B00110000
Portd.2 = 1
Portd.3 = 1
Portd.6 = 1
Portd.7 = 1
Config Timer0 = Timer , Prescale = 1024
Enable Interrupts
Enable Timer0
On Timer0 Tim0isr
Do
Loop
'11,0592 MHz / 1024 / 108 = 100 Hz
Tim0isr:
timer0=256-108
'Eingang D2, Timer i1, Ausgang D4
if pind.2=0 AND i1<3 then i1=i1+1 ' Taste gedrückt?
if i1<3 AND pind.2=1 then i1=0 ' Entprellung
if i1 > 2 then i1 = i1 + 1 ' Timer läuft
if i1 = 4 then portd.4=1 ' Impuls Start
if i1 = 104 then portd.4=0 ' 1 s, Impuls Ende
if i1 = 104 then i1=0 ' Timer Stop
'Eingang D3, Timer i2, Ausgang D5
if pind.3=0 AND i2<3 then i2=i2+1 ' Taste gedrückt?
if i2<3 AND pind.3=1 then i2=0 ' Entprellung
if i2 > 2 then i2 = i2 + 1 ' Timer läuft
if i2 = 4 then portd.5=1 ' Impuls Start
if i2 = 204 then portd.5=0 ' 2 s, Impuls Ende
if i2 = 204 then i2=0 ' Timer Sto
Return
End
Hier werden die Eingänge angefragt D2 und D3 und die Ausgänge D4 und D5 gesteuert. Das passt zu den Tasten S1 und S2 auf dem ES-M32 und zu den beiden LEDs. Mit einem Druck auf S1 wird LED1 für eine Sekunde eingeschaltet. Mit einem Druck wird S2 für zwei Sekunden eingeschaltet. Beide Vorgänge funktionieren völlig unabhängig voneinander. Man kann also die Taster gleichzeitig oder nacheinander drücken. Die jeweilige Zeit startet mit dem Druck auf den jeweiligen Taster.
Tim0isr:
timer0=256-108
'Eingang D2, Timer i1, Ausgang D4
if pind.2=0 AND i1<3 then i1=i1+1 ' Taste 1 gedrückt?
if i1<3 AND pind.2=1 then i1=0 ' Entprellung
if i1 > 2 then i1 = i1 + 1 ' Timer läuft
if i1 = 4 then portd.4=1 ' Impuls Start
if i1 = 104 then portd.4=0 ' 1 s, Impuls Ende
if i1 = 104 then i1=0 ' Timer Stop
'Eingang D3, Timer i2, Ausgang D5
if pind.3=0 AND i2<3 then i2=i2+1 ' Taste 2 gedrückt?
if i2<3 AND pind.3=1 then i2=0 ' Entprellung
if i2 > 2 then i2 = i2 + 1 ' Timer läuft
if i2 = 4 then portd.5=1 ' Impuls Start
if i2 = 204 then portd.5=0 ' 2 s, Impuls Ende
if i2 = 204 then i2=0 ' Timer Stop
'Eingang D3, Timer i3, Ausgang D5
if pind.6=0 AND i3<3 then i3=i3+1 ' Taste 3 gedrückt?
if i3<3 AND pind.6=1 then i3=0 ' Entprellung
if i3 > 2 then
i3 = i3 + 1 ' Timer läuft
if i3 = 4 then portd.5=1 ' Impuls Start
if i3 = 34 then portd.5=0 ' 300 ms, Impuls Ende
if i3 = 64 then portd.5=1 ' Impuls Start
if i3 = 94 then portd.5=0 ' 300 ms, Impuls Ende
if i3 = 124 then portd.5=1 ' Impuls Start
if i3 = 154 then portd.5=0 ' 300 ms, Impuls Ende
if i3 = 154 then i3=0 ' Timer Stop
end if
Ein drittes
Ereignis wurde noch hinzugefügt, wobei diesmal gleich drei Impulse erzeugt
werden. Der zugehörige Code ist etwas länger. Damit nicht jede if-Abfrage
behandelt werden muss, auch wenn sie gerade nicht aktuelle ist, werden die Ausgaben
in eine if-Schleife gesetzt, die davon abhängt ob das Ereignis gestartet wurde.
Wenn nämlich sehr viele Zeilen in der Interruptprozedur stehen, sollte die
Abarbeitung niemals länger als 10 ms dauern.