Nun, der Atmega8 hat nur 2 I/O-Pins (PD2 & PD3) die man als Interrupt verwenden kann.
Damit kommen wir zur 2. Lösung und zwar mit dem Timer-Interrupt. Mit dieser Lösung können wir sogar mehr I/O-Pins verwenden, somit mit mehr Tastern arbeiten.
Timer-Interrupt
Der Atmega8 bietet zwei Timer an (Timer0 und Timer1). Ein Timer kann man als einen integrierten Zähler bezeichnen.
Der Timer0 ist ein 8-bit Timer, somit arbeitet er von 0-255 (2 hoch 8 = 256).
Der Timer1 ist ein 16-bit Timer, somit arbeitet kann er von 0-65535 zählen (2 hoch 16 = 65536)
Durch folgende Befehle konfigurieren wir und aktivieren den Timer sowie Interrupt:
Code: Alles auswählen
Config Timer0 = Timer , Prescale = 8 '->Timer0 wird konfiguriert, Prescale = ist der Teiler
On Ovf0 Unserunterprogramm_isr '->Bei Overflow soll er das "Unserunterprogramm_isr" aufrufen
Enable Timer0 '->Aktivierung Timer0
Enable Interrupts '->Aktivierung Interrupt
Der Prescale ist der Teiler. Mit diesem Teiler können wir die Timer-Geschwindigkeit/Durchslaufanzahl verringern. Es gibt verschiedene Teilerwerte: 1 , 8, 64, 256 oder 1024.
Wenn unser Atmega8 mit 1 Mhz getaktet ist sind es 1 000 000 hz.
Die 1000000 müssen durch den Teiler geteilt werden und anschließend durch 256 (für den Overflow).
z.B.:
Bei einem Teiler 1:
1000000/1/256= 3906,25 mal. In einer Sek. würde 3906,25 mal ein Overflow bzw. ISR stattfinden.
Bei einem Teiler 8:
1000000/8/256= 488,28 mal. In einer Sek. würde 488,28 mal ein Overflow bzw. ISR stattfinden.
In dem Unterprogramm soll er die IF-Funktion mit der Überprüfung nach dem Taster ausführen.
Um nicht das Hauptprogramm zusätzlich zu verlangsamen verwenden wir einen Prescaler von 8. Welches locker aureichend. Denn bei fast jeder zweiten Milisekunden findet eine Ausführung des Unterprogramms statt.
In dem Unterprogramm könnte man sogar mehrere IF-Abfragen zu mehreren Tasten durchführen.
Der gesamte fertige Code mit dem Unterprogramm/ISR sieht dann so aus:
Code: Alles auswählen
$regfile = "m8def.dat"
$crystal = 1000000
Config Pind.5 = Output
Config Pind.6 = Output
Config Pind.2 = Input
Config Timer0 = Timer , Prescale = 8
On Ovf0 Unserunterprogramm_isr
Enable Timer0
Enable Interrupts
Taster1 Alias Pind.2
Led1 Alias Portd.5
Led2 Alias Portd.6
Do
Led1 = 1
Waitms 1000
Led1 = 0
Waitms 1000
Led2 = 1
Waitms 1000
Led2 = 0
Waitms 1000
Loop
Unserunterprogramm_isr:
If Taster1 = 1 Then
Led1 = 1
Led2 = 1
Waitms 500
Led1 = 0
Led2 = 0
End If
Return
Wer schon mal programmiert und mit Variablen gearbeitet hat, kann sich das Durchlesen der Erklärung fast sparen
Einer Variabel kann ein Wert/Zeichen zugewissen werden. Die Variabel speichert sich den Wert/Zeichen und zum späteren Zeitpunkt kann man durch ansprechen der Variabel den Wert/Zeichen gelesen und z.B. weiterverarbeitet werden.
Mit folgendem Befehl wird eine Variabel deklariert:
Code: Alles auswählen
Dim Vari1 As Integer
Typ "Integer" kann ein Wert von -32767 bis +32768 speichern
Typ "Byte" von 0 - 255
Weitere Typen kann man in der Hilfe von Bascom finden.
Mit diesem Befehl kann man der Variabel einen Wert zuweisen:
Code: Alles auswählen
Vari1 = 1000
Code: Alles auswählen
Vari1 = Vari1 + 100
Beim Typ "Byte" kann ein Overflow bzw. Überlauf statt finden. Wenn 255 erreicht sind und man erhöht es um eine 1, so springt es auf 0 und zählt weiter. Genauso umgekehrt mit dem subtrahieren...
Nun fragt Ihr euch bestimmt, wozu Variabel gut sind? Für PWM (Dimmen) benötigt man z.B.: Variabel, um die Helligkeit bzw. Frequenz zuändern.
PWM (Dimmen)
Um eine PWM zu erzeugen, muss die Leds ganz schnell ein- und ausgeschaltet werden.
Es gibt verschiedene Lösungen dafür:
Die einfachste Lösung wäre mit Pause:
Code: Alles auswählen
Led1 = 1
Waitms 1
Led1 = 0
Waitms 10
Möchte man die Frequenz über Tastern ändern können, so muss man mit Variablen arbeiten, hier der ganze Code:
Code: Alles auswählen
$regfile = "m8def.dat"
$crystal = 1000000
Config Pind.5 = Output
Config Pind.6 = Output
Config Int0 = Rising
Config Int1 = Rising
Enable Interrupts
Enable Int0
Enable Int1
On Int0 Unterprogramm
On Int1 Unterprogramm2
Dim Laenge As Byte
Laenge = 0
Led1 Alias Portd.5
Led2 Alias Portd.6
Do
Led1 = 1
Waitms 1
Led1 = 0
Waitms Laenge
Loop '
Unterprogramm:
Laenge = Laenge + 1
Return
Unterprogramm2:
Laenge = Laenge - 1
Return
Der 1. Taster erhöht die Auszeit somit verringert es die Helligkeit. Ab eine bestimmte Anzahl fängt die Led an sichtbar zu blinken.
Mit 2. Taster verringert man die Auszeit. Somit erhöht man die Helligkeit.
Eine viel bessere Lösung ist über eine IF-Schleife, damit lässt sich die Helligkeit über eine Variabel von 0-254 bestimmen:
Code: Alles auswählen
$regfile = "m8def.dat"
$crystal = 1000000
Config Pind.5 = Output
Config Pind.6 = Output
Config Pind.2 = Input
Config Int0 = Rising
Config Int1 = Rising
Enable Interrupts 'einschalten der Interrupts
Enable Int0
Enable Int1
On Int0 Unterprogramm
On Int1 Unterprogramm2
Dim Zaehler As Byte
Dim Laenge As Byte
Laenge = 254
Led1 Alias Portd.5
Led2 Alias Portd.6
Do
If Zaehler > Laenge Then Led1 = 1 Else Led1 = 0
Zaehler = Zaehler - 1
Loop '
Unterprogramm:
Laenge = Laenge + 1
Return
Unterprogramm2:
Laenge = Laenge - 1
Return
Wenn die Variabel "Zaehler" größer als "Laenge" ist. Wird die Led leuchten.
Die Variabel "Zaehler" wird nach jedem Durchlauf um 1 vermindert. Sobald 0 erreicht ist, fängt es wieder von 255 an.
Je größer der Wert "Laenge" (max. 254) ist, umso seltener wird die Led leuchten, denn nur wenn Zaehler=255 ist bzw. größer als "Laenge" leuchtet die Led. Je kleiner der Wert "Laenge" ist, desto häufiger wird die Led leuchten.