www.mikrocontroller.net

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


Autor: Markus H. (haniham) Benutzerseite
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht 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
$regfile = "m48def.dat"
$crystal = 16000000
$hwstack = 100
$swstack = 100
$framesize = 100

'Variablen des Servos und Warten
Dim Wert As Byte
Dim Warten As Bit
Wert = 100

'2 Subs deklarieren
Declare Sub On_int0
Declare Sub On_int1

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

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

'Pullups für PD2 und PD3
Portd.2 = 1
Portd.3 = 1

'Erste Displayausgabe
Locate 1 , 1
Lcd "Wert:"
Locate 2 , 1
Lcd Wert
Servo(1) = Wert

'Beide Interrups bei fallender Flanke
Config Int0 = Falling
Config Int1 = Falling

' "Sprungziel" für Interrupts
On Int0 On_int0
On Int1 On_int1

'Interrupts aktivieren
Enable Int0
Enable Int1
Enable Interrupts

'LED einschalten
Portb.0 = 1

'Hauptschleife
Do

   Toggle Portb.0                                           'LED wechseln
   Waitms 100                                               'Warten

   If Warten = 1 Then                                       'Wenn Wartezustand,
      Waitms 900                                            'Dann Pause
      Enable Int0
      Enable Int1                                           'Interrupts wieder aktivieren
      Enable Interrupts
      Warten = 0                                            'Wartezustand deaktivieren
   End If

Loop


Sub On_int0:                                                'Subprogramm Wert um 1 reduzieren und ausgeben
   Wert = Wert - 1
   Locate 2 , 1
   Lcd Wert ; "  "
   Servo(1) = Wert
   Disable Int0
   Disable Int1
   Warten = 1
End Sub

Sub On_int1:                                                'Subprogramm Wert um 1 erhöhen und ausgeben
   Wert = Wert + 1
   Locate 2 , 1
   Lcd Wert ; "  "
   Servo(1) = Wert
   Disable Int1
   Disable Int0
   Warten = 1
End Sub

Autor: Jürgen (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Peter Diener (pdiener) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Markus H. (haniham) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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:
Do
   Debounce Portd.2 , 0 , On_int0 , Sub
   Debounce Portd.3 , 0 , On_int0 , Sub
   Toggle Portb.0
   Waitms 100
loop
?

Autor: Markus H. (haniham) Benutzerseite
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht 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?
'PD2(Int0) und PD3(INT1) als Eingang , PD7 und PD7 als PB0(Servo) und PB0 als Ausgang(LED)
Config Portd.3 = Input
Config Portd.7 = Output
Config Portb.0 = Output
Config Servos = 1 , Servo1 = Portd.7 , Reload = 10

'Pullups für PD2 und PD3
Portd.2 = 1
Portd.3 = 1

'Erste Displayausgabe
Locate 1 , 1
Lcd "Wert:"
Locate 2 , 1
Lcd Wert
Servo(1) = Wert

'LED einschalten
Portb.0 = 1

'Hauptschleife
Do
   Debounce Portd.2 , 0 , On_int0 , Sub
   Debounce Portd.3 , 0 , On_int0 , Sub
   Toggle Portb.0                                           'LED wechseln
   Waitms 100                                               'Warten
Loop


Sub On_int0:                                                'Subprogramm Wert um 1 reduzieren und ausgeben
   Wert = Wert - 1
   Locate 2 , 1
   Lcd Wert ; "  "
   Servo(1) = Wert
End Sub

Sub On_int1:                                                'Subprogramm Wert um 1 erhöhen und ausgeben
   Wert = Wert + 1
   Locate 2 , 1
   Lcd Wert ; "  "
   Servo(1) = Wert
End Sub

Autor: mue_C (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Eingänge fragt man immer noch über PinD.2 und PinD.3 ab.

Autor: Markus H. (haniham) Benutzerseite
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht 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:
$regfile = "m48def.dat"
$crystal = 16000000
$hwstack = 100
$swstack = 100
$framesize = 100

'Variable des Servos
Dim Wert As Byte
Wert = 100

'2 Subs deklarieren
Declare Sub On_int0
Declare Sub On_int1

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

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

'Pullups für PD2 und PD3
Portd.2 = 1
Portd.3 = 1

'Erste Displayausgabe
Locate 1 , 1
Lcd "Wert:"
Locate 2 , 1
Lcd Wert
Servo(1) = Wert

'LED einschalten
Portb.0 = 1

'Hauptschleife
Do
   Debounce Pind.2 , 0 , On_int0 , Sub
   Debounce Pind.3 , 0 , On_int1 , Sub
   Toggle Portb.0                                           'LED wechseln
   Waitms 100                                               'Warten
Loop


Sub On_int0:                                                'Subprogramm Wert um 1 reduzieren und ausgeben
   Wert = Wert - 1
   Locate 2 , 1
   Lcd Wert ; "  "
   Servo(1) = Wert
End Sub

Sub On_int1:                                                'Subprogramm Wert um 1 erhöhen und ausgeben
   Wert = Wert + 1
   Locate 2 , 1
   Lcd Wert ; "  "
   Servo(1) = Wert
End Sub

Autor: Klaus De lisson (kolisson)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Weingut Pfalz (weinbauer)
Datum:

Bewertung
0 lesenswert
nicht 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

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.