Bascom Unerklärlicher Fehler im Programm

OP Persönliche Seite #1990419
Lesenswert?

So Hi!

Da ich seit langem nicht mehr programmiert habe, habe ich jetzt versucht 
ein Bascom Programm zu schreiben, welches einen Servo steuert und 
welchen man mit 2 Tastern ansteuern können sollte.

Jetzt habe ich ein wenig rumprogrammiert und habe ein Programm erstellt, 
was eigentlich genau das machen sollte. Jedoch "hängen" sich die 
Interrupts von beiden Tastern immer nach 2-3 ich hatte schon mal 6 
Betätigungen geschafft - auf und der Wert bleibt bei weiterer Betätigung 
unverändert.

Ich kann mir jedoch nicht diesen Fehler erklären, ich denke aber, dass 
ein problem mit dem vom servo-befehl verwendeten timer0 und den 
Interrupts int0 und int1 besteht.

Hoffentlich kann mir jemand helfen.

Schon mal besten Dank im Voraus,
       hani
1
$regfile = "m48def.dat"
2
$crystal = 16000000
3
$hwstack = 100
4
$swstack = 100
5
$framesize = 100
6

7
'Variablen des Servos und Warten
8
Dim Wert As Byte
9
Dim Warten As Bit
10
Wert = 100
11

12
'2 Subs deklarieren
13
Declare Sub On_int0
14
Declare Sub On_int1
15

16
'LCD Initialisieren
17
Config Lcdpin = Pin , Db4 = Portc.2 , Db5 = Portc.3 , Db6 = Portc.4 , _
18
   Db7 = Portc.5 , E = Portc.1 , Rs = Portc.0
19
Config Lcd = 16 * 2
20
Cls
21
Cursor Off
22

23
'PD2(Int0) und PD3(INT1) als Eingang , PD7 und PD7 als Servo und PB0 als Ausgang(LED)
24
Config Portd.3 = Input
25
Config Portd.7 = Output
26
Config Portb.0 = Output
27
Config Servos = 1 , Servo1 = Portd.7 , Reload = 10
28

29
'Pullups für PD2 und PD3
30
Portd.2 = 1
31
Portd.3 = 1
32

33
'Erste Displayausgabe
34
Locate 1 , 1
35
Lcd "Wert:"
36
Locate 2 , 1
37
Lcd Wert
38
Servo(1) = Wert
39

40
'Beide Interrups bei fallender Flanke
41
Config Int0 = Falling
42
Config Int1 = Falling
43

44
' "Sprungziel" für Interrupts
45
On Int0 On_int0
46
On Int1 On_int1
47

48
'Interrupts aktivieren
49
Enable Int0
50
Enable Int1
51
Enable Interrupts
52

53
'LED einschalten
54
Portb.0 = 1
55

56
'Hauptschleife
57
Do
58

59
   Toggle Portb.0                                           'LED wechseln
60
   Waitms 100                                               'Warten
61

62
   If Warten = 1 Then                                       'Wenn Wartezustand,
63
      Waitms 900                                            'Dann Pause
64
      Enable Int0
65
      Enable Int1                                           'Interrupts wieder aktivieren
66
      Enable Interrupts
67
      Warten = 0                                            'Wartezustand deaktivieren
68
   End If
69

70
Loop
71

72

73
Sub On_int0:                                                'Subprogramm Wert um 1 reduzieren und ausgeben
74
   Wert = Wert - 1
75
   Locate 2 , 1
76
   Lcd Wert ; "  "
77
   Servo(1) = Wert
78
   Disable Int0
79
   Disable Int1
80
   Warten = 1
81
End Sub
82

83
Sub On_int1:                                                'Subprogramm Wert um 1 erhöhen und ausgeben
84
   Wert = Wert + 1
85
   Locate 2 , 1
86
   Lcd Wert ; "  "
87
   Servo(1) = Wert
88
   Disable Int1
89
   Disable Int0
90
   Warten = 1
91
End Sub
Angehängte Dateien:
Gast #1990458
Lesenswert?

Hallo,
Du solltest "disableinterrupts" als ersten Befehl in der Interruptrutine
ausführen und "enableinterrupts" als letzten.
Ansonsten solltest Du das ganze Konzept nochmals überarbeiten.
z.B. Tasten im 10-tel Sekundentakt pollen und nicht mit Intterupt.

Gruß Jürgen
#1990670
Lesenswert?

Es hülfe ganz enorm, wenn man mal das Bascom-Manual lesen würde.
Es gibt nämlich speziell für Tastenabfragen den Debounce-Befehl.

Tasten mit externen Interrupts sind dagegen die schlechteste Lösung, 
weil sie fast nie funktionieren und deutlich aufwendiger sind.


Peter
OP Persönliche Seite #1990723
Lesenswert?

OK, Gut danke für die Vörschläge   werde mal schauen, dass ich die so 
schnell wie möglich implementiere.

Zum einem Ursprünglich hatte ich den gesamten code im"Interruptbereich 
stehen, samt der pause und es hatte auch funktioniert, aber nach dem 
tastendruck verging immer erst 1Sek(die pause), bis sich der servo 
ausrichtete   und ich denke mal, dass das daran lag, da der int0 eine 
höhere priorität besitzt als der timer0 - dene ich?

Danach hatte ich mich mit dem debounce in der hauptschleife versucht - 
jedoch wollte es ums verre**** nicht fuktionieren - aber egal ich 
probiers jetzt dann noch mal mit dem debounce.

Sollte es dann etwa so aussehen:?
also die interruptdeklartation weglassen und dann in der Hauptschleife:
1
Do
2
   Debounce Portd.2 , 0 , On_int0 , Sub
3
   Debounce Portd.3 , 0 , On_int0 , Sub
4
   Toggle Portb.0
5
   Waitms 100
6
loop
?
OP Persönliche Seite #1990741
Lesenswert?

Markus H. schrieb:
> so
> schnell wie möglich implementiere

Also Gut - gesagt-getan:

Jetzt zeigt sich mein avr, wie bereits heute schon einmal gänzlich 
unbeeindruckt von einem Tastendruck und die led blinkt munter vor sich 
weiter

Oweeehhh  und jetzt?
1
'PD2(Int0) und PD3(INT1) als Eingang , PD7 und PD7 als PB0(Servo) und PB0 als Ausgang(LED)
2
Config Portd.3 = Input
3
Config Portd.7 = Output
4
Config Portb.0 = Output
5
Config Servos = 1 , Servo1 = Portd.7 , Reload = 10
6

7
'Pullups für PD2 und PD3
8
Portd.2 = 1
9
Portd.3 = 1
10

11
'Erste Displayausgabe
12
Locate 1 , 1
13
Lcd "Wert:"
14
Locate 2 , 1
15
Lcd Wert
16
Servo(1) = Wert
17

18
'LED einschalten
19
Portb.0 = 1
20

21
'Hauptschleife
22
Do
23
   Debounce Portd.2 , 0 , On_int0 , Sub
24
   Debounce Portd.3 , 0 , On_int0 , Sub
25
   Toggle Portb.0                                           'LED wechseln
26
   Waitms 100                                               'Warten
27
Loop
28

29

30
Sub On_int0:                                                'Subprogramm Wert um 1 reduzieren und ausgeben
31
   Wert = Wert - 1
32
   Locate 2 , 1
33
   Lcd Wert ; "  "
34
   Servo(1) = Wert
35
End Sub
36

37
Sub On_int1:                                                'Subprogramm Wert um 1 erhöhen und ausgeben
38
   Wert = Wert + 1
39
   Locate 2 , 1
40
   Lcd Wert ; "  "
41
   Servo(1) = Wert
42
End Sub
Angehängte Dateien:
OP Persönliche Seite #1990826
Lesenswert?

Gott sei Dank, dass hier auch einige nachtaktive sind.
Sollter da der Compiler nicht eine Fehlermeldung ausgeben ? Naja egal - 
Jetzt funktonierts endlich.

Vielen Dank an euch Alle für die schnelle Hilfe!

Aber ich denke ich werde doch irgendwann auf eine andere Sprache, wie 
z.B. C Umsteigen müssen, denn ich finde mich in einer "klaren, strengen 
Syntax" besser zurecht, denn wegen dem einen blöden Fehler hat das ganze 
"Projekt" gesponnen.

Also nochmals vielen Dank und zuletzt noch den fertigen code:
1
$regfile = "m48def.dat"
2
$crystal = 16000000
3
$hwstack = 100
4
$swstack = 100
5
$framesize = 100
6

7
'Variable des Servos
8
Dim Wert As Byte
9
Wert = 100
10

11
'2 Subs deklarieren
12
Declare Sub On_int0
13
Declare Sub On_int1
14

15
'LCD Initialisieren
16
Config Lcdpin = Pin , Db4 = Portc.2 , Db5 = Portc.3 , Db6 = Portc.4 , _
17
   Db7 = Portc.5 , E = Portc.1 , Rs = Portc.0
18
Config Lcd = 16 * 2
19
Cls
20
Cursor Off
21

22
'PD2(Int0) und PD3(INT1) als Eingang , PD7 und PD7 als PB0(Servo) und PB0 als Ausgang(LED)
23
Config Portd.3 = Input
24
Config Portd.7 = Output
25
Config Portb.0 = Output
26
Config Servos = 1 , Servo1 = Portd.7 , Reload = 10
27

28
'Pullups für PD2 und PD3
29
Portd.2 = 1
30
Portd.3 = 1
31

32
'Erste Displayausgabe
33
Locate 1 , 1
34
Lcd "Wert:"
35
Locate 2 , 1
36
Lcd Wert
37
Servo(1) = Wert
38

39
'LED einschalten
40
Portb.0 = 1
41

42
'Hauptschleife
43
Do
44
   Debounce Pind.2 , 0 , On_int0 , Sub
45
   Debounce Pind.3 , 0 , On_int1 , Sub
46
   Toggle Portb.0                                           'LED wechseln
47
   Waitms 100                                               'Warten
48
Loop
49

50

51
Sub On_int0:                                                'Subprogramm Wert um 1 reduzieren und ausgeben
52
   Wert = Wert - 1
53
   Locate 2 , 1
54
   Lcd Wert ; "  "
55
   Servo(1) = Wert
56
End Sub
57

58
Sub On_int1:                                                'Subprogramm Wert um 1 erhöhen und ausgeben
59
   Wert = Wert + 1
60
   Locate 2 , 1
61
   Lcd Wert ; "  "
62
   Servo(1) = Wert
63
End Sub
Angehängte Dateien:
#1990845
Lesenswert?

Hallo Markus H

.. der Peter Dannegger hat eigentlich schon ein wenig recht..
allerdings muss ich sagen, dass ich mit Tastenabfragen über
einen externen Int eigentlich glücklich bin.
Ich benötige dann nur eine Hardwareentprellung für alle Tasten.

Dein Problem liegt aber in deinem Programm.

Du musst dein programm etwa so schreiben:

Do

If Taste1gedrückt = 1 then

Tu was ich will
Taste1gedrückt = 0 <- zurücksetzen

end if

Loop

END


INT Routine:

Frage Port ab
Wenn Pin_x = 1 then Taste1gedrückt = 1

Return




*****************
Zudem kann man in Bascom niemal einen LCD Befehl in eine INT Routine 
setzen.
Das geht immer schief

Gruss Klaus
#1990889
Lesenswert?

Klaus De lisson schrieb:
> Zudem kann man in Bascom niemal einen LCD Befehl in eine INT Routine
> setzen.
> Das geht immer schief

Käse, kann man, ist aber normalerweise kontraproduktiv, weil das LCD die 
Kiste mächtig bremst ... ist "unschön"
hat aber auch nix mit Bascom zu tun, würde in ASM genauso die Bremse 
rein hauen. Für Tastenabfrage braucht man aber auch keine Int 
normalerweise, weil die Systembremse eh vor den Tasten sitzt oder steht.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren