Loop-Schleife unterbrechen?

Gast #845767
Lesenswert?

Hallo!

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

4

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

11
Led1 Alias Porta.5
12
Led2 Alias Porta.6
13
Led3 Alias Porta.7
14
Taster Alias Pinb.6
15

16

17
Do
18
   If Taster = 1 Then
19
      Gosub Tasteraus
20
   Else
21
      Gosub Tasterein
22
   End If
23
Loop
24

25
Tasteraus:
26
   Led1 = 0
27
   Led2 = 0
28
   Led3 = 0
29
   Wait 1
30
   Led1 = 1
31
   Led2 = 1
32
   Led3 = 1
33
   Wait 1
34
Return
35

36
Tasterein:
37
   Led1 = 0
38
   Led2 = 1
39
   Led3 = 1
40
   Waitms 50
41
   Led1 = 1
42
   Led2 = 0
43
   Led3 = 1
44
   Waitms 50
45
   Led1 = 1
46
   Led2 = 1
47
   Led3 = 0
48
   Waitms 50
49
Return
50

51
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
Gast #845874
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.
#845893
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.
Gast #845899
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)
1
Tabelle_aus =
2
(1000, 0,0,0   // für Taste aus
3
 1000, 1,1,1
4
    0 );
5
Tabelle_ein =
6
(  50, 0,1,1  // für Taste ein
7
   50, 1,0,1
8
   50, 1,1,0
9
    0 );
10
*******************
11
globale Variable:  
12
pointer     = 0
13
abgelZeit   = 0;
14
*******************
15
timer_interrupt_alle_eine_millisekunde
16
{
17
  if ( pointer=0) then return;
18
  if (*pointer=0) then return;
19
  abgelZeit=abgelZeit + 1;
20
  if (abgelZeit = *pointer)
21
  {
22
    pointer   = pointer + 1;
23
    led1      = *pointer;
24
    pointer   = pointer + 1;
25
    led2      = *pointer;
26
    pointer   = pointer + 1;
27
    led3      = *pointer;
28
    pointer   = pointer + 1;
29
    abgelZeit = 0;
30
  }
31
}
32
*******************
33
main
34
{
35
  init timer;
36
  endlosschleife
37
  {
38
    if (positiveFlanke_Taste aus) pointer = adresse(Tabelle_aus)
39
    if (positiveFlanke_Taste ein) pointer = adresse(Tabelle_ein)
40
  }
41
}
Gast #846017
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
Gast #846022
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
Gast #846035
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.
Gast #846206
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.
Gast #846482
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
Gast #846520
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.
Gast #846531
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
#850417
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

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