PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Counter als Zeitgeber



kawamaha
13.02.2010, 13:48
hallo,

ich nehme meistens counter als timer her. wenns genauer gehen muß nen timer als takt und counter zum vervielfachen. im folgenden beispiel blinkt sekbyte im sekundentakt (nicht genau, aber das spielt hier keine rolle) und minbyte soll alle 9 sek blinken.
meine problem: manchmal blinkt minbyte alle 9 sek, manchmal alle 10 sek.
irgendwie denk ich, liegt es daran dass ich bei xxxbyte=0 gleichzeitig ein anderes byte runterzählen lasse und das xxxbyte wieder auf den anfangswert setze.
läuft jetzt die schleife nochmal durch und xxxbyte ist immer noch 0, dann wird eben das andere byte nochmal runtergezählt.
so ganz hab ich das leider noch nicht kapiert, wann ein befehl gelesen wird und wann er ausgeführt wird.
oder liegts an was anderem :? :? :?


$regfile = "attiny26.dat"
$crystal = 1000000

Ddrb = &B00011100 'Bit 0, 1 auf Eingang
Portb = &B00000011



Config Timer0 = Timer , Prescale = 1024 'Timer0 als timer definieren, teiler 1024 '
Const Preset = 5 'zählt von 1 bis 255


On Timer0 Marke
Timer0 = 230

Enable Timer0
Enable Interrupts

Dim Sekbyte As Byte
Dim Minbyte As Byte
Sekbyte = 0
Minbyte = 9

Do

If Sekbyte < 5 Then
Portb.4 = 1
Else
Portb.4 = 0
End If

If Sekbyte = 20 Then
Decr Minbyte
End If

If Sekbyte = 20 Then
Sekbyte = 0
End If

If Minbyte = 9 Then
Portb.3 = 1
Else
Portb.3 = 0
End If

If Minbyte = 0 Then
Minbyte = 9
End If

Loop


Marke:
Timer0 = 230
If Pinb.0 = 0 Then
Incr Sekbyte
End If

Return

Vitis
13.02.2010, 17:34
Was meinst du mit


so ganz hab ich das leider noch nicht kapiert, wann ein befehl gelesen wird und wann er ausgeführt wird.

Prinzipiell werden alle Befehle nacheinander ausgeführt, Schritt für Schritt
wie sie im Programm stehen, es sein denn :) es gibt immer ein "Aber" es kommt ein Interrupt dazwischen. Dann wird nämlich Dein Programmablauf an der Stelle unterbrochen und die ISR, die Interrupt Service Routine, ausgeführt, es sein denn ... und da gibts dann wieder ein Aber, zumindest beim AVR, der Controller ist schon am Abarbeiten einer anderen ISR ;)
Du hast eine Abfrage " = 20" drinnen für den Sekundenzähler, doch was passiert, wenn der Zähler 20 erreicht, aber in der Mainloop noch nicht wieder an der Abfragestelle ankommt und die ISR nochmal ausgelöst wird? ... er zählt auf 21 weiter und die Bedingung wird nicht ausgeführt, erst wieder wenn der Zähler die 255 überlaufen hat und wieder bei 0 anfängt zu zählen.

Probiers mal so:




$regfile = "attiny26.dat"
$crystal = 1000000

$hwstack = 32 ' default use 32 for the hardware stack
$swstack = 10 ' default use 10 for the SW stack
$framesize = 20

Ddrb = &B00011100 'Bit 0, 1 auf Eingang
Portb = &B00000011

Config Timer0 = Timer , Prescale = 1024 'Timer0 als timer definieren, teiler 1024 '
On Timer0 Marke
Timer0 = 230n

Enable Timer0
Enable Interrupts

Const Preset = 5 'zählt von 1 bis 255



Dim Sekbyte As Byte
Dim Minbyte As Byte
Sekbyte = 0
Minbyte = 9

Do

If Sekbyte < 5 Then
Portb.4 = 1
Else
Portb.4 = 0
End If

If Sekbyte > 19 Then
Decr Minbyte
Sekbyte = Sekbyte - 20
End If

If Minbyte = 0 Then
Minbyte = 9
End If

If Minbyte = 9 Then
Portb.3 = 1
Else
Portb.3 = 0
End If

Loop


Marke:
Timer0 = 230
If Pinb.0 = 0 Then
Incr Sekbyte
End If

Return
End

kawamaha
14.02.2010, 09:04
Danke!!!
funktionieren tuts, muß mir nur mal in ner ruhigen minute durch den kopf gehen lassen, warums funktioniert :-b

Vitis
14.02.2010, 12:46
Da liegt das "Geheimnis":


If Sekbyte > 19 Then
Decr Minbyte
Sekbyte = Sekbyte - 20
End If