Forum: Mikrocontroller und Digitale Elektronik Habe Timer Problem


von Yannic W. (Gast)


Lesenswert?

Hallo, ich habe ein Problem mit folgendem code:
1
$regfile = "m16def.dat"
2
$crystal = 16000000
3
$hwstack = 32
4
$swstack = 20
5
$framesize = 40
6
$baud = 9600
7
8
9
Config Portb.3 = Input
10
11
Config Lcdpin = Pin , Db4 = Porta.3 , Db5 = Porta.2 , Db6 = Porta.1 , Db7 = Porta.0 , E = Porta.4 , Rs = Porta.5
12
Config Lcd = 24 * 2
13
Initlcd
14
Cursor Off
15
16
Dim Minuten As Byte
17
Dim Sekunden As Byte
18
Dim Zeit1 As Byte
19
Dim Zeit2 As Byte
20
21
22
Config Timer1 = Timer , Prescale = 256
23
Const Timervorgabe = 3036
24
On Timer1 Timer_irq
25
Enable Interrupts
26
27
28
Minuten = 0
29
Sekunden = 0
30
Zeit1 = 0
31
Zeit2 = 0
32
33
34
Do
35
Locate 1 , 1
36
Lcd Sekunden
37
38
If Pinb.3 = 1 Then
39
   Enable Timer1
40
End If
41
42
Loop
43
44
45
Timer_irq:
46
  Timer1 = Timervorgabe
47
  Incr Sekunden
48
  If Sekunden = 60 Then
49
    Incr Minuten
50
    Sekunden = 0
51
  End If
52
Return

Sobald ich den Taster betätige springt Sekunden sofort auf 1 anstelle 
erst eine Sekunde zu warten. Danach läuft es so wie es soll im 
Sekundentakt. Hat jemand eine Lösung für das Problem ?

mfg Yannic W.

von Stefan B. (stefan) Benutzerseite


Lesenswert?

Beim Enable Timer1 ist deine Timervorgabe noch nicht geladen, d.h. 
Timer1 hat eine Timervorgabe von 0, d.h. der erste Interrupt kommt 
sofort nach dem Enable und dann erst wird kontinuierlich beim Auftreten 
des Interrupts die Timervorgabe neu gesetzt.

von Yannic W. (Gast)


Lesenswert?

Sprich es müsste gehen, wenn ich in die If für den Tasten Taster über 
Enable Timer1 ; Timervorgabe = 3036 setze oder ?

mfg Yannic W.

von Stefan B. (stefan) Benutzerseite


Lesenswert?

Nö.

Timervorgabe ist schon korrekt gesetzt (Const Timervorgabe = 3036), aber 
das ist nur eine Arbeitskonstante. Für den Timer1 bringt das noch 
nichts. Es muss eine Zuweisung an Timer1 dazukommen (so wie in der ISR).

Und damit es einen Effekt hat, muss die Reihenfolge andersrum sein 
(setzen/Zuweisung vorm enable).

If Pinb.3 = 1 Then
   Timer1 = Timervorgabe
   Enable Timer1
End If

von Yannic W. (Gast)


Lesenswert?

Vielen Dank :)

von Yannic W. (Gast)


Lesenswert?

Gut irgendwie war es das wohl doch noch nicht so ganz.

Neuer Code:
1
$regfile = "m16def.dat"
2
$crystal = 16000000
3
$hwstack = 32
4
$swstack = 20
5
$framesize = 40
6
$baud = 9600
7
8
Config Portb.3 = Input
9
10
Dim Minuten As Byte
11
Dim Sekunden As Byte
12
13
Sekunden = 0
14
15
Config Timer1 = Timer , Prescale = 256
16
Const Timervorgabe = 3036
17
Timer1 = Timervorgabe
18
On Timer1 Timer_irq
19
Enable Interrupts
20
21
Do 
22
If Pinb.3 = 1 Then
23
   Gosub Automodus
24
End If
25
Loop
26
27
Automodus: 
28
Enable Timer1
29
30
Do 
31
If Sekunden = 5 Then 
32
Machwas
33
End if 
34
Loop
35
36
37
Timer_irq:
38
  Incr Sekunden
39
  If Sekunden = 60 Then
40
    Incr Minuten
41
    Sekunden = 0
42
  End If
43
Return

Es passiert wieder das gleiche wie vorher.

von Yannic W. (Gast)


Lesenswert?

Keiner mehr eine Idee ?

von Stefan B. (stefan) Benutzerseite


Lesenswert?

1
' Einmalige Initialisierungen: 
2
' BASCOM Interna
3
$regfile = "m16def.dat"
4
$crystal = 16000000
5
$hwstack = 32
6
$swstack = 20
7
$framesize = 40
8
$baud = 9600
9
10
' Einmalige Initialisierungen: 
11
' Variablen
12
Dim Minuten As Byte
13
Dim Sekunden As Byte
14
Sekunden = 0
15
16
' Einmalige Initialisierungen: 
17
' Hardware
18
Config Portb.3 = Input
19
Config Timer1 = Timer , Prescale = 256
20
Const Timervorgabe = 3036
21
Timer1 = Timervorgabe ' #1
22
On Timer1 Timer_irq
23
' #2
24
Enable Interrupts
25
26
' Hauptschleife
27
Do 
28
  If Pinb.3 = 1 Then
29
    Goto Automodus    ' <=== DO LOOP mit GOTO verlassen
30
  End If
31
Loop
32
33
Automodus: 
34
  ' #3
35
  Enable Timer1
36
37
Do 
38
  If Sekunden = 5 Then 
39
    Machwas
40
  End If 
41
Loop
42
End            ' <=== Ende Hauptprogramm
43
44
' Subroutine Timer1 ISR
45
Timer_irq:
46
  Incr Sekunden
47
  If Sekunden = 60 Then
48
    Incr Minuten
49
    Sekunden = 0
50
  End If
51
Return

Eventuell den Code von #1 an Stelle #2 oder Stelle #3 schreiben. Ich 
weiss nicht, ob BASCOM bei On Timer1 Timer_irq zuvor gesetzte Timer1 
Werte in Ruhe lässt bzw. hat das im vorherigen Beispiel an der Stelle 
funktioniert?

von Stefan B. (stefan) Benutzerseite


Lesenswert?

ADD: Und den Timer1 in der Interrupt-Routine neu laden nicht vergessen! 
So wie im ersten Beispiel.

von Yannic W. (Gast)


Lesenswert?

An stelle 3 hatte ich ihn bereits stehen. Brachte aber auch leider 
garnichts.

Hast du ggf. nen Avr da, an dem du den code mal antesten kannst. So 
könnte man wenigstens sicher sein, das es klappt.

von STK500-Besitzer (Gast)


Lesenswert?

Kennt Bascom eigentlich den CTC-Mode?
Da braucht man dann nichts nachladen...

von Stefan B. (stefan) Benutzerseite


Lesenswert?

@  Yannic W.
> An Stelle 3 hatte ich ihn bereits stehen. Brachte aber auch leider
> garnichts.

Hast du das gelesen: Und den Timer1 in der Interrupt-Routine neu laden 
nicht vergessen! So wie im ersten Beispiel.

> Hast du ggf. nen Avr da, an dem du den code mal antesten kannst. So
> könnte man wenigstens sicher sein, das es klappt.

Nur einen Atmega32 oder einen Attiny2313 in anderen Schaltungen, die ich 
aber auseinander pflücken müsste. Jetzt ist es mir ehrlich zu spät, mit 
dem Hardwarefummeln anzufangen. Wenn nix geht, kümmere ich mich morgen 
abend darum. Und ich kann nur mit einer Bascom AVR Demoversion 
aufwarten. Ich hoffe das reicht.

@  STK500-Besitzer
> Kennt Bascom eigentlich den CTC-Mode?
> Da braucht man dann nichts nachladen...

Auf den ersten Blick sehe ich im Manual nichts bei CONFIG ... und ON 
INTERRUPT ... zum Clear Timer on Compare Modus. 
http://avrhelp.mcselec.com/index.html

von Stefan B. (stefan) Benutzerseite


Lesenswert?


von Yannic W. (Gast)


Lesenswert?

So den code hab ich gerade nochmal veruscht.

Klappte aber leider wieder nicht:
1
$regfile = "m16def.dat"
2
$crystal = 16000000
3
$hwstack = 32
4
$swstack = 20
5
$framesize = 40
6
$baud = 9600
7
8
Config Portb.3 = Input
9
10
Config Lcdpin = Pin , Db4 = Porta.3 , Db5 = Porta.2 , Db6 = Porta.1 , Db7 = Porta.0 , E = Porta.4 , Rs = Porta.5
11
Config Lcd = 24 * 2
12
Initlcd
13
Cursor Off
14
15
16
Dim Minuten As Byte
17
Dim Sekunden As Byte
18
Sekunden = 0
19
20
Config Portb.3 = Input
21
22
Config Timer1 = Timer , Prescale = 256
23
Const Timervorgabe = 3036
24
On Timer1 Timer_irq
25
Timer1 = Timervorgabe
26
Enable Interrupts
27
28
29
Do
30
  If Pinb.3 = 1 Then
31
    Goto Automodus
32
  End If
33
Loop
34
35
Automodus:
36
Enable Timer1
37
38
Do
39
Locate 2 , 1
40
Lcd Sekunden
41
  If Sekunden = 5 Then
42
    Locate 1 , 1
43
    Lcd "5 sek"
44
  End If
45
Loop
46
End
47
48
Timer_irq:
49
  Timer1 = Timervorgabe
50
  Incr Sekunden
51
  If Sekunden = 60 Then
52
    Incr Minuten
53
    Sekunden = 0
54
  End If
55
Return

von Stefan B. (stefan) Benutzerseite


Lesenswert?

So ich habe es mit einem schnell zusammengestrickten Atmega32-Aufbau und 
Bascom AVR Demo ausprobiert. Ich habe aber kein LCD angeschlossen und 
keinen Taster.

Geprüft habe ich an einem freien Pin (PORTD.6), den ich auf Output 
gestellt habe und im ersten Versuch im Sekundentakt zwischen 1 und 0 
toggele. Den jeweiligen Zustand messe ich mit einem Spannungsmesser. 
Klappt alles, schöner Wechsel zwischen 5V und 0V im Sekundentakt.

Im zweiten Versuch lasse ich den Pin auf 0 und schalte ihn nur in der 
Sekunde 5 auf 1. Klappt auch. In Sekunde 0 bis 4 0V, dann eine Sekunde 
lang 5V und dann wieder lange 0V.

Lass mal die erste DO LOOP komplett weg, um zu sehen, ob es Probleme mit 
dem Taster gibt und du nie zum Label Automodus und zum Restprogramm 
kommst.

von Yannic W. (Gast)


Lesenswert?

Hmmm, würde das denn Sinn erlgeben ? Ich meine ja nur in die Schleife 
Automodus muss er ja automatisch kommen, da er ja sonst bei echter 
sekunde 4 auf dem display nichts ausgeben würde.

Kann es aber totzdem nochmal ohne die do loop versuchen.

von Yannic W. (Gast)


Lesenswert?

sodale, ich habe es jetzt geschafft, das Problem weitgehend einzugrenzen 
:)

Folgener Code läuft:
1
$regfile = "m16def.dat"
2
$crystal = 16000000
3
$hwstack = 32
4
$swstack = 20
5
$framesize = 40
6
$baud = 9600
7
8
Config Portb.3 = Input
9
10
Config Lcdpin = Pin , Db4 = Porta.3 , Db5 = Porta.2 , Db6 = Porta.1 , Db7 = Porta.0 , E = Porta.4 , Rs = Porta.5
11
Config Lcd = 24 * 2
12
Initlcd
13
Cursor Off
14
15
16
Dim Minuten As Byte
17
Dim Sekunden As Byte
18
Sekunden = 0
19
20
21
Config Timer1 = Timer , Prescale = 256
22
Const Timervorgabe = 3036
23
On Timer1 Timer_irq
24
Timer1 = Timervorgabe
25
Enable Interrupts
26
27
Do
28
Gosub Automodus
29
Loop
30
31
Automodus:
32
33
Enable Timer1
34
35
Do
36
Locate 2 , 1
37
Lcd Sekunden
38
  If Sekunden = 5 Then
39
    Locate 1 , 1
40
    Lcd "5 sek"
41
  End If
42
Loop
43
44
End
45
46
Timer_irq:
47
  Timer1 = Timervorgabe
48
  Incr Sekunden
49
  If Sekunden = 60 Then
50
    Incr Minuten
51
    Sekunden = 0
52
  End If
53
Return

Jetzt stellt sich nur die Frage, wieso geht es mit Taster nicht ?

von Yannic W. (Gast)


Lesenswert?

push

Keiner mehr eine Idee ? Wie schon gesagt liegt es am Taster. Nur wie 
kann ich es nun funktionierend mit Taster hinbekommen ?

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.