Problem mit IsCharWaiting()

    This site uses cookies. By continuing to browse this site, you are agreeing to our Cookie Policy.

    • Problem mit IsCharWaiting()

      Hallo

      Ich hatte ja schon mal ein Problem mit dieser Funktion allerdings war da ein MAX485 beteiligt.
      Aktuell stolperte ich über eine an sich nur offene TTL-Schnittstelle.
      Soll heißen, +UB-RX-TX-GND sind an eine SUB-D 9pol Buchse herausgeführt um dort bei Bedarf einen Bluetooth-Dongle anzuschließen.
      Das funktioniert auch fehlerfrei und erwartungsgemäß.

      Nun war es aber so, dass dieser Dongle nicht angesteckt war und die Übertragungsfunktion wieder an der IsCharWaiting-Funktion scheiterte, weil diese wieder mal "meinte" es befinden sich wartende Zeichen im Buffer was aber definitiv nicht der Fall ist.

      Komischerweise wird am Beginn der Sub eine Schleife korrekt durchlaufen, bleibt dann aber im Anschluss in der nachfolgenden Schleife hängen weil die Variable iTumer (die wird im IRQ herunter gezählt um einen Timeout zu realisieren) immer wieder neu gesetzt wird obwohl weder Zeichen vorhanden sind noch überhaupt Hardware angeschlossen ist.

      Abhilfe hat auch hier ein Widerstand mit 10k von RX gegen GND gebracht.
      Offenbar braucht die Funktion IsCharWaiting diese Maßnahme obwohl ich sicher bin, dass das in der Vergangenheit auch mit der aktuellen Schaltung ohne diesen Widerstand auch funktioniert hat.

      Ist das normal und stört nur mich oder ist das noch niemand aufgefallen?

      Source Code

      1. While IsCharWaiting(#2) = 1 ' Buffer leeren
      2. fA = WaitKey(#2)
      3. Wend
      4. .
      5. .
      6. .
      7. .
      8. If IsCharWaiting(#2) = 1 Then
      9. iTimer = MS_1000
      10. fS = ""
      11. fA = 0
      12. While iTimer <> 0 And fA <> 13 And Len(fS) < 64
      13. If IsCharWaiting(#2) = 1 Then
      14. fA = WaitKey(#2)
      15. If fA = 10 Then
      16. fA = 13
      17. End If
      18. If fA > 32 Then
      19. fS = fS + Chr(fA)
      20. End If
      21. lcd "X"
      22. iTimer = MS_1000
      23. End If
      24. Wend
      25. End If
      Display All
    • Um den Buffer zu löschen kennt Bascom einen Befehl: "Clear SerialInX"

      In deiner While-Schleife scheint ein logischer Fehler zu stecken.
      1. Warum setzt du innerhalb Zeile 12 bis 24 den iTimer immer wieder neu? So wird der Timeout nie erreicht.
      2. Welchen Sinn macht es, in zeile 12 alles UND zu verknüpfen?
      3. Welchen Sinn macht es, in Zeile 13 abzufragen, ob ein Zeichen im Buffer ist, und dann auf das Zeichen in Zeile14 zu "Warten"? Zeichen ist doch da, also lesen, fertig.

      Ist deine Baudrate relativ gering, dass du da einen Timeout verwendest? Geht das nicht mit $Timeout?
    • Mitch64 wrote:

      In deiner While-Schleife scheint ein logischer Fehler zu stecken.
      nein tut es nicht ^^

      Mitch64 wrote:

      Warum setzt du innerhalb Zeile 12 bis 24 den iTimer immer wieder neu? So wird der Timeout nie erreicht.
      Weil der Timeout nach jedem empfangenen Zeichen wieder zurückgesetzt werden soll.
      Die gezeigte Schleife befindet sich in einer übergeordneten Schleife und hat eigentlich nur die Aufgabe solange Zeichen zu verarbeiten bis ein CR kommt und das auch nur wenn wirklich Zeichen anliegen.
      Das Problem ist ja, dass die Funktion IsCharWaiting fälschlicher weise meldet es liegt ein Zeichen an obwohl dies gar nicht der Fall ist.
      Darum wird ja der Timer immer wieder zurückgesetzt und die Schleife kann nicht verlassen werden.
      Womit wir bei deiner nächsten Frage sind

      Mitch64 wrote:

      Welchen Sinn macht es, in zeile 12 alles UND zu verknüpfen?
      Die Schleife soll eben dann verlassen werden können wenn entweder der Zeitablauf eingetreten ist, ein CR empfangen wurde oder der empfangene Text 64 Zeichen erreicht hat was dann in der Folge entsprechend bearbeitet wird.

      Mitch64 wrote:

      Welchen Sinn macht es, in Zeile 13 abzufragen, ob ein Zeichen im Buffer ist, und dann auf das Zeichen in Zeile14 zu "Warten"? Zeichen ist doch da, also lesen, fertig.
      Naja, wenn aber kein Zeichen da ist, würde das Programm solange in der Funktion Waitkey verharren was den weiteren Ablauf stören würde.
      Die hier gesteuerte Hardware hat ja auch noch was anderes zu tun, soll an der Stelle aber auch bei Bedarf Daten über eine RS232 verarbeiten können.
      Diese Möglichkeit wird durch entsprechenden Tastendruck aktiviert und auch wieder deaktiviert.
      Und während da Auf "Daten" gelauert wird, wird z.B. am LCD-Display unabhängig vom IRQ auch noch was ausgegeben (das ist im Beispiel aber gar nicht dargestellt)
      Meine Funktion tut eben noch was anderes während sie auf Zeichen wartet und soll auch zeitnahe verlassen werden können.

      Und die Funktion $Timeout kenne ich auch, nur ich habe mehr als eine RS232 (die andere bedient über einen MAX485 ein weiteres Gerät.

      Das Programm funktioniert ja auch erwartungsgemäß (zumindest wenn man den RX-Pin der betroffenen Schnittstelle mit einem Widerstand an GND legt).
      Was ja mein eigentliches Problem ist.

      Vielleicht ist es ja gar kein Problem. Nur die Funktion IsCharWaiting verhält sich halt nicht so wie ich diese Funktion verstehen würde.
      Sie meldet Zeichen wo gar keine sind und das kann nur abgestellt werden, wenn der entsprechende RX-Port mit einem Widerstand "herunter gezogen" oder auf einen Pegel definiert) wird.
      Vielleicht ist das auch so üblich, ich wäre halt bisher davon ausgegangen, dass der Chip das selbst können sollte.

      Ich habe ja schon einige Projekte mit Microcontrollern realisiert, nur ist das IMHO das erste wo eine Schnittstelle auch unbeschaltet sein kann und prompt stolpere ich wieder über das IsCharWaiting.
    • Hallo Zitronenfalter,
      um eine sichere Funktion zu erreichen, wirst du den RX Pin auf High ziehen müssen. Ein Low auf RX signalisiert dem UART Receiver die Startbedingung, also versucht er ein Byte einzulesen. Solange dort kein Low ankommt, wird auch nie das Bit USART Receive Complete gesetzt werden, was mit IsCharWaiting überprüft wird.
    • Zitronenfalter wrote:

      nein tut es nicht
      Na dann tut es ja, oder?

      Deine While-Schleife wird erst verlassen, wenn ein Zeichen CR ist oder der Text eine bestimmte länge erreicht hat oder der Timeout erreicht ist?
      Wieso sind dann die Bedingungen UND-Verknüpft?

      Zudem blockiert deine While-Schleife trotzdem, bis eine der Bedingungen eintritt (wenns richtig verknüpft wäre).

      Du könntest doch einfach Abfragen
      If IsCharWait=1 then
      Input #2,EmpfangsString
      End If

      Der Input liest bis zum CR.

      Ich kann nur sagen, wenn alles richtig gemacht wäre, würde es auch richtig funktionieren.

      Und den PullUp am RxD hängt man nicht nach Low, sondern an High. Denn Die Flanke nach Low markiert für den Uart praktisch das Startbit.

      Ob das jetzt bei dir funktioniert, hin oder her, der PullUp gehört an VCC!
    • Also ich interpretiere

      BASCOM Source Code

      1. While iTimer <> 0 And fA <> 13 And Len(fS) < 64
      Bleibe in der Schleife solange der Timer nicht abgelaufen ist, kein CR empfangen wurde oder die Stringlänge weniger als 64 Zeichen enthält.
      Trifft mindestens eine der Bedingungen nicht mehr zu wird die Schleife verlassen.

      Mitch64 wrote:

      Du könntest doch einfach AbfragenIf IsCharWait=1 then
      Input #2,EmpfangsString
      End If

      Der Input liest bis zum CR.
      Eben, Input erwartet unbedingt ein CR und wartet solange bis das auch eintritt was gegen eine Abarbeitung anderer Funktionen während dem warten auf Daten spricht da ja innerhalb der Schleife mehr als nur das warten auf Daten passiert (das Beispiel oben ist ja stark gekürzt).
      Das würde $Timeout möglicherweise abfangen, aber ich habe mehr als eine Schnittstelle und möchte an der anderen das nicht so lösen müssen.

      Mitch64 wrote:

      Und den PullUp am RxD hängt man nicht nach Low, sondern an High.
      Das werde ich noch ändern.
      Was mich aber zu der Frage bringt, ist der denn immer notwendig, weil ich eigentlich das bisher überhaupt noch nie so gesehen habe.

      Ich muss aber nochmals darauf hinweisen, dass es vollkommen irrelevant ist was da in der Schleife passiert weil die ja gar nicht betreten werden dürfte wenn die Funktion IsCharWaiting korrekt arbeiten würde.
      Immerhin gibt diese Funktion ja den Wert "1" zurück obwohl die RS232 gar nicht beschalten ist und somit gar keine Zeichen da sein dürfen.
      Und selbst in der Schleife wird ja auch dauernd ein Zeichen gemeldet was gar nicht da ist weshalb ja der Timeout nicht zuschlagen kann.
      Interessant ist ja auch, dass dieses imaginäre Zeichen durch Waitkey abgefragt werden kann weil anderenfalls ja die erste Schleife durchlaufen wird.
      In der zweiten Schleife ist es das gleiche und da da ein Zeichen empfangen wurde (Ich vermute mal Byte 0) wird natürlich der Timer wieder neu gesetzt wodurch diese Schleife dann nicht mehr verlassen werden kann.
    • Zitronenfalter wrote:

      Das werde ich noch ändern.
      Was mich aber zu der Frage bringt, ist der denn immer notwendig, weil ich eigentlich das bisher überhaupt noch nie so gesehen habe.
      Offene Eingänge sind sehr hochohmig und empfangen alles was da im Äther um einen herum abgeht, Netzbrummen, Schalten von Verbrauchern etc.
      Offene Eingänge sind daher zu vermeiden. Dabei ist es unerheblich ob der Einganh ein PC-Interrupt, ein normaler Interrupt, ein RxD-Pin oder sonst einer ist.

      Wenn du einen Schalter gegen GND an einem Eingang anschließt, sorgst du ja auch für einen PullUp. Genau das ist der Grund.

      Ich weiß jetzt nicht, wie der UART intern funktioniert. Ob er auf den Low-Pegel bereits reagiert und dann ein Byte versucht einzulesen oder ob das eine abfallende Flanke sein muss.
      Daher ändere erst mal den PullUp, damit der RxD auf den IDLE-Pegel gezogen wird.

      Vielleicht ist dein Problem dann schon behoben.

      Wenn dein Code funktioniert, wenn du Hardware angeschlossen hast, wird der RxD ja von extern ja auf High gehalten. Dann funktioniert. Sobald du die abziehst, wird der Pegel low und es müssten theoretisch immer 0-Bytes (ASCII 0) eingelesen.
      Damit wird ein Zeichen erkannt, Timeout gesetzt, es ist aber kein CR und der Strung wird nicht die geforderte Länge erreichen und hängt in der Schleife?
    • Franz wrote:

      Aber du hast doch auch keine RS232 Schnittstelle, oder? Dann hättest du normalerweise einen MAX323 dahinter, der die Pegel für den Controller richtig hält.
      Das ist eine RS232-Schnittstelle mit 9600,8N1.
      Und ich brauche da keinem MAX232 weil bei Bedarf an den TTL-RX-TX ein Bluetooth-Modul mit entsprechender Pegelwandlung angeschlossen ist.
      Das sind diese HC-05/HC-06 Module die mit 5V betrieben werden aber am RX eine Pegelanpassung in Form eines Spannungsteilers erfordert.

      Und das sind dann insgesamt max. 15cm Anschlussleitung.

      So wie sich das jetzt darstellt dürfte wohl der offene Eingang das Problem sein mit dem Pullup funktioniert das jetzt auch wieder erwartungsgemäß (allerdings auch wenn ich den Abstand zur Fritzbox erweitere :D ).
      Ich hatte bisher keine zeitweise unbenutzten (und somit offene) Schnittstellen in meinen Anwendungen.
      In der Schleife wird der sich wohl deshalb festfahren, da meine Einleseroutine nicht druckbare Zeichen verwirft aber dennoch als empfangenes Zeichen behandelt und den Timeout zurücksetzt, das werde ich auch noch ändern.

      Danke auf jeden Fall für die Denkanstöße.