Forum: Mikrocontroller und Digitale Elektronik Bascom Unerklärlicher Fehler im Programm


von Markus H. (haniham) Benutzerseite


Angehängte Dateien:

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

von Jürgen (Gast)


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

von Peter D. (pdiener) Benutzerseite


Lesenswert?

Wenn einer der Interrups auftritt und zwar genau hier dazwischen

      Enable Interrupts
--->
      Warten = 0

dann wird der Interrupt ausgeführt, dort warten auf 1 gesetzt, das 
danach im Hauptprogramm gleich wieder auf 0 und dann die Interrupts nie 
wieder eingeschaltet.

Grüße,

Peter

von Peter D. (peda)


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

von Markus H. (haniham) Benutzerseite


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
?

von Markus H. (haniham) Benutzerseite


Angehängte Dateien:

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

von mue_C (Gast)


Lesenswert?

Eingänge fragt man immer noch über PinD.2 und PinD.3 ab.

von Markus H. (haniham) Benutzerseite


Angehängte Dateien:

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

von Klaus D. (kolisson)


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

von Weingut P. (weinbauer)


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.

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.