Bascom BASCOM ; Erste Schritte zum Ausprobieren

Wir verwenden also Vorteiler 1024 statt 64:
Config Timer1 = Pwm , Prescale = 1024 , Compare A Pwm = Clear Down , Compare B Pwm = Clear Down
Du müßtest also diese Zeile im Initialisierungsbereich (also vor der Schleife) einfügen.
Und noch etwas aufräumen, dann sieht es so aus:



CodeBox BascomAVR
$regfile = "m8def.dat"
$crystal = 8000000
$hwstack = 40
$swstack = 16
$framesize = 32
$baud = 19200

Dim Zeichen As String * 1

Config Timer1 = Pwm , Prescale = 1024 , Compare A Pwm = Clear Down , Compare B Pwm = Clear Down

Rot Alias Portd.7                                           'Name für Portbit des Beines
Config Rot = Output                                         'LED ist Ausgang
Rot = 1                                                     'high Pegel
Gruen Alias Portc.3
Config Gruen = Output
Gruen = 1

Do
'(
   Input "Zeichen eingeben: " , Zeichen
   If Zeichen = "1" Then
      Rot = 1
      Print "Led An"
   Elseif Zeichen = "0" Then
      Rot = 0
      Print "Led Aus"
   Elseif Zeichen = "t" Then
      Toggle Rot
      Print "Toggle Led"
   Elseif Zeichen = "?" Then
      If Rot = 0 Then
         Print "Led ist aus"
      Else
         Print "Led ist an"
      End If
   End If
')
Loop


Der Timer läuft jetzt also, jedesmal wenn er die Null erreicht, wird automatisch das TOV1-Bit in TIFR gesetzt.
Deine Aufgabe ist:
Füge in der Hauptschleife unter dem auskommentierten Block einen Code ein, der jedesmal wenn der Timer1 die Null erreicht, die grüne LED toggelt.

Im bisherigen Code wurde bereits eine LED getoggelt, nun eben die andere
Im bisherigen Code fragst Du bereits Bit7 in PortD ab

P.S.: Steckbrett sieht inzwischen so aus:
8041
 
Zuletzt bearbeitet:
Also ich habe das so gedacht,


CodeBox BascomAVR
$regfile = "m8def.dat"
$crystal = 8000000
$hwstack = 40
$swstack = 16
$framesize = 32
$baud = 19200

Config Timer1 = Pwm , Prescale = 1024 , Compare A Pwm = Clear Down , Compare B Pwm = Clear Down

Config Portd.7 = Output
Config Portc.3 = Output

Dim Zeichen As String * 1

Rot Alias Portd.7
Rot = 1
Gruen Alias Portc.3
Gruen = 1

Do
'(
   Input "Zeichen eingeben: " , Zeichen
   If Zeichen = "1" Then
      Rot = 1
      Print "Led An"
   Elseif Zeichen = "0" Then
      Rot = 0
      Print "Led Aus"
   Elseif Zeichen = "t" Then
      Toggle Rot
      Print "Toggle Led"
   Elseif Zeichen = "?" Then
         If Rot = 0 Then
            Print "Led ist aus"
         Elseif Rot = 1 Then
            Print "Led ist an"
         End If
   End If
')
   If Timer1 = 0 Then
      Toggle Gruen
   End If

Loop
End

Leider passiert da nichts.
Steckbrett sieht inzwischen so aus:
Mir ist aufgefallen, dass die Verbindungen vom Maxx232 (oder wie man das nennt) zum µC über Kreuz verlaufen.
Ich habe RxI mit RxD am µC und TxO mit TxD am µC verbunden.
Was ist nun richtig?
 
Mir ist aufgefallen, dass die Verbindungen vom Maxx232 (oder wie man das nennt)
Der MAX232 ist ein Pegelwandler-IC von Maxim (Dallas?), der 12V-RS232-UART auf 5V-TTL-UART wandelt. Es gibt natürlich diverse Derivate von anderen Firmen mit ähnlichen Namen, die dasselbe tun.
Kernstück der von mir verwendeten Adapter-Platine ist irgendein FTDI, der ein USB-Endgerät darstellt, welches mit einem virtuellen seriellen Port im PC kommuniziert (über USB), und dem Mikrocontroller gegenüber 'ne TTL-UART bereitstellt.
RXI des Adapters ist auch aus der Sicht des Adapters zu verstehen - "I" wie In, also der Receiver des FTDI-Chips. Folglich ist da der Transmitter des Mikrocontrollers (dessen Ausgang) anzuschließen. Enteprechendes gilt in Umgekehrter richtung beim anderen Anschluß. TXO ist der Transmitter-Ausgang des Adapters, der vom Receiver (RX) des Controllers empfangen werden soll.

Dein Adapter läuft ja, also alles so lassen.


Leider passiert da nichts.
Sicher?
Was sollte denn jetzt passieren?
Der Timer taktet mit einem 1024stel des Systemtaktes, das heißt andersrum, daß der Timer aus Sicht des Systemtaktes nur alle 1024 Takte einen Schritt macht. Oder anders gesagt: der Timer steht 1024 Systemtakte lang still.
Solange der Timer irgendeinen Wert verschieden null hat, ändert sich eh nichts, klar - interessant wirds, wenn der Timer=0 ist.
Dann ist die IF-Bedingung wahr, und die LED wird getoggelt. Aber nicht nur einmal (wenn der Timer den Schritt auf Null macht), sondern ununterbrochen (solange der Timer bei der IF-Frage gleich Null ist (bei jedem Schleifendurchlauf einmal natürlich)).
Nehmen wir mal an, die Schleife benötigt im Null-Fall Zehn Takte, dann würde die LED dort etwa hundertmal getoggelt werden. Wenn es eine gerade Anzahl ist, ist der Zustand der LED hinterher wieder derselbe.

Mit der Abfrage des Timer-Zählers selbst bist Du also auf dem Holzweg. Nicht solange der Zähler gleich null ist, sondern jedesmal einmal, wenn er Null geworden ist.
Wie gesagt: das TOV1--Bit im TIFR wird automatisch gesetzt, wenn der Timer 0 erreicht. Und es bleibt solange gesetzt, bis entweder ein daran gekoppelter Interrupt abgearbeitet wird (verwenden wir nicht), oder Das Bit durch die Software (also Dich - Deinen Programmcode) gelöscht wird.
 
Mit der Abfrage des Timer-Zählers selbst bist Du also auf dem Holzweg
Die Hinweise in #101 nütze mir demzufolge gar nichts. Mir hat sich die If Abfrage im Kopf festgesetzt und ich kann machen was ich will, ich finde keine Lösung.
Jetzt hab ich eine Erläuterung für die Register gefunden. Um diese zu verstehen, benötige ich allerdings Beispiele mit den dazugehörigen Lösungen.
Für mich ist das eben alles neu, da ich bisher nur aus dem Internet gefundene Codes abgeschrieben habe und keine Erklärung dazu hatte.
 

Anhänge

  • irq-uebung.pdf
    116,8 KB · Aufrufe: 6
Scheint etwas älter zu sein da noch Signal ()
Die Architektur des Mega8 ist auch nicht taufrisch, und ihm geht's ja weniger um den C-Code, als mehr um eine deutsche Erklärung der Register und deren Bits. Paßt also soweit. Allerdings handelt es sich dort um Timer0, wir verwenden Timer1 (welcher deutlich komplexer ist). Dort wird ein Frequenzkorrigierter singleSlope Modus (CTC) verwendet - wir sind beim phasenkorrekten dualSlope (PWM). Da der Timer1 auch die Modi des Timer0 kann, sind die Erklärungen trotzdem möglicherweise hilfreich.
Ich hatte hier mal was zu den Registern des Timer1 des Mega8 geschrieben. Auf deutsch.;)
Die Hinweise in #101 nütze mir demzufolge gar nichts. Mir hat sich die If Abfrage im Kopf festgesetzt und ich kann machen was ich will,
Doch doch,
Hinweis I war, daß Du die grüne LED genauso wie die Rote toggeln mußt. Das hast Du in Zeile 41 korrekt umgesetzt.
Hinweis II war, daß Du bereits ein Bit in einem I/O-Register abfragst - nämlich PORTD.7 in Zeile 33 und 35 (hier jetzt auskommentiert, klar). Das hast Du da zwar nicht ausgeschrieben, aber Bascom ersetzt überall "Rot" durch "PORTD.7", klar?

Jetzt habe ich Dir gesagt, daß Du mit der Abfrage des Zählers selbst (TCNT1 bzw unter Bascom auch Timer1) auf dem Holzweg bist (das ist so, als wenn Du im Auto ununterbrochen auf den Tacho/Kilometerzähler starrst, und siehst daß der "0000" anzeigt oder eben nicht). Der Timer hat aber neben seinem "Kilometerzähler" noch 'ne Lampe (Flag/Fähnchen) die jedesmal wenn er auf "0000" umschaltet angeht, und dann anbleibt bis irgendwer sie wieder deaktiviert..
Dann bleibt sie auch aus, wenn der Timer weiterhin auf "0000" steht - erst wenn er wieder auf "0000" umschaltet, geht sie wieder an.

Diese Lampe ist das Überlaufflag des Timers, TOV1. Es befindet sich beim Mega8 im allgemeinen "Timer and Counter Flag Register". TIFR.
Im Datenblatt steht dazu:
Timer/Counter Interrupt Flag Register - TIFR
OCF2​
TOV2​
ICF1​
OCF1A​
OCF1B​
TOV1​
-​
TOV0​

[…]
• Bit 2 – TOV1: Timer/Counter1, Overflow Flag
The setting of this flag is dependent of the WGM13:0 bits setting. In normal and CTC modes, the TOV1 Flag is set when the timer overflows. Refer to Table 39 on page 97 for the TOV1 Flag behavior when using another WGM13:0 bit setting.
TOV1 is automatically cleared when the Timer/Counter1 Overflow Interrupt Vector is executed. Alternatively, TOV1 can be cleared by writing a logic one to its bit Location.

Der Google-Übersetzer macht daraus:
Die Einstellung dieses Flags hängt von der Einstellung des WGM13: 0-Bits ab. Im Normal- und CTC-Modus wird das TOV1-Flag gesetzt, wenn der Timer überläuft. In Tabelle 39 auf Seite 97 finden Sie das Verhalten des TOV1-Flags bei Verwendung einer anderen WGM13: 0-Bit-Einstellung.

TOV1 wird automatisch gelöscht, wenn der Timer / Counter1 Overflow Interrupt Vector ausgeführt wird. Alternativ kann TOV1 gelöscht werden, indem eine logische Eins in das Bit Location geschrieben wird.
Eigentlich halbwegs verständlich...
Wir folgen also dem Link zu Table 39 auf Seite 97.
Wir verwenden wie bereits mehrfach geschrieben den phasenkorrekten 8-Bit PWM - in der Tabelle also Mode 1. In der letzten Spalte (TOV1 Flag Set on) steht: "Bottom" (Unterseite, Boden... hä?).
Auf Seite 76 steht in Table 35 definiert:
BOTTOM: The counter reaches the BOTTOM when it becomes 0x0000.
Daraus macht der Google-Übersetzer:
Der Zähler erreicht den UNTEN, wenn 0x0000 angezeigt wird.
Also Bottom tritt ein, wenn der Zähler auf "0000" schaltet, und dann wird nach Tabelle 39 bei unserem Modus das TOV1 gesetzt.
Gelöscht wird es entweder dirch die Abarbeitung des entsprechenden Interruptes (verwenden wir nicht/ist nicht aktiviert) oder eben indem Du das Bit selbst setzt ('ne "1" reinschreibst).

Wie man unter Bascom auf Bits in Registern zugreifen kann, hatten wir bereits - einen zusätzlichen neuen Namen mußt Du hier nicht unbedingt vergeben (Alias).
 
Zuletzt bearbeitet:
Ich komme nicht weiter!
Irgendwie muss ich die ganzen Register in den Code schreiben. Wie man das macht, habe ich nicht rausfinden können.
 
Irgendwie muss ich die ganzen Register in den Code schreiben.
??
Ein Register, bzw sogar nur ein Bit eines Registers...


CodeBox BascomAVR
Elseif Rot = 1 Then
Hier hast Du abgefragt, ob das Bit "Rot" gesetzt ist. Hinter "Rot" verbirgt sich "Portd.7" (eben genau das Bein, wo Du die LED angeschlossen hast - deswegen hat es mit ALIAS ja auch diesen Namen bekommen).
Da könnte also ebenso stehen:


CodeBox BascomAVR
Elseif Portd.7= 1 Then

Jetzt sollst Du stattdessen das TOV1-Bit in TIFR prüfen, also genauso:


CodeBox BascomAVR
IF TIFR.TOV1=1 Then

Ist das Bit gesetzt, kannst Du die LED toggeln, außerdem mußt Du dann das Flag auch selbst löschen - wie oben beschrieben, indem Du eine eins reinschreibst:


CodeBox BascomAVR
TIFR.TOV1=1
 
Zuletzt bearbeitet:
indem Du eine eins reinschreibst:


CodeBox BascomAVR BascomAVR1TIFR.TOV1=1
Das hab ich gemacht. Dabei springt der Pfeil im Simulator auch nur auf und ab.
Bei allen Erklärungen im Internet steht etwas mit Interrupts, isr und Begriffen, von denen ich keine Ahnung habe, wie eines mit dem anderen funktioniert.
Ich finde auch keine Beispiele mit dem ich die Theorie in der Praxis bzw. auf dem Steckbrett vergleichen und experimentieren kann.



CodeBox BascomAVR
$regfile = "m8def.dat"
$crystal = 8000000
$hwstack = 40
$swstack = 16
$framesize = 32
$baud = 19200

Config Timer1 = Pwm , Prescale = 1024 , Compare A Pwm = Clear Down , Compare B Pwm = Clear Down

Config Portd.7 = Output
Config Portc.3 = Output

Dim Zeichen As String * 1

Rot Alias Portd.7
Rot = 0
Gruen Alias Portc.3
Gruen = 1

Do
'(
   Input "Zeichen eingeben: " , Zeichen
   If Zeichen = "1" Then
      Rot = 1
      Print "Led An"
   Elseif Zeichen = "0" Then
      Rot = 0
      Print "Led Aus"
   Elseif Zeichen = "t" Then
      Toggle Rot
      Print "Toggle Led"
   Elseif Zeichen = "?" Then
         If Rot = 0 Then
            Print "Led ist aus"
         Elseif Rot = 1 Then
            Print "Led ist an"
         End If
   End If
')
   If Tifr.tov1 = 1 Then
      Toggle Gruen
   End If
   Set Tifr.1

Loop
End

Ich werde das wohl nie verstehen.
 
Bei allen Erklärungen im Internet steht etwas mit Interrupts, isr und Begriffen, von denen ich keine Ahnung habe, wie eines mit dem anderen funktioniert.
Der Timer hat aber neben seinem "Kilometerzähler" noch 'ne Lampe (Flag/Fähnchen) die jedesmal wenn er auf "0000" umschaltet angeht, und dann anbleibt bis irgendwer sie wieder deaktiviert..
Dann bleibt sie auch aus, wenn der Timer weiterhin auf "0000" steht - erst wenn er wieder auf "0000" umschaltet, geht sie wieder an.

Diese Lampe ist das Überlaufflag des Timers, TOV1. Es befindet sich beim Mega8 im allgemeinen "Timer and Counter Flag Register". TIFR.
Im Datenblatt steht dazu:
Timer/Counter Interrupt Flag Register - TIFR
OCF2​
TOV2​
ICF1​
OCF1A​
OCF1B​
TOV1​
-​
TOV0​

[…]
• Bit 2 – TOV1: Timer/Counter1, Overflow Flag
The setting of this flag is dependent of the WGM13:0 bits setting. In normal and CTC modes, the TOV1 Flag is set when the timer overflows. Refer to Table 39 on page 97 for the TOV1 Flag behavior when using another WGM13:0 bit setting.
TOV1 is automatically cleared when the Timer/Counter1 Overflow Interrupt Vector is executed. Alternatively, TOV1 can be cleared by writing a logic one to its bit Location.

Der Google-Übersetzer macht daraus:
Die Einstellung dieses Flags hängt von der Einstellung des WGM13: 0-Bits ab. Im Normal- und CTC-Modus wird das TOV1-Flag gesetzt, wenn der Timer überläuft. In Tabelle 39 auf Seite 97 finden Sie das Verhalten des TOV1-Flags bei Verwendung einer anderen WGM13: 0-Bit-Einstellung.

TOV1 wird automatisch gelöscht, wenn der Timer / Counter1 Overflow Interrupt Vector ausgeführt wird. Alternativ kann TOV1 gelöscht werden, indem eine logische Eins in das Bit Location geschrieben wird.
Eigentlich halbwegs verständlich...
Wir folgen also dem Link zu Table 39 auf Seite 97.
Wir verwenden wie bereits mehrfach geschrieben den phasenkorrekten 8-Bit PWM - in der Tabelle also Mode 1. In der letzten Spalte (TOV1 Flag Set on) steht: "Bottom" (Unterseite, Boden... hä?).
Auf Seite 76 steht in Table 35 definiert:
BOTTOM: The counter reaches the BOTTOM when it becomes 0x0000.
Daraus macht der Google-Übersetzer:
Der Zähler erreicht den UNTEN, wenn 0x0000 angezeigt wird.
Also Bottom tritt ein, wenn der Zähler auf "0000" schaltet, und dann wird nach Tabelle 39 bei unserem Modus das TOV1 gesetzt.
Gelöscht wird es entweder dirch die Abarbeitung des entsprechenden Interruptes (verwenden wir nicht/ist nicht aktiviert) oder eben indem Du das Bit selbst setzt ('ne "1" reinschreibst).
TOV1 ist das Überlauf-Fähnchen des Timers. Es wird jedesmal gesetzt, wenn der Timer in irgendeiner Form überläuft. Wann das bei welchem Mode konkret der Fall ist, steht in der genannten Tabelle 39.
Im hier verwendeten Fall immer, wenn BOTTOM=niedrigster Timerwert=0 erreicht wird.

An TOV1 kann(!) ein Interrupt geknüpft werden. Dazu muß lediglich das zum TOV1 gehörende Interrupt Enable Bit (Timer 1 Overflow Interrupt Enable - TOIE1) im Timer/Counter Interrupt Mask Register - TIMSK) gesetzt werden. BAscom bietet Dir dafür die Instruktion Enable Timer1 an, die nichts anderes macht.
Außerdem müssen die Interrupts generell freigegeben sein - dazu muß das Bit "I" (Global enable Interrupts) im Statusregister (SREG) gesetzt sein. In Bascom kannst Du dies durch Enable Interrupts erreichen (oder Set SREG.I oder SREG.I=1 oder SEI oder...).
Sind diese beiden Bits also gesetzt (globale Freigabe und lokale Aktivierung) ist der Interrupt scharf.
Jedesmal wenn TOV1 dann gesetzt wird/ist wird das Programm unterbrochen, die Interrupts global gesperrt und eine durch die Hardware festgelegte Adresse im Programmspeicher ausgeführt. Gleichzeitig wird automatisch das TOV1 gelöscht. An dieser Adresse muß quasi der Code platziert werden, der im Interrupt-Fall ausgeführt werden soll.
Da (nur eine Adresse) paßt er aber im allgemeinen nicht hin, also wird dort lediglich ein Sprungbefehl in die entsprechende Interrupt Service Routine (ISR) platziert. Das nimmt Bascom Dir mit On Interruptquelle Sprungziel ab. In der so erreichten ISR wird er entsprechende Code abgearbeitet, die ISR selbst wird mit einem Return beendet, welches Interrupts global wieder scharfmacht, und zu dem Punkt zurückkehrt, wo das Programm unterbrochen wurde.

Wir verwenden aber keine Interrupts. Wir haben den Überlaufs-Interrupt nicht lokal (TIFR) aktiviert, und erst recht nicht die Interrupts global freigegeben (SREG).
Wir greifen nur auf das, bei jedem "Timerüberlauf" automatisch gesetzte TOV1 zu.
Die IF-Abfrage ab Zeile 40 paßt also, ABER:
Ist das Bit gesetzt, kannst Du die LED toggeln, außerdem mußt Du dann das Flag auch selbst löschen
Derzeit setzt Du das TOV1 bei jedem Schleifendurchlauf zurück, dadurch werden einige gesetzte TOVs gelöscht, bevor sie ausgewertet wurden. Du sollst sie nur dann zurücksetzen, wenn sie erkannt (und bearbeitet) wurden/werden, also im IF-Block.
 
Blöde Frage / Ergänzung, müsste es in 43 nicht "Set Tifr.tov1" sein? Ok, mag hier von den Bits her passen.
 
Blöde Frage / Ergänzung, müsste es in 43 nicht "Set Tifr.tov1" sein?
Nicht gesehen...
Beim IF hats ja noch gestimmt...
Ok, mag hier von den Bits her passen.
Nein, paßt nicht... Bit1 wird nicht verwendet, wenn wäre es Bit2, aber genau aus diesem Grund verwendet man ja auch besser die definierten Namen.
Trotzdem gehört das zurücksetzen des Flags auch in den If-Block - der Timerüberlauf kann ja auch zwischen dem Prüfen (IF...) und dem Sprung zum End If auftreten. Dann würde TOV1 gesetzt werden und sofort gelöscht.
Beim nächsten Durchlauf der Schleife und der nächsten IF-Prüfung würde dieser Timerüberlauf also nicht mehr erkannt werden.
 
Ok, es hat wohl keinen Sinn mehr für mich hier weiter zu machen. Es sollte doch nur eine Zeile weiter im Programm entstehen, aber inzwischen sind so viele neue Begriffe aufgetreten und ich keinen Zusammenhang mehr erkennen kann.

Ich danke allen für Ihre Zeit und Mühe.
 
Wo willst Du denn hin? Also was ist Dein Ziel?
Ursprünglich war das ein Thread, wo Cassio Jordy diverse Programmieraufgaben bzw Aufgaben zu Programmen gestellt hatte, weil dieser was darüber lernen wollte.
Du hast diesen alten Thread dann mit einem anderen, nur teilweise funktionierendem Programm aufgegriffen. Eines der Hauptprobleme dabei war, daß Du zwei (mindestens) unterschiedliche Programme /Teilprogramme (aus welchen Quellen auch immer) vereinen wolltest, die sich gegenseitig in die Quere kommen.
In Anlehnung an Cassio hab ich Dir also ein paar, unter Bascom eigentlich recht einfache Aufgeben gestellt.
Einerseits Teilprogramm, welches 'ne Über empfangene UART-Kommandos 'ne LED schaltet - der Teil läuft und ist derzeit via Kommentar deaktiviert.
Andererseits wollte ich auf Basis der - von Dir gelieferten - Timerkonfiguration 'ne andere LED blinken lassen.
Wo Du da jetzt Probleme hast, kann ich nicht mehr nachvollziehen.
Die vier Zeilen sind fast korrekt, es sind nur zwei Sachen zu korrigieren:
müsste es in 43 nicht "Set Tifr.tov1
gehört das zurücksetzen des Flags auch in den If-Block
Also:


CodeBox BascomAVR
$regfile = "m8def.dat"
$crystal = 8000000
$hwstack = 40
$swstack = 16
$framesize = 32
$baud = 19200
 
Config Timer1 = Pwm , Prescale = 1024 , Compare A Pwm = Clear Down , Compare B Pwm = Clear Down
 
Config Portd.7 = Output
Config Portc.3 = Output
 
Dim Zeichen As String * 1
 
Rot Alias Portd.7
Rot = 0
Gruen Alias Portc.3
Gruen = 1
 
Do
'(
   Input "Zeichen eingeben: " , Zeichen
   If Zeichen = "1" Then
      Rot = 1
      Print "Led An"
   Elseif Zeichen = "0" Then
      Rot = 0
      Print "Led Aus"
   Elseif Zeichen = "t" Then
      Toggle Rot
      Print "Toggle Led"
   Elseif Zeichen = "?" Then
         If Rot = 0 Then
            Print "Led ist aus"
         Elseif Rot = 1 Then
            Print "Led ist an"
         End If
   End If
')
   If Tifr.tov1 = 1 Then
      Toggle Gruen
      Set Tifr.Tov1
   End If
 Loop
End

Damit sollte die LED blinken.
Wir hätten also zwei Teilprogramme, die - jedes für sich - korrekt laufen. Ich wollte Dich dann die Kommentare entfernen lassen, das erste Teilprogramm also reaktivieren.
Was beobachtest Du dann?
Und warum?
 
Wo willst Du denn hin? Also was ist Dein Ziel?
Ich werde hier von Experten mit Fachspezifischen Bergriffen bearbeitet, was für mich Neuland ist. Ich selbst sehe keine Erfolge und schon gar nicht das Ziel, was ich mal erreichen möchte. Hab einfach "Rot" gesehen.
If Tifr.tov1 = 1 Then Toggle Gruen Set Tifr.Tov1 End If
Irgendwie hatte ich schon einmal den Code so geschrieben. Kann schon sein, daß da ein Fehler oder und eine Falsche Zeile war. Auf jeden Fall hab ich hin und her experimentiert und kein Ergebnis erreicht.

Was beobachtest Du dann?
Die Rote Led reagiert genau auf die Anwendungen in den If Bedingungen und die Grüne Led toggelt bei jeder Enter Eingabe, ganz unabhängig davon was im Terminal eingegeben wird.
Es sind
  1. zwei unabhängige If Bedingungen
  2. soll die Grüne Led toggeln
  3. wird sie eh auf 0 gesetzt, wenn der Timer "0000" ist
 
Jedes der beiden Teilprogramme einzeln läuft korrekt. Das UART-Teilprogramm schaltet seine LED entsprechend der Vorgaben und gibt ggf. Rückmeldung, das Timer-Teilprogramm toggelt kontinuierlich seine LED.

Aber beide Programme zusammen laufen irgendwie nicht richtig - das UART Programm läuft, das Timer-Programm toggelt nur...
bei jeder Enter Eingabe
Das UART-Teilprogramm blockiert also das Timer-Programm, aber nicht umgekehrt. Warum?
Weil INPUT bei jedem Schleifendurchlauf solange wartet, bis ein String empfangen wurde. Da Input aber grundsätzlich nicht wissen kann, wie lang der String sein wird (kann ja sogar ein leerer String sein), wartet INPUT auf das Return (Enter), bevor der Rest, und insbesondere auch das andere Teilprogramm abgearbeitet werden kann.
Das Timer-Teilprogramm hingegen wartet nicht auf "Timer-wird-Null", sondern schaut bei jedem Schleifendurchlauf nur mal kurz, ob der Timer zwischendurch (also seit dem letzten Schleifendurchlauf) Null geworden ist/war, und reagiert dann ggf. Das Teilprogramm blockiert also nicht.

Um jetzt beide Teilprogramme zusammen lauffähig zu bekommen, müssen wir die Abhängigkeit vom Return loswerden. Dazu gäbe es mehrere Wege - wir verwenden ja immer nur ein Zeichen, brauchen also eigentlich das Return als String-Ende-Indikator gar nicht.

Input erwartet das Enter - also brauchen wir eine Alternative. diese gibt es zB mit Inputbin (Input binary). Inputbin nimmt eigentlich nur "Zahlen" entgegen, aber ein String ist ja auch nichts anderes als 'ne Kette ASCII-Zeichen, und diese werden anhand ihres ASCII-Codes abgespeichert/verarbeitet. Und das sind "Zahlen". Außerdem muß bei Inputbin die Anzahl der erwarteten Bytes bekannt sein - in unserem Fall eins.

Wir ändern also den Variablentyp von Zeichen in Zeile 13 von String * 1 auf Byte.
Und in Zeile 22 Input auf Inputbin (inputbin unterstützt kein kombiniertes Print-Input - "Zeichen eingeben" müßtest Du also vorher selbst durch ein Print schreiben lassen.)
Wenn Du das hast (Code zeigen) - was beobachtest Du jetzt, und warum?
 
Zuletzt bearbeitet:


CodeBox BascomAVR
Do
   Inputbin Zeichen
   If Zeichen = "1" Then
      Rot = 1
      Print "Led An"
   Elseif Zeichen = "0" Then
      Rot = 0
      Print "Led Aus"
   Elseif Zeichen = "t" Then
      Toggle Rot
      Print "Toggle Led"
   Elseif Zeichen = "?" Then
         If Rot = 0 Then
            Print "Led ist aus"
         Elseif Rot = 1 Then
            Print "Led ist an"
         End If
   End If

   If Tifr.tov1 = 1 Then
      Toggle Gruen
      Set Tifr.tov1
   End If
Loop
End

Gruen toggelt bei jeder Eingabe die ich für Rot in den If Bedingungen festgelegt habe.
Gruen toggelt auch, wenn ich den Terminal Emulator schließe.
Ob das jetzt richtig ist bzw. so sein soll ? Im Prinzip ist es doch das gleiche wie vorher ?
Die Print-Zeile musste ich weglassen. Es kommen immer wieder Fehlermeldungen.
 
Zitat aus der Online-Hilfe zu Inputbin:
Note that the INPUTBIN statement doesn't wait for a CRLF but just for the number of Bytes.
Inputbin wartet nicht auf ein CR, aber auf (irgendein) empfangenes Zeichen.
Wir brauchen also sowas wie das TOV-Flag, welches einen Timerüberlauf anzeigt, für den UART, daß ein Zeichen empfangen wurde. Ein Flag, das wir prüfen könnten, und nur bei empfangenem Zeichen würde dann mit Inputbin das Zeichen gelesen werden.
Natürlich gibt es ein solches Flag auch - das Bit "USART Receive Complete" (RXC) im "USART Control an Status Register A" (UCSRA) ist immer dann gesetzt, wenn ein ungelesenes Byte im USART-Empfangspuffer liegt.
Bascom bietet als Hochsprache auch 'ne Funktion an, die genau dieses Bit prüft/ausliest: Ischarwaiting() (Is Char waiting?)
Ischarwaiting liefert 'ne null, wenn kein Byte empfangen wurde, und 'ne eins, wenn der Puffer nicht leer ist.
Darauf kannst Du in einer weiteren IF-Abfrage prüfen.
Die Print-Zeile musste ich weglassen. Es kommen immer wieder Fehlermeldungen.
Müßte direkt eine Zeile hinter das "Do" - dann würde es aber ununterbrochen bei jedem Schleifendurchlauf ausgegeben werden. -> später
 
Gruen reagiert immer noch bei jeder Eingabe.
Wie soll das Programm eigentlich laufen?


CodeBox BascomAVR
$regfile = "m8def.dat"
$crystal = 8000000
$hwstack = 40
$swstack = 16
$framesize = 32
$baud = 19200

Config Timer1 = Pwm , Prescale = 1024 , Compare A Pwm = Clear Down , Compare B Pwm = Clear Down

Config Portd.7 = Output
Config Portc.3 = Output

Dim Zeichen As Byte

Rot Alias Portd.7
Rot = 0
Gruen Alias Portc.3
Gruen = 1

Do
   Print "Zeichen eingeben: "
   Inputbin Zeichen
   If Zeichen = "1" Then
      Rot = 1
      Print "Led An"
   Elseif Zeichen = "0" Then
      Rot = 0
      Print "Led Aus"
   Elseif Zeichen = "t" Then
      Toggle Rot
      Print "Toggle Led"
   Elseif Zeichen = "?" Then
         If Rot = 0 Then
            Print "Led ist aus"
         Elseif Rot = 1 Then
            Print "Led ist an"
         End If
   End If

   Tifr = Ischarwaiting()
   If Tifr.tov1 = 1 Then
      Toggle Gruen
      Set Tifr.tov1
   End If
Loop
End
 
Ischarwaiting prüft, ob ein Zeichen durch den UART empfangen wurde. Genau genommen das RXC-Flag im USCRA-Register.
Du sollst das nicht beim Timer-Teilprogramm anwenden (und schon gar nicht TIFR zuweisen), sondern beim UART-Teilprogramm.
Dort sollst Du mit Ischarwaiting prüfen, ob ein Zeichen empfangen wurde, und nur wenn dies der Fall war, mit Inputbin oder Inkey das Zeichen abholen, und dann wie gehabt weiterverarbeiten.
Schau Dir mal das Example zu Ischarwaiting an.

Inkey??
Was ist der Unterschied zwischen Inputbin und Inkey? Inputbin wartet auf soviele Bytes, wie die angegebenen Variablen benötigen. Inkey liest lediglich den Empfangspuffer aus. Wenn der Puffer leer ist, liefert Inkey allerdings 'ne Null (&H00 bzw &B00000000 bzw 0 dezimal bzw ASCII-Null) - "Nichts empfangen" ist also von "Null empfangen" nicht zu unterscheiden, klar?
Derzeit würden wir zwar die null eh nicht auswerten, aber später schon.

Also wie gesagt erst mit Ischarwaiting prüfen ob was im Buffer ist.
Nur dann den Buffer mit Inkey auslesen.
Dann das gelesene Zeichen auswerten und verarbeiten.
 

Ü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)