mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Loop-Schleife unterbrechen?


Autor: Thomas E. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo!

Ich habe folgende Schaltung auf einem Attiny26 am Laufen:
$regfile = "Attiny26.dat"
$crystal = 1000000


Config Pinb.6 = Input
Portb.6 = 1
Config Porta.7 = Output
Config Porta.6 = Output
Config Porta.5 = Output

Led1 Alias Porta.5
Led2 Alias Porta.6
Led3 Alias Porta.7
Taster Alias Pinb.6


Do
   If Taster = 1 Then
      Gosub Tasteraus
   Else
      Gosub Tasterein
   End If
Loop

Tasteraus:
   Led1 = 0
   Led2 = 0
   Led3 = 0
   Wait 1
   Led1 = 1
   Led2 = 1
   Led3 = 1
   Wait 1
Return

Tasterein:
   Led1 = 0
   Led2 = 1
   Led3 = 1
   Waitms 50
   Led1 = 1
   Led2 = 0
   Led3 = 1
   Waitms 50
   Led1 = 1
   Led2 = 1
   Led3 = 0
   Waitms 50
Return

End

Wenn ich jetzt den Taster drücke, läuft erst das Programm Tasteraus 
fertig, ERST DANN springt der Controller auf das Programm Tasterein. Da 
das Programm Tasteraus 2 Sekunden dauert, und ich beispielsweise bei dem 
Umschaltvorgang von Led123=0 auf Led123=1 den Taster drücke, dauert es 
noch eine Sekunde, bis das Programm Tasterein aufgeruden wird.

Wie könnte ich diese Wartezeit verhindern?

Thomas

Autor: Matthias Lipinsky (lippy)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Wie könnte ich diese Wartezeit verhindern?

Anders Programmieren!

So, dass keine Totzeiten durch Delay(wait) entstehen.

Autor: Thomas E. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Und was für Alternativen würden sich da bieten?

Thomas

Autor: Fabian B. (fabs)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Solches "warten" macht man mit Timern. Das geht bestimmt auch in bascom.
Dann brauchste auch gar keine Subs mehr sondern nur den Timerinterrupt 
und eine globale Variable.

Gruß
Fabian

Autor: Matthias Lipinsky (lippy)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Und was für Alternativen würden sich da bieten?


Keine. SOnst bleibts Spaghetticode.

Wie  Fabian B. (fabs) sagte:
-Die Ausgabedaten für die Leds in eine Tabelle packen.
-Über einen Timerinterrupt neue Daten an den AUsgang schaufeln.
-Die Taster ändern nur den Zeiger, der in die Tabelle zeigt.

=> Kein Delay/Wait mehr nötig.

Autor: Timmo H. (masterfx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Keine. SOnst bleibts Spaghetticode.
Kann man mit Basic eigentlich Nicht-Spaghetticode machen? ;-)


>Und was für Alternativen würden sich da bieten?
Wie bereits gesagt. Mach dir einen Timer und für die Taster irgendwie 
globale Flags, die du in der ISR abfragst und entsprechend reagierst.

Autor: Matthias Lipinsky (lippy)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Kann man mit Basic eigentlich Nicht-Spaghetticode machen? ;-)

Stimmt. Wohl eher nicht ;-)

Naja, wollen ja keine Diskussion Bascom/Nicht_bascom lsobrechen hier..

Ich will mal was produktives beisteuern. Ich würds etwa so machen:
(pseudocode)
Tabelle_aus =
(1000, 0,0,0   // für Taste aus
 1000, 1,1,1
    0 );
Tabelle_ein =
(  50, 0,1,1  // für Taste ein
   50, 1,0,1
   50, 1,1,0
    0 );
*******************
globale Variable:  
pointer     = 0
abgelZeit   = 0;
*******************
timer_interrupt_alle_eine_millisekunde
{
  if ( pointer=0) then return;
  if (*pointer=0) then return;
  abgelZeit=abgelZeit + 1;
  if (abgelZeit = *pointer)
  {
    pointer   = pointer + 1;
    led1      = *pointer;
    pointer   = pointer + 1;
    led2      = *pointer;
    pointer   = pointer + 1;
    led3      = *pointer;
    pointer   = pointer + 1;
    abgelZeit = 0;
  }
}
*******************
main
{
  init timer;
  endlosschleife
  {
    if (positiveFlanke_Taste aus) pointer = adresse(Tabelle_aus)
    if (positiveFlanke_Taste ein) pointer = adresse(Tabelle_ein)
  }
}

Autor: Peter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Matthias Beispiel ist aber in C und nicht in Basic. Aber der Ansatz mit 
einem Timer-Interrupt ist sicher die schönste Variante, ich weiss aber 
nicht ob man das mit Basic kann, bzw. weiss nicht wie man das in Basic 
macht.

Aber ich hätte noch einen alternativen Vorschlag:

$regfile = "Attiny26.dat"
$crystal = 1000000


Config Pinb.6 = Input
Portb.6 = 1
Config Porta.7 = Output
Config Porta.6 = Output
Config Porta.5 = Output

Led1 Alias Porta.5
Led2 Alias Porta.6
Led3 Alias Porta.7
Taster Alias Pinb.6

Do
  For i=1 to 10
     If Taster = 1 Then
       If i<6
         Gosub TasterausOff
       Else
         Gosub TasterausOn
       Ensdif
     Else
       Gosub Tasterein
     End If
  next i
Loop

TasterausOff:
   Led1 = 0
   Led2 = 0
   Led3 = 0
   Waitms 100
Return

TasterausOn:
   Led1 = 1
   Led2 = 1
   Led3 = 1
   Waitms 100
Return

Tasterein:
   Led1 = 0
   Led2 = 1
   Led3 = 1
   Waitms 50
   Led1 = 1
   Led2 = 0
   Led3 = 1
   Waitms 50
   Led1 = 1
   Led2 = 1
   Led3 = 0
   Waitms 50
Return

End

Autor: Peter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Oups...

Eine Sekunde ist 10x100ms! Für eine Sekunde sollte es natürlich so sein:

Do
  For i=1 to 20
     If Taster = 1 Then
       If (i < 11)
         Gosub TasterausOff
       Else
         Gosub TasterausOn
       Ensdif
     Else
       Gosub Tasterein
     End If
  next i
Loop

Autor: Matthias Lipinsky (lippy)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Matthias Beispiel ist aber in C und nicht in Basic.

Deshalb habe ich pseudocode drübergeschrieben, weil es nicht exakt C 
ist. DIese bascom kann doch keiner...

@Peter:
Dort sind auch auf wieder Warteschleifen drin, in der Zeit kann nix 
anderes passieren...
Also nur anders programmiert, aber immernoch dasselbe Problem.

Autor: Peter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Deshalb habe ich pseudocode drübergeschrieben, weil es nicht exakt C
>ist. DIese bascom kann doch keiner...
Ich kenne Bascom auch nicht und benutze C. Aber ich habe früher viel in 
Basic programmiert (Atari, Taschenrechner, VBA) und finde es ist bei 
weitem nicht so schlecht wie sein Ruf, schon gar nicht für erste 
Schritte. Es gibt keinen Grund, abschätzig auf den Basic-Programmierern 
rum zu hacken, wie dies hier im Forum offenbar üblich ist. Spagetticode 
hängt vom Programmierer ab, nicht von der Programmiersprache!

>Dort sind auch auf wieder Warteschleifen drin, in der Zeit kann nix
>anderes passieren...
Ich schreibe ja, dass eine Lösung mit Timer-Interrupt die bessere Lösung 
ist.

Meine Variante lösst einfach mal das Problem, dass man bis zu zwei 
Sekunden warten muss, bis ein Tastendruck erkannt wird. Nun wird die 
Taste immerhin alle 100...150ms abgefragt, was im Normalfall schon recht 
praktikabel ist.

Autor: Thomas E. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Peter!

Besten Dank dür deine Hilfe!
Leider gibt mir Bascom eine Fehlermeldung aus, wenn ich versuche, den 
Code zu kompilieren. Weißt du eventuell, woran das liegen könnte?

Thomas

Autor: Paul Baumann (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Vielleicht an "Ensdif" statt "Endif" in der Schleife? ;-)

Wenn Du in Bascom mit der Maus ganz unten auf die Fehlermeldung gehst
und darauf klickst, hüpft der Compiler in die Zeile mit dem Fehler und 
färbt sie rot.

MfG Paul

Autor: Thomas E. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Paul!

Den Schreibfehler bei "End If" habe ich schon lange ausgebessert. Beim 
draufklicken auf die Fehlermeldung springt der in die Zeile
For i=1 to 10

Thomas

Autor: Peter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Vielleicht an "Ensdif" statt "Endif" in der Schleife? ;-)


Tja, das ist natürlich ein Tippfehler und muss natürlich  "End If" 
heissen. Vielleicht gibt's noch weitere Fehler. Der Compiler wird Dir 
schon sagen, wo's noch was zu mekern gibt.

Ich denke du musst auch die Variable i für den Schleifenzähler 
deklarieren, zum Beispiel als Byte.

Autor: Peter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Geht es so auch nicht...?

___________________________________________________

$regfile = "Attiny26.dat"
$crystal = 1000000


Config Pinb.6 = Input
Portb.6 = 1
Config Porta.7 = Output
Config Porta.6 = Output
Config Porta.5 = Output

Led1 Alias Porta.5
Led2 Alias Porta.6
Led3 Alias Porta.7
Taster Alias Pinb.6

Dim i As Byte

Do
  For i = 1 To 20
     If Taster = 1 Then
       If i<11
         Gosub TasterausOff
       Else
         Gosub TasterausOn
       End If
     Else
       Gosub Tasterein
     End If
  Next i
Loop

TasterausOff:
   Led1 = 0
   Led2 = 0
   Led3 = 0
   Waitms 100
Return

TasterausOn:
   Led1 = 1
   Led2 = 1
   Led3 = 1
   Waitms 100
Return

Tasterein:
   Led1 = 0
   Led2 = 1
   Led3 = 1
   Waitms 50
   Led1 = 1
   Led2 = 0
   Led3 = 1
   Waitms 50
   Led1 = 1
   Led2 = 1
   Led3 = 0
   Waitms 50
Return

End

Autor: Thomas E. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Nein leider funktioniert auch dieser Code nicht. Jetzt gibt er schon 
vier Meldungen aus, die alle entweder zu "< 11" führen, oder gegen den 
Befehl "End If" gehen.

Thomas

Autor: Peter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Da hab ich wohl noch das "Then" beim "If i < 11 Then" vergessen...

Autor: AVRFan (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Welches Verhalten soll das Programm überhaupt realisieren?

Autor: Thomas E. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Werds heute mal versuchen, Peter.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Thomas E. wrote:
> Nein leider funktioniert auch dieser Code nicht. Jetzt gibt er schon
> vier Meldungen aus, die alle entweder zu "< 11" führen, oder gegen den
> Befehl "End If" gehen.^

Nur so als Hinweis:
Sehr oft ist der Text einer Fehlermeldung hilfreich beim Suchen
nach dem Fehler

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.