PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Hilfe bei Zeitsteuerung



Blamaster
21.02.2008, 11:23
Hallo ich möchte in Bascom eine Zeitsteuerung umsetzen. Das klappt vom Grundprinzip auch. Nur aus irgendeinem Grund geht der Zähler um 1 sek vor.

Code(aufs wichtige reduziert):



$crystal = 16000000
.....
Config Portb.3 = Input
.....
Dim Minuten As Byte
Dim Sekunden As Byte
.....
Config Timer1 = Timer , Prescale = 256
Const Timervorgabe = 3036
On Timer1 Timer_irq
Enable Interrupts
.....
Minuten = 0
Sekunden = 0
.....
Do
If Pinb.3 = 1 Then
Gosub Automodus
End If
Loop
.....
Automodus:
Enable Timer1
Do
Locate 2 , 1
Lcd Sekunden
If Minuten = 0 And Sekunden = 10 Then
"Mach was"
End If
Loop
.....
Timer_irq:
Timer1 = Timervorgabe
Incr Sekunden
If Sekunden = 60 Then
Incr Minuten
Sekunden = 0
End If
Return


Jemand eine Idee wodran das liegen kann ?

mfg Blamaster

askazo
21.02.2008, 12:02
If Sekunden = 60 Then
Incr Minuten
Sekunden = 0
Hier liegt der Fehler, würde ich sagen.
Eine Uhr Springt von der 60. Sekunde auf die erste Sekunde der neuen Minute. Bei dir gibt es noch eine "nullte" Sekunde, Deine Minute hat so also 61 Sekunden. Wenn Du nach dem hochzählen der Minute die Sekunde also auf 1 setzt, sollte es stimmen.

askazo

Blamaster
21.02.2008, 12:12
Stimmt. Daran hatte ich nicht gedacht. Ändert aber bei meinem Code ja trotzdem nicht wirklich was, da er ja ab der 1. sekunde falsch zählt und das halt schon bevor die 1. Minute rum ist.

zerush
21.02.2008, 12:23
If Sekunden = 60 Then
Incr Minuten
Sekunden = 0
Hier liegt der Fehler, würde ich sagen.
Eine Uhr Springt von der 60. Sekunde auf die erste Sekunde der neuen Minute. Bei dir gibt es noch eine "nullte" Sekunde, Deine Minute hat so also 61 Sekunden. Wenn Du nach dem hochzählen der Minute die Sekunde also auf 1 setzt, sollte es stimmen.

askazo

Ich glaube du irrst dich:

Eine Uhr zählt ja von X:00 bis X:59..
d.h. wenn du die 60.sekunde hast, musst du die minute um 1 erhöhen und die sekungen auf null setzen:
0:58 - 0:59 - 1:00

Das sollte so stimmen!

@Blamaster:
Was genau ist denn jetzt das Problem?
Fängt er einfach bei 1 an zu zählen, aber sonst klappt alles?

Blamaster
21.02.2008, 12:27
jenau das ist es. und somit wird die aktion schon nach 4 anstelle der angegebenen 5 sekunden ausgeführt.

zerush
21.02.2008, 12:34
Ich kenne mich jetzt mit Bascom leider nicht so genau aus, wie Bascom den Timer konfiguriert.
Aber wenn er beispielsweise bei 0 anfängt, unf herunter zählen lässt, bekommst du logischerweise direkt am Anfang einen IRQ und somit steht der Zähler schon am Anfang auf einer Sekunde.

edit: sorry ich bin grad irgendwie nich beim AVR gewesen, der müsste eigentlich immer hochzählen!
Aber vielleicht wird der zähler am anfang irgendwie vorgeladen und erreicht daher direkt einen overflow?!?
Am besten mal debuggen und schauen wie die Timer Register aussehen, nachdem der Timer initialisiert wurde!

Blamaster
21.02.2008, 13:13
Und wie genau geht das?

"Am besten mal debuggen und schauen wie die Timer Register aussehen, nachdem der Timer initialisiert wurde!"

Blamaster
21.02.2008, 14:52
Update.

Hab ebend gerade in die Timer_irq nochmal eine Lcd Ausgabe gesetzt, um zu sehen wann der Timer Interrupt das 1. mal ausgelöst wird.

Sobald ich den Taster drücke springt er sofort in die Timer_irq.

Woran kann das liegen ?

zerush
21.02.2008, 15:11
Ja also das debuggen funktioniert nur, wenn du einen JTAG Programmierer hast. Hat Bascom nicht auch einen Simulator? Dann könnte man da einfach mal gucken wie die Timer Register gesetzt werden.

Versuche mal unter
Const Timervorgabe = 3036
direkt den Timer1 zu setzten:
Timer 1 = Timervorgabe

Blamaster
21.02.2008, 15:56
Hmmmm, bringt leider auch nichts. Kann es daran liegen, das Enabel Interrupts schon erfolgt, bevor der Taster gedrückt wurde ?

Eins ist aufjedenfall sicher, der 1. Interrupt Aufruf erfolgt nicht nach einer Sekunde.

zerush
21.02.2008, 16:36
Enable Interrupts aktiviert diese nur, ausgelöst werden kann er aber noch nicht, da der Timer noch nicht läuft. Eigentlich sollte der Timer IRQ erst ausgelöst werden, wenn er einen Überlauf verursacht. Dies geschieht scheinbar direkt am Anfang..

Greifst du irgendwo im Programm noch auf den Timer zu?

Blamaster
21.02.2008, 16:54
Nein. Das ist die einzige Stelle. Muss jede sub bzw. interrupt schleife eigentlich durch etwas beendet werden ?

T.b.

Test:

Do

Loop

Timer_irq:
.....
Return

Sprich die Test: endet ja nicht mit return oder end sub oder sowas. Aber das sollte doch auch keine Rolle spielen oder?

zerush
21.02.2008, 17:31
Theoretisch müssten die auch beendet werden (ich glaube bei bascom gibts nen END SUB oder sowas, weiß ich aber nicht genau).
Ausmachen dürfte es jedoch, aufgrund der DO .. LOOP geschichte, nichts, weil er da ja eh nicht mehr raus kommt..

Versuch mal:
...
Automodus:
Enable Timer1
Timer1 = Timervorgabe
Do
...

Wenn er dann auch direkt reinspringt versuche es mal so:
...
Automodus:
Timer1 = Timervorgabe
Enable Timer1
Do
...

Berichte mal was sich tut...

Blamaster
21.02.2008, 18:05
Es passiert genau das gleiche wie vorher auch.

Blamaster
21.02.2008, 18:15
Um 100% ausschließen zu können das der Rest von meinem code bzw. Programm damit etwas zu tun hat, habe ich nun nochmal ein ganz neues erstellt, nur mit nem Taster, nem Timer und einem Display.

Es passiert wieder das gleiche wie vorher. Aber so kann ich jetzt den ganzen code posten, das ist dann vielleicht etwas leichter.



$regfile = "m16def.dat"
$crystal = 16000000
$hwstack = 32
$swstack = 20
$framesize = 40
$baud = 9600


Config Portb.3 = Input

Config Lcdpin = Pin , Db4 = Porta.3 , Db5 = Porta.2 , Db6 = Porta.1 , Db7 = Porta.0 , E = Porta.4 , Rs = Porta.5
Config Lcd = 24 * 2
Initlcd
Cursor Off

Dim Minuten As Byte
Dim Sekunden As Byte
Dim Zeit1 As Byte
Dim Zeit2 As Byte


Config Timer1 = Timer , Prescale = 256
Const Timervorgabe = 3036
On Timer1 Timer_irq
Enable Interrupts


Minuten = 0
Sekunden = 0
Zeit1 = 0
Zeit2 = 0


Do
Locate 1 , 1
Lcd Sekunden

If Pinb.3 = 1 Then
Enable Timer1
End If

Loop


Timer_irq:
Timer1 = Timervorgabe
Incr Sekunden
If Sekunden = 60 Then
Incr Minuten
Sekunden = 0
End If
Return


So kann jetzt auch nochmal beschreiben was passiert. Avr wird angeschlossen, auf dem Display wird die 0 gezeigt. Ich drücke den Taster die 0 springt sofort zu einer 1 um, danach erhöht sich die Zahl im Sekundentakt.

mfg Blamaster

zerush
21.02.2008, 18:47
Wie sieht es denn aus, wenn du in der if Abfrage erst den Timer enablest und dann die Interrupts? Also oben dann das Enable Interrupts weg...

Ehrlich gesagt habe ich jetzt auch keine Ideen mehr. :(

helimike0705
21.02.2008, 18:58
schreibe mal in deine pin abfrage anstatt " Enable Timer1 "
"gosub Timer_irq".
kenn mich zwar nicht so gut mit timern aus aber probiere mal aus.

gruß mike

Blamaster
21.02.2008, 19:23
Das hätte ja zum effekt das er genauso sofort in die interrupt schleife springt. Und wenn Enable Timer1 nicht gesetzt wird, zählt der timer auch nichts ;)

Blamaster
21.02.2008, 19:29
Wie sieht es denn aus, wenn du in der if Abfrage erst den Timer enablest und dann die Interrupts? Also oben dann das Enable Interrupts weg...

Ehrlich gesagt habe ich jetzt auch keine Ideen mehr. :(

Habs gerade versucht, wiedermal vergebens. Irgendwie hab ich das gefühl das dort etwas verdammt faul ist.

Hat denn jamnd die Möglichkeit den code mal auf nem avr laufen zu lassen ?