Bascom BASCOM ; Erste Schritte zum Ausprobieren

Unter aufräumen würde ich verstehen, die Teile mit der Roten Led zu entfernen, da diese zum lernen und verstehen vorgesehen war.
 
Ja ok, das auch, wenn du das nicht mehr brauchst.
Ich meine eher den Rattenschwanz zu kürzen. Also die Teilprogramme auszulagern. Sprich in der Hauptschleife (Main Loop) nur noch bei Bedarf Unterprogramme aufzurufen. So wie beim Taster. Die Grüne(?) Timer LED würde ich aber erst mal noch drin lassen. Nur als Indikator bei der Fehlersuche dass der Timer noch läuft.

Dein Programm ist jetzt noch recht klein, aber glaub mir, Quelltexte >1000 Zeilen sind keine Seltenheit. Wenn da auch noch zigfach ineinander verschachtelt wird, du findest dich nicht mehr zurecht. Daher lieber auslagern. Ist zwar nicht ganz so optimal was die Performance angeht (für die Sprünge werden ein paar Taktzyklen verbraten), macht den Code aber wesentlich besser lesbarer und verständlicher.

Davon ab, wenn wir zu Interrupts kommen musst du es so oder so ;)
 
Daher lieber auslagern
Wie ist das gemeint. Ich muss mich jetzt erst einmal umstellen. Unter Auslagern versehe ich, dass ich etwas abfrage und wenn diese erfüllt oder auch nicht erfüllt ist, dann Gosub, diese dann unter dem Main Teil geschrieben wird. Wenn ich mich jetzt richtig ausgedrückt habe.
 
Richtig.

Code:
Main:
   If IsCharWaiting = 1 Then Gosub OnUartRx
   If Tifr...
Goto Main

OnUartRx:
   ...
Return
Vom Prinzip so. (Vorsicht, freihand getippt, wirst schon wissen wie ich es meine)
 
Ist das in etwa richtig?


CodeBox BascomAVR
$regfile = "m8def.dat"                  'Controllerdefinitionsdatei einbinden
$crystal = 8000000                      'Systemtakt angeben (Baudrate)
$hwstack = 40                           'Stacks
$swstack = 16
$framesize = 32
$baud = 19200                           'Baudrate UART
Dim Zeichen As Byte                     'UART-Empfang
Dim Z As Byte
Dim Fla As Byte
Dim Pause As Byte
Dim Pausex2 As Byte
Dim Tov1cnt As Byte
Dim Countdown As Word
Ddrc = &B_11_1111
Portc = &B00_0000
Ddrd = &B_1111_1111
Portd = &B0000_0000
Rot Alias Portd.7
Blau Alias Portd.6
Gruen Alias Portc.3
Rot = 0
Blau = 0
'Phasenkorrekter 8-Bit-PWM, PWM-Frequenz=245Hz
Config Timer1 = Pwm , Prescale = 64 , Compare A Pwm = Clear Down , Compare B Pwm = Clear Down
Main:
   If Ischarwaiting() = 1 Then Gosub Onuartrx
   If Tifr.tov1 = 1 Then Gosub Flag
   Goto Main

Onuartrx:
   Zeichen = Inkey()                    'dann Zeichen aus Puffer lesen
   If Zeichen = "1" Then                'Wenn Zeichen = "1"
      Rot = 1                        '...
      Print "Led An"
   Elseif Zeichen = "0" Then         'Wenn Zeichen = "0"
      Rot = 0                        '...
      Print "Led Aus"
   Elseif Zeichen = "t" Then         'Wenn Zeichen = "t"
      Toggle Rot                     '...
      Print "Toggle Led"
   Elseif Zeichen = "?" Then         'Wenn Zeichen = "?"
      If Rot = 0 Then                'Dann wenn Led aus ist...
         Print "Led ist aus"
      Elseif Rot = 1 Then            'sonst wenn Led an ist...
         Print "Led ist an"
      End If
   Elseif Zeichen = 0 Then           'bei 0x00 PWM deaktivieren
      Config Timer1 = Pwm , Prescale = 64 , Compare A Pwm = Disconnect , Compare B Pwm = Disconnect
   Elseif Zeichen = 255 Then         'bei 0xFF PWM aktivieren
      Config Timer1 = Pwm , Prescale = 64 , Compare A Pwm = Clear Down , Compare B Pwm = Clear Down
   Else
      Countdown = Zeichen * 60
      Config Timer1 = Pwm , Prescale = 64 , Compare A Pwm = Clear Down , Compare B Pwm = Clear Down
   End If
Return

Flag:
   Set Tifr.tov1                        'Überlaufflag zurücksetzen
   Incr Tov1cnt                      'überlaufzähler inkrementieren
   If Pause = Tov1cnt Then           'entspricht dem 2ten "waitms pause"
      Fla = Rnd(200)
      Fla = Fla + 55
      Pwm1a = Fla
   End If
   If Pausex2 = Tov1cnt Then         'entspricht dem ersten "waitms pause"
      Pwm1b = 255 - Fla
      Pause = Rnd(10)
      Pause = Pause * 6
      Pausex2 = Pause
      Shift Pausex2 , Left           'pausex2=pause*2
      Tov1cnt = 0
   End If
   Incr Z
   If Z = 245 Then                   'Überläufe zählen (245)
      Z = 0                          'Zähler zurücksetzen
      Toggle Gruen                   'LED toggeln
      If Countdown = 0 Then
         Config Timer1 = Pwm , Prescale = 64 , Compare A Pwm = Disconnect , Compare B Pwm = Disconnect
      Else
         Decr Countdown
      End If
   End If
Return
 
Zuletzt bearbeitet:
Jupp.
Ich würde deine 2. Routine nur nicht "Flag" nennen sondern OnTimer1Overflow. Weil es ist im Endeffekt genau das ;)
Aus der Routine könnte man jetzt noch den Sekunden-Teil raus ziehen. Also If Z = 245 Then Gosub Tick1Sec
So wie du es schon gemacht hast.

So sieht man gleich welcher Bereich wofür da ist und kann für den Moment irrelevantes ausblenden, je nach IDE sogar ein- und ausklappen.
 
Die Grüne Led toggelt nicht und schaltet somit auch nicht die Pwm ab. Sonst funktionier alles wie zuvor.


CodeBox BascomAVR
$regfile = "m8def.dat"                  'Controllerdefinitionsdatei einbinden
$crystal = 8000000                      'Systemtakt angeben (Baudrate)
$hwstack = 40                           'Stacks
$swstack = 16
$framesize = 32
$baud = 19200                           'Baudrate UART
Dim Zeichen As Byte                     'UART-Empfang
Dim Z As Byte
Dim Fla As Byte
Dim Pause As Byte
Dim Pausex2 As Byte
Dim Tov1cnt As Byte
Dim Countdown As Word
Ddrc = &B_11_1111
Portc = &B00_0000
Ddrd = &B_1111_1111
Portd = &B0000_0000
Rot Alias Portd.7
Blau Alias Portd.6
Gruen Alias Portc.3

'Phasenkorrekter 8-Bit-PWM, PWM-Frequenz=245Hz
Config Timer1 = Pwm , Prescale = 64 , Compare A Pwm = Clear Down , Compare B Pwm = Clear Down
Main:
   If Ischarwaiting() = 1 Then Gosub Onuartrx
   If Tifr.tov1 = 1 Then Gosub Ontimer1overflow
   If Z = 245 Then Gosub Tick1sec
   Goto Main

Onuartrx:
   Zeichen = Inkey()                    'dann Zeichen aus Puffer lesen
   If Zeichen = "1" Then                'Wenn Zeichen = "1"
      Rot = 1                           '...
      Print "Led An"
   Elseif Zeichen = "0" Then            'Wenn Zeichen = "0"
      Rot = 0                           '...
      Print "Led Aus"
   Elseif Zeichen = "t" Then            'Wenn Zeichen = "t"
      Toggle Rot                        '...
      Print "Toggle Led"
   Elseif Zeichen = "?" Then            'Wenn Zeichen = "?"
      If Rot = 0 Then                   'Dann wenn Led aus ist...
         Print "Led ist aus"
      Elseif Rot = 1 Then               'sonst wenn Led an ist...
         Print "Led ist an"
      End If
   Elseif Zeichen = 0 Then              'bei 0x00 PWM deaktivieren
      Config Timer1 = Pwm , Prescale = 64 , Compare A Pwm = Disconnect , Compare B Pwm = Disconnect
   Elseif Zeichen = 255 Then            'bei 0xFF PWM aktivieren
      Config Timer1 = Pwm , Prescale = 64 , Compare A Pwm = Clear Down , Compare B Pwm = Clear Down
   Else
      Countdown = Zeichen * 60
      Config Timer1 = Pwm , Prescale = 64 , Compare A Pwm = Clear Down , Compare B Pwm = Clear Down
   End If
Return
Ontimer1overflow:
   Set Tifr.tov1                        'Überlaufflag zurücksetzen
   Incr Tov1cnt                         'überlaufzähler inkrementieren
   If Pause = Tov1cnt Then              'entspricht dem 2ten "waitms pause"
      Fla = Rnd(200)
      Fla = Fla + 55
      Pwm1a = Fla
   End If
   If Pausex2 = Tov1cnt Then            'entspricht dem ersten "waitms pause"
      Pwm1b = 255 - Fla
      Pause = Rnd(10)
      Pause = Pause * 6
      Pausex2 = Pause
      Shift Pausex2 , Left              'pausex2=pause*2
      Tov1cnt = 0
   End If
Return
Tick1sec:
   Incr Z
   Z = 0                                'Zähler zurücksetzen
   Toggle Gruen                         'LED toggeln
   If Countdown = 0 Then
      Config Timer1 = Pwm , Prescale = 64 , Compare A Pwm = Disconnect , Compare B Pwm = Disconnect
   Else
      Decr Countdown
   End If
Return
 
Da fehlt das If Z = 245 in der OnTimer1Overflow ;)
Die sollte die Tick1Sek aufrufen.
Dann sollte alles gehen.
 
Das If Z=245 is doch in der Main drin und damit wird die Tick1sec aufgerufen und nicht die OnTimer1Overflow.
 
Das stimmt zwar, ist jetzt aber nicht so wie es vorher war, da war es im Overflow Teilprogramm.
Daher bist du auch etwas durcheinander gekommen.
Weil, was passiert hier?


CodeBox BascomAVR
   Incr Z
   Z = 0                                'Zähler zurücksetzen
 
Kann ich jetzt nicht ganz nachvollziehen. Wo genau muss das jetzt im Ontimer1overflow eingesetzt werden und wie muss das Tick1sec dann aussehen?
 
Zeile 74/75.
Du erhöhst Z um 1.
Danach setzt du es gleich wieder auf 0.
Effektiv bleibt Z also auf 0.

Vorher hast du Z erhöht und wenn es seinen Wert erreicht hat hast du den Sekundenteil begonnen. dort hast du Z genullt und den anderen Kram wie die grüne LED blinken lassen gemacht.

Also das Incr Z muss definitiv zurück in die Overflow Routine.
Streng genommen könnte die If in der Main bleiben. Performanter wäre es aber nur dann zu prüfen wenn der Wert auch verändert wurde, also in der Overflow.


Der Name Z als Variable ist übrigens kritisch, da es 4 Register-Paare gibt, namentlich W, X, Y und Z. W ist nicht offiziell, ist mir aber schon öfters begegnet. W ist recht logisch als Namen für das erste. Es handelt sich hierbei um die letzten Register die adressierbar sind. Vermutlich daher auch die letzten Buchstaben des Alphabets. M habe ich auch schon mal gesehen (Multiplikatonsergebnis). Diese Namen sollte man lieber meiden.
 
Ich habe jetzt in der Main
If Ischarwaiting() = 1 Then Gosub Onuartrx
If Tifr.tov1 = 1 Then Gosub Ontimer1overflow
Goto Main

und demzufolge das
Incr C
If C = 245 Then
C = 0
Toggle Gruen
If Countdown = 0 Then
Config Timer1 = Pwm , Prescale = 64 , Compare A Pwm = Disconnect , Compare B Pwm = Disconnect
Else
Decr Countdown
End If
End If

im Ontimer1overflow stehen. Ach ja, aus "Z" wie Zähler ist "C" wie Counter geworden.
Wenn ich das richtig verstehe, läuft ja alles über den Tifr.tov1.
Allerdings kürzer ist der Code auch nicht und wie kann ich das jetzt über Taster schalten. Muss doch irgendwo eine feste Zahl eingetragen werden.
Im Ontimer1overflow sind doch nur UART Befehle. Müsste also ein neue Routine rein.
 
Zuletzt bearbeitet:
Nein, nicht kürzer, das war auch nicht das Ziel. Er ist organisierter.
Deine Teilbereiche sind sauber voneinander getrennt.

OnTimer1Overflow kümmert sich doch um das Timing.
OnUartRx kümmert sich um die Befehle.
Jetzt könnte man eine OnKey1Pressed machen.
 
If Key1 Then Gosub Onkey1pressed ist eine neue Routine.
Welcher Pin wäre am vorteilhaftesten?
 
Wenn noch frei wäre einer der INT Pins die beste Wahl, prinzipiell kann aber fast jeder genutzt werden.
 
Na, du möchtest doch ohne PC die Kerze anzünden, für 8h.
 
Könnte es möglich sein, dass ich die Routine ontimer1overflow bei Tastendruck starten kann.
Eine andere Vorstellung habe ich jetzt nicht.
Bin noch in der Arbeit.
 

Über uns

  • Makerconnect ist ein Forum, welches wir ausschließlich für einen Gedankenaustausch und als Diskussionsplattform für Interessierte bereitstellen, welche sich privat, durch das Studium oder beruflich mit Mikrocontroller- und Kleinstrechnersystemen beschäftigen wollen oder müssen ;-)
  • Dirk
  • Du bist noch kein Mitglied in unserer freundlichen Community? Werde Teil von uns und registriere dich in unserem Forum.
  •  Registriere dich

User Menu

 Kaffeezeit

  • Wir arbeiten hart daran sicherzustellen, dass unser Forum permanent online und schnell erreichbar ist, unsere Forensoftware auf dem aktuellsten Stand ist und der Server regelmäßig gewartet wird. Auch die Themen Datensicherheit und Datenschutz sind uns wichtig und hier sind wir auch ständig aktiv. Alles in allem, sorgen wir uns darum, dass alles Drumherum stimmt :-)

    Dir gefällt das Forum und unsere Arbeit und du möchtest uns unterstützen? Unterstütze uns durch deine Premium-Mitgliedschaft!
    Wir freuen uns auch über eine Spende für unsere Kaffeekasse :-)
    Vielen Dank! :ciao:


     Spende uns! (Paypal)