Seite 1 von 1

Ressourcensparende RS232-Kommunikation

Verfasst: 23.12.2014 09:02
von Regenduft
Hallo liebe Leute und fröhliche Weihnacht,

ich bin gerade am rätseln, ob es eine bessere Möglichkeit gibt eine ressourcensparende RS232-Kommunikation zu realisieren, anstatt die im Anhang gespostete Methode mit einem Delay. (Der tatsächlich verwendete Code ist etwas komplexer und steigert die Delay-Zeit stufenweise.)

Der Hintergrund ist, dass ich mit einem µController kommuniziere, dieser allerdings die meiste Zeit weder sendet noch empfängt. Einerseits ist es mir wichtig, dass der PC schnell reagiert, sobald sich der Controller meldet, andererseits will ich nicht unnötig oft die Empfangsschleife auf dem PC durchrödeln lassen und Rechenzeit verschenken.

Ich bin für alle Anregungen offen! :)

Wie immer vielen Dank im vorraus und auch ein Danke an WPÖ für die "Kaufberatung" vor Anschaffung des µControllers (...auch wenn's schon ewig her ist)!

Code: Alles auswählen

Repeat
  
  If AvailableSerialPortInput( SerialPort )
    
    ; ... Daten empfangen und verarbeiten ...
    
  Else
    
    Delay( 123 ) ; kleine Pi-mal-Daumen-Auszeit
    
  EndIf
  
ForEver

Re: Ressourcensparende RS232-Kommunikation

Verfasst: 23.12.2014 20:47
von BSP
Hallo Regenduft.

Ich lerne gerade erst, AVR's zu benutzen.
Z.Z benutze ich den AtMega8, mit dem ich meine Modellbahn steuere.
Die Verbindung zum PC stelle ich mit einem USBzuUart- Baustein her.
Die Gleismelder muss ich ständig abfragen.
Die Abfrage, ob Zeichen anliegen, erledige ich sogar in einer "normalen" Eventabfrage.
So ungefähr sieht mein Prg z.Z. aus:

Code: Alles auswählen

	
	#txt2 = 2
	#txt3 = 3
	#txt4 = 4
	
	#SerialPort = 0
  Port$ = "COM6"
  baut = 1800
  avrnr=1

	If Not OpenSerialPort(#SerialPort, Port$, baut, #PB_SerialPort_NoParity, 8, 1, #PB_SerialPort_NoHandshake, 1024, 1024)
    MessageRequester("Information", "Konnte Port nicht öffnen!")
    End
  EndIf
  
	OpenWindow(0,0,0,300,400,"UART- Test",#PB_Window_SystemMenu|#PB_Window_ScreenCentered)
	AddWindowTimer(0, 123, 10)
	
	Repeat
	  ev = WaitWindowEvent()
	  Select ev
	  Case #PB_Event_Gadget
	  
	  Default
	  
	  EndSelect
	  
	  If AvailableSerialPortInput(#SerialPort)
      ;wort$=ReadSerialString() ; Eigene Funktion, darum hier auskommentiert
      ;Debug wort$
      Select StringField(wort$,1,".")
      Case "gef"
        wort$=Mid(wort$,5)
        wort$=Left(wort$,Len(wort$)-1)
        SetGadgetText(#txt2,wort$)
      Case "mld"
        SetGadgetText(#txt3,wort$)
      Case "ende"
        SetGadgetText(#txt4,wort$)
      Default
        If FindString(wort$,"nothalt")
        SetGadgetText(#txt4,wort$)
        EndIf
        ;SetGadgetText(#txt4,wort$)
      EndSelect
    EndIf
Until ende
MfG & Frohe Fest an Alle.
Bernd

Re: Ressourcensparende RS232-Kommunikation

Verfasst: 24.12.2014 01:06
von Bisonte
@BSP: Ich frage mich gerade, was denn passiert, wenn gar kein WindowEvent anliegt....
Dann wird die serielle Schnittstelle nämlich gar nicht erst abgefragt.

Wegen dem "AddWindowTimer()" wolltest Du wohl eine periodische Abfrage machen,
hast aber vergessen das Event auch abzufragen ;)

@Regenduft:
Ich denke um eine ewige Abfrage wird man bei der seriellen Abfrage nicht umhinkommen,
da es leider kein Event gibt, das ausgelöst wird, wenn Daten anliegen.

Wenn ein Fenster dabei ist, das benutzbar bleiben soll schlage ich ein WaitWindowEvent mit
TimeOut vor. Ansonsten bleibt es wohl bei dem Delay.

Alles weitere darf man mich nicht fragen ... Wie der Italiener in der Tschibo Werbung : Isch haaabe gar kein Serialport ;)

Re: Ressourcensparende RS232-Kommunikation

Verfasst: 24.12.2014 02:14
von BSP
Hallo Bisonte.

Sorry. Pure Gewohnheit.
Was funktioniert wird nicht mehr überprüft und geändert.
Habs eben überprüft.
Inzwischen läufts auch wieder "normal" mit
ev = WaitWindowEvent(wert) ; (wert kann bei mir auch "1" sein

Hätte ich vieleicht erwähnen sollen:
Den "AddWindowTimer()" habe (hatte) ich aus technischen Gründen drin.
Siehe:
http://www.purebasic.fr/german/viewtopi ... =3&t=28417

So wird die Eventschleife auf jeden Fall durchlaufen
und meine Schnittstelle abgefragt.

Gruß: Bernd

Re: Ressourcensparende RS232-Kommunikation

Verfasst: 24.12.2014 03:02
von NicTheQuick
Du kannst das ganze in einem extra Thread laufen lassen. So habe ich das in einem anderen Projekt von mir auch gemacht. Zusammen mit einem Thread-fähigen (Ring)Puffer läuft das dann ohne Probleme. Man kann dann aus dem Hauptprogramm Daten abfangen und sende, wann man möchte, und im Hintergrund in einem extra Thread werkelt dann eben das serielle Gedöns. Ich glaube ich hatte das sogar schon mal irgendwo hier im Forum gepostet. Ich habe das allerdings im Interface-Stil aufgebaut, ist also recht simpel zu benutzen und.

Re: Ressourcensparende RS232-Kommunikation

Verfasst: 27.12.2014 22:00
von Regenduft
Vielen Dank BSP, Bisonte und NicTheQuick! (in chronologischer Reihenfolge :wink:)

Beim "Thread-Tip" musste ich mir mal wieder an die Stirn klatschen. Ich habe schon so oft irgendwelche Aufgaben in Threads ausgelagert, einfach zu Lernzecken, und wenn es mal eine Gelegenheit gibt wo ein Thread wirklich sinnvoll ist, dann komme ich nicht auf die Idee...

Werde das ganze dann vermutlich etwa so umsetzen (ungetestet, nur zur Schemadarstellung!)

Code: Alles auswählen

EnableExplicit

#USB_BitRate_FullSpeed  = 12000000 ; 12 Mbit/s
#USB_ByteRate_FullSpeed =  1500000 ; 1.5 MB/s

Enumeration CustomEvents #PB_Event_FirstCustomValue
  #Event_SerialInput
EndEnumeration


Declare ThreadProc_SerialPort( *void )
Define THREAD_SerialPort = CreateThread( @ThreadProc_SerialPort() , #Null )
Global MUTEX_SerialPort_LoopDelay = CreateMutex()
Global SerialPort_LoopDelay = 123 ; Pi-mal-Daumen-Auszeit
Global SIGNAL_Serial_VerarbeitungBeendet = CreateSemaphore()

Global SerialPort = OpenSerialPort( #PB_Any, "COM7" , #USB_ByteRate_FullSpeed ,
                                    #PB_SerialPort_NoParity , 8 , 1 , #PB_SerialPort_NoHandshake ,
                                    4096 , 4096 ) ; <- entspricht µC-Puffergröße


Procedure ThreadProc_SerialPort( *void )
  Static LoopDelay = 1
  
  Repeat
    
    If AvailableSerialPortInput( SerialPort )
      
      PostEvent( #Event_SerialInput ) ; Sende Event: "Daten kommen!"
      WaitSemaphore( SIGNAL_Serial_VerarbeitungBeendet ) ; warte auf Ende der Verarbeitung...
      
    Else
      
      If TryLockMutex( MUTEX_SerialPort_LoopDelay )
        LoopDelay = SerialPort_LoopDelay
        UnlockMutex( MUTEX_SerialPort_LoopDelay )
      EndIf
      Delay( LoopDelay ) ; wird bei längerer Inaktivität schrittweise erhöht
      
    EndIf
    
  ForEver
  
EndProcedure


Repeat ; Hauptschleife
  
  Select WaitWindowEvent()
      
    Case #Event_SerialInput
      ; Daten empfangen inkl.
      ; evtl. Gegenkommunikation
      SignalSemaphore( SIGNAL_Serial_VerarbeitungBeendet )
      
  EndSelect
  
ForEver
Ich habe übrigens auch keine echte RS323-Schnittstelle mehr, dafür aber ein µC-Board mit multipler Persönlichkeitsstörung! Hält sich tatsächlich für eine Serielle Schnittstelle, eine Tastatur, einen Joystick, eine Maus und einen MIDI-Controller... Da ja PureBasic bekanntermaßen sehr benutzerfreundlich ist vertragen sich die zwei ganz gut! ;)
(Wer's genauer wissen will: "Teensy ++ 2.0" von "PJRC" mit einem "Atmel AT90USB1286")