PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Stoppuhr



derpedi
13.12.2009, 13:38
Hallo!
ich bin gerade dabei mir eine Stoppuhr zu bauen, welche die Zeit zwischen Schalter1 und Schalter2 stoppt - in sekunden und milisekunden

kann mir vielleicht jmd helfen, mit der Bascom-Hilfe komme ich nicht weit.

Thomas$
13.12.2009, 13:43
setzt mal den code rein damit man sehen kann wie weit du bist.
ansonsten sieh dir die timer funktion an und externen interuppt

derpedi
13.12.2009, 14:34
also so sollte es irgendwie aussehen,
mir fehlt halt noch die stoppuhrfunktion, ich weiß nicht wie ich die hochzählen lassen soll


$regfile = "M8def.dat"
$crystal = 16000000
$hwstack = 100
$swstack = 100
$framesize = 100


Dim Millisekunden As Byte
Dim Minuten As Byte
Dim Sekunden As Byte





Config Portc = Output
Config Pinb.1 = Input
Config Pinb.3 = Input
Portb.1 = 0
Portb.7 = 0



Do

Config Timer1 = Timer , Prescale = 64
Const Timervorgabe = 40536
If Pinb.1 = 0 Then
On Timer1 Timer_irq

Print "schalter 1"
Enable Interrupts
end if

Millisekunden = 00
Minuten = 0
Sekunden = 0



' - - - - - - -





If Pinb.3 = 1 Then
Print "schalter 2"
Disable Timer1

Print "Zeit: " ; Minuten ; ":" ; Sekunden ; ":" ; Millisekunden ; " "


End If

Loop

Che Guevara
13.12.2009, 15:54
Hallo derpedi,

sieh dir mal folgenden code an:



$regfile = "m8def.dat"
$crystal = 16000000
$baud = 19200
$framesize = 40
$hwstack = 40
$swstack = 40


Config Pind.2 = Input
Config Pind.3 = Input
Portd.2 = 1
Portd.3 = 1

Dim Millisekunden As Word
Dim Sekunden As Byte
Dim Minuten As Byte
Dim Stoppuhr_flag As Bit
Const Timer1_vorgabe = 49536
Stoppuhr_flag = 0

Config Int0 = Falling
On Int0 Stoppuhr_starten
Enable Int0

Config Int1 = Falling
On Int1 Stoppuhr_stoppen
Enable Int1

Config Timer1 = Timer , Prescale = 1
Timer1 = Timer1_vorgabe
On Timer1 Stoppuhr
Stop Timer1
Enable Timer1

Enable Interrupts


Do

If Stoppuhr_flag = 1 Then
Reset Stoppuhr_flag
Print "Minuten: " ; Minuten ; " Sekunden: " ; Sekunden ; " Millisekunden: " ; Millisekunden
Print "Zeit (MM:SS:mm): " ; Minuten ; ":" ; Sekunden ; ":" ; Millisekunden
End If

Loop

End

Stoppuhr_starten:
Start Timer1
Return

Stoppuhr_stoppen:
Stop Timer1
Set Stoppuhr_flag
Return

Stoppuhr:
Timer1 = Timer1_vorgabe
Incr Millisekunden
If Millisekunden = 1000 Then
Millisekunden = 0
Incr Sekunden
End If
If Sekunden = 60 Then
Sekunden = 0
Incr Minuten
End If
Return


Zu deinem Code kann ich nur folgendes sagen:
1. "Configs" sollten immer vor dem Mainloop, am Anfang des Programms stehen
2. Gewöhn dir bitte einen strukturierten Programmierstil an, das ist leicher für dich selbst und auch für die Leser deines Codes.

Das soll jetzt keine Beleidigung/Demütigung o.ä. sein, sondern nur eine "Hilfestellung".

Gruß
Chris

Sauerbruch
13.12.2009, 21:47
...ich hätte auch noch ´n paar Tips:

Config Pinb.1 = Input
Config Pinb.3 = Input
Portb.1 = 0
Portb.7 = 0

I/O-Ports muss man nicht extra als Eingang konfigurieren - das sind sie von ganz alleine, wenn man den Controller hochfährt. Das hat mit den "DDR"-Registern zu tun, die initial alle auf &B00000000 stehen.

Gleiches gilt für die Port-Register (z.B. PORTB.1 oder PORTB.7) - auch die sind automatisch 0, unless otherwise noted :-)

Mit "Enable TimerX" und "Disable TimerX"hält man den Timer mitnichten an - man aktiviert bzw. deaktiviert nur den Interrupt der ausgelöst wird, wenn der Timer überläuft. Was Du meinst ist "Start TimerX" und "Stop TimerX".

(To be continued...)

So ´ne Stoppuhr ist für´s erste natürlich ein ganz schön sportliches Projekt... und wenn´s als ganzes nicht geht, kann man kaum herausfinden, wo der Fehler liegt. Hast Du denn schon mal einfachere Dinge probiert, wie z.B.

- den Timer-Überlauf mit ´ner LED bei verschiedenen Preloads darzustellen?

- externe und interne Interrupts auszulösen?

- Eingangspins abzufragen?

etc., etc... Anhand so kleiner Mini-Projekte kann man am besten den Umgang mit den unzähligen Möglichkeiten lernen, die einem Bascom bietet. Ich selbst habe übrigens den "Durchbruch" geschafft, als ich mir das Buch von Roland Walter gekauft habe. Ist didaktisch wärmstens zu empfehlen, und voller sehr lehrreicher Mini-Codes für alle wesentlichen Funktionen eines Mikrocontrollers einschließlich UART- und TWI-Kommunkation, ADC-Wandler etc., etc.

derpedi
22.01.2010, 18:53
Hey,
nach sehr langer Winterpause habe ich mich heute mal wieder mit meiner Stoppuhr beschäftigt. Und sie ist fertig und funktioniert. zwar leider nicht ganz genau, bei 60sek habe ich eine abweichung von 2,8 sekunden oder so. Aber sie misst quasi auf die viertelsekunde genau
weiß jmd auf welchen startwert ich den timer setzen muss damit ich bei einem prescaler von 64 genau 0.25 sekunden bekomme? - 16mhz

und wie kann ich noch einen 3. schalter dazu bekommen, so etwas wie eine reset taste zu sein? so dass ich wieder neu die zeit stoppen kann.





$regfile = "M8def.dat"
$crystal = 16000000
$baud = 9600




Config Portc = Output ' Kompletter C Port Output
Config Pinb.0 = Input ' Eingang 1
Config Pinb.1 = Input ' Eingang 2

Portb.0 = 0
Portb.1 = 1

Do

If Pinb.0 = 1 Then ' Startknopf


Print "Start"
Enable Interrupts
Enable Timer1 ' Timer: GO

Dim W As Word
Dim A As Integer
Dim B As Integer
Dim C As Integer

Config Timer1 = Timer , Prescale = 64
A = 0 ' A = 1/4 Sekunden
B = 0 ' B = ganze Sekunden 1 - 9
C = 0 ' C = 10er Zahlen


W = Timer1
Timer1 = W

Do


On Timer1 Isr_timer1

Loop



Isr_timer1:
Print "interrupt!" ; W
A = A + 1
If A = 4 Then
B = B + 1
A = 0
End If
If B = 10 Then
C = C + 1
B = 0
End If
Print "A=" ; A
Print "B=" ; B
Print "C=" ; C
W = 0




End If

' Stoppknopf
If Pinb.1 = 0 Then ' Timer STOPP
Stop Timer1

If A = 1 Then
Print "Das waren " ; C ; B ; "," ; "25 Sekunden"
End If

If A = 2 Then
Print "Das waren " ; C ; B ; "," ; "5 Sekunden"
End If

If A = 3 Then
Print "Das waren " ; C ; B ; "," ; "75 Sekunden"
End If

If A = 0 Then
Print "Das waren " ; C ; B ; "," ; A ; " Sekunden"
End If




End If


Return

Loop

yaro
22.01.2010, 19:18
Hallo derpedi,
ich kenn mich mit Basic nicht so gut aus, kann dir aber sagen, dass du, wenn du geschickt programmierst mit deiner Hardware eine Genauigkeit von 2-3µs bekommen kannst.

Gruß, Yaro

for_ro
22.01.2010, 20:32
Setze dies
Timer1=62500
als ersten Befehl in die Isr_timer1, dann kommt der Interrupt exakt nach 0,25 Sekunden.
Aber:
Der On Timer1 Befehl sollte vor die Do...Loop.
Du musst die Prints aus der ISR nehmen. Die Ausführung dauert so lange, dass der nächste Interrupt schon wieder ansteht.
Wenn du unbedingt eine Ausgabe willst, dann
- setze in der ISR nur ein Flag
- prüfe dies in der Do...Loop ab
- setze das Flag zurück
- führe die Print Befehle aus.

Besserwessi
23.01.2010, 01:31
Ein Problem für die Genauigkeit kann es schon sein wenn der Timer Startwert jedesmal per Hand gesetzt wird. Mit den vorteiler 64 mag das gerade noch gehen, es kann aber gelegentlich Fehler geben.
Der Timer 1 hat auch einen mode bei dem die Hardware immer nur bis zu einem bestimmten Wert Zählt (CTC Mode).

Die Variablendeklaration gehört vor den eigentlichen Code. Die ISR kommt in der regel ganz ans Ende, nicht irgendwo in die Hauptschleife, und dazu noch mitten in ein IF... . Ein wunder das der Compliler sich da nicht beschwert.

derpedi
07.03.2010, 16:46
Ich kenne mich wirklich nicht allzu gut mit Bascom und Programmierung allgemein aus, vielleicht könnt ihr nochmal drüber schauen ob alles gut aussieht. funktionieren tuts

siehts gut aus?




$regfile = "M8def.dat"
$crystal = 16000000
$baud = 9600




Config Portc = Output ' Kompletter C Port Output
Config Pinb.0 = Input ' Eingang 1
Config Pinb.1 = Input ' Eingang 2

Portb.0 = 0
Portb.1 = 1


Dim W As Word
Dim A As Integer
Dim B As Integer
Dim C As Integer

Do

Config Timer1 = Timer , Prescale = 64
A = 0 ' A = 1/4 Sekunden
B = 0 ' B = ganze Sekunden 1 - 9
C = 0 ' C = 10er Zahlen


W = Timer1
Timer1 = 62500

If Pinb.0 = 1 Then
Sound Portb.0 , 200 , 500 ' Startknopf


Print "Start"
Enable Interrupts
Enable Timer1 ' Timer: GO




' angeblich jetzt alle 0,25s




On Timer1 Isr_timer1
Do
Loop



Isr_timer1:
'Print "interrupt!" ; W
A = A + 1
If A = 4 Then
B = B + 1
A = 0
End If
If B = 10 Then
C = C + 1
B = 0

End If


Print C ; B ; " Sekunden"




End If

' Stoppknopf
If Pinb.1 = 0 Then ' Timer STOPP
Stop Timer1
Sound Portb.0 , 200 , 500
Waitms 10
Sound Portb.0 , 200 , 500

If A = 1 Then
Print "Das waren " ; C ; B ; "," ; "25 Sekunden"
End If

If A = 2 Then
Print "Das waren " ; C ; B ; "," ; "5 Sekunden"
End If

If A = 3 Then
Print "Das waren " ; C ; B ; "," ; "75 Sekunden"
End If

If A = 0 Then
Print "Das waren " ; C ; B ; "," ; A ; " Sekunden"
End If




End If


Return


Loop

Besserwessi
07.03.2010, 18:02
Wenn funktioniert ist gut, gut aussehen tut's aber nicht. Der Code ist immer noch fast so schlecht sortiert wie zuvor.

Mich wundert es, daß sich der Compiler nicht über die Unordnung beschwert.

peterfido
07.03.2010, 21:37
Meine StopUhr läuft recht genau. Den Code habe ich auf dem anderen Rechner.
Die Werte allerdings im Kopf...
Timer0
Quarzoszillator: 4 MHZ
Timerstartwert: 100
Prescaler 256
damit zählt er quasi die 100stel Sekunden.
Am Ende der Messung die Hundertstel Sekunden durch 600 teilen und vom Wert abziehen.
Wenn lZeit also die 100stel beinhaltelt:

lMerker = lzeit/600
lzeit=lzeit-lmerker

Dann nur noch die hundertstel in Stunden, Minuten, Sekunden, hundertstel aufteilen.