Wie kriege ich den input eines seriellen Geräts?

Übersicht BlitzMax, BlitzMax NG Allgemein

Neue Antwort erstellen

poet

Betreff: Wie kriege ich den input eines seriellen Geräts?

BeitragDi, Jun 13, 2006 3:30
Antworten mit Zitat
Benutzer-Profile anzeigen
Ich hab ein USB Gerät (monome.org), das über entsprechende Treiber wie ein altbackened serielles Gerät eingebunden ist. Mit den Stream Funktionen kann ich den COM Port auch öffnen und Daten rausschicken. Nur mit dem lesen der Daten die vom Gerät kommen haperts. Hat da jemand Erfahrung mit?

Mit dem folgenden Code kann ich das Gerät steuern:
Code: [AUSKLAPPEN]
Local mH:TStream
mH = OpenStream("COM3:")

WriteByte(mH,%10000000)
WriteByte(mH,%11111111)
FlushStream(mH)

CloseStream(mH)


Aber wenn ich mit ReadByte() versuche was zu lesen kommt nichts.
Und wenn ich mir mit StreamSize() die länge des Streams anzeigen lasse verändert sich daran nichts wenn ich auf dem Gerät die Knöpfe drücke.
Ich hab auch schon versucht mit ReadStream() einen reinen Lesezugriff zu bekommen, aber das hat auch nichts gebracht.

Vertex

BeitragDi, Jun 13, 2006 11:04
Antworten mit Zitat
Benutzer-Profile anzeigen
Code: [AUSKLAPPEN]
SuperStrict

Framework BRL.StandardIO
Import BRL.PolledInput

Const GENERIC_READ          : Int = $80000000
Const GENERIC_WRITE         : Int = $40000000
Const OPEN_EXISTING         : Int = 3
Const FILE_ATTRIBUTE_NORMAL : Int = $80
Const INVALID_HANDLE_VALUE  : Int = -1

Extern "Win32"
   Function apiCreateFile:Int(FileName$z, DesiredAccess:Int, ShareMode:Int, ..
                              SecurrityAttribute:Byte Ptr, CreationDisposition:Int, ..
                              FlagsAndAttributes:Int, TemplateFile:Int) = "CreateFileA@28"
   Function apiCloseHandle:Int(Obj:Int) = "CloseHandle@4"
   Function apiWriteFile:Int(File:Int, Buffer:Byte Ptr, NumberOfBytesToWrite:Int, ..
                             NumberOfBytesWritten:Int Ptr, Overlapped:Byte Ptr) = "WriteFile@20"
   Function apiReadFile:Int(File:Int, Buffer:Byte Ptr, NumberOfBytesToRead:Int, ..
                            NumberOfBytesRead:Int Ptr, Overlapped:Byte Ptr) = "ReadFile@20"

   Function apiGetCommState:Int(File:Int, DCB:Byte Ptr) = "GetCommState@8"
   Function apiSetCommState:Int(File:Int, DCB:Byte Ptr) = "SetCommState@8"
   Function apiBuildCommDCB:Int(Def$z, DCB:Byte Ptr) = "BuildCommDCBA@8"
   Function apiGetCommTimeouts:Int(File:Int, CommTimeouts:Byte Ptr) = "GetCommTimeouts@8"
   Function apiSetCommTimeouts:Int(File:Int, CommTimeouts:Byte Ptr) = "SetCommTimeouts@8"

   Function GetLastError:Int() = "GetLastError@0"
End Extern

Type TDCB
   Field DCBlength : Int
   Field BaudRate  : Int
   Field Control   : Int
   Field Reserved  : Short
   Field XonLim    : Short
   Field XoffLimc  : Short
   Field ByteSize  : Byte
   Field Parity    : Byte
   Field StopBits  : Byte
   Field XonChar   : Byte
   Field XoffChar  : Byte
   Field ErrorChar : Byte
   Field EofChar   : Byte
   Field EvtChar   : Byte
   Field Reserved1 : Short
End Type

Type TCommtimeouts
   Field ReadIntervalTimeout         : Int
   Field ReadTotalTimeoutMultiplier  : Int
   Field ReadTotalTimeoutConstant    : Int
   Field WriteTotalTimeoutMultiplier : Int
   Field WriteTotalTimeoutConstant   : Int
End Type

Type TComm Extends TStream
   Field Handle       : Int  = INVALID_HANDLE_VALUE
   Field Port         : Byte
   Field ReadTimeout  : Int
   Field WriteTimeout : Int

   Method Open:Int(Port:Byte)
      Local Handle : Int

      Handle = apiCreateFile("COM"+String(Port), GENERIC_READ | GENERIC_WRITE, ..
                             0, Null, OPEN_EXISTING, 0, 0)
      If Handle = INVALID_HANDLE_VALUE Then
         Return False
      Else
         Self.Handle = Handle
         Self.Port   = Port
         Return True
      EndIf
   End Method

   Method Read:Int(Buffer:Byte Ptr, Size:Int)
      Local Count:Int

      If Self.Handle = INVALID_HANDLE_VALUE Then Return 0
      If Not apiReadFile(Self.Handle, Buffer, Size, Varptr(Count), Null) Then Return 0
      Return Count
   End Method
   
   Method Write:Int(Buffer:Byte Ptr, Size:Int)
      Local Count:Int

      If Self.Handle = INVALID_HANDLE_VALUE Then Return 0
      If Not apiWriteFile(Self.Handle, Buffer, Size, Varptr(Count), Null) Then Return 0
      Return Count
   End Method

   Method Close()
      If Self.Handle <> INVALID_HANDLE_VALUE Then
         apiCloseHandle(Self.Handle)
         Self.Handle = INVALID_HANDLE_VALUE
      EndIf
   End Method

   Method Set:Int(Settings:String)
      Local DCB:TDCB

      If Self.Handle = INVALID_HANDLE_VALUE Then Return False

      DCB = New TDCB
      If (Not apiGetCommState(Self.Handle, DCB)) Or ..
         DCB.DCBlength <> SizeOf(TDCB) Then Return False
      If Not apiBuildCommDCB(Settings, DCB) Then Return False
      If Not apiSetCommState(Self.Handle, DCB) Then Return False
      
      Return True
   End Method
   
   Method SetTimeouts:Int(ReadTimeout:Int, WriteTimeout:Int)
      Local Timeouts:TCommtimeouts
      
      If Self.Handle = INVALID_HANDLE_VALUE Then Return False

      Timeouts = New TCommtimeouts
      If Not apiGetCommTimeouts(Self.Handle, Timeouts) Then Return False

      Timeouts.ReadTotalTimeoutConstant  = ReadTimeout
      Timeouts.WriteTotalTimeoutConstant = WriteTimeout
      If Not apiSetCommTimeouts(Self.Handle, Timeouts) Then Return False
      
      Return True
   End Method
End Type

Global COM1    : TComm
Global Message : String

COM1 = New TComm
Print(COM1.Open(1))
Print(COM1.Set("baud=9600 parity=N data=8 stop=1"))
Print(COM1.SetTimeouts(500, 500))

Repeat
   Message = Input("Message: ")
   If Message = "end" Then
      Exit
   Else
      COM1.WriteLine(Message)
   EndIf
   
   Print(COM1.ReadLine())
Forever

COM1.Close()
End


mfg olli

Edit: Jetzt gehts, habe nur "Return True" vergessen.

poet

BeitragDi, Jun 13, 2006 15:16
Antworten mit Zitat
Benutzer-Profile anzeigen
Sehr cool, vielen Dank.

Ich musste noch die Methoden ReadBytes() ändern, so das sie keine Exception wirft wenn es nichts zu lesen gibt, aber damit läufts jetzt.

Zum testen hab ich den Serial Port Monitor verwendet, der kann auch selber ne Verbindung aufbauen und macht das mit den Read Abfragen dann noch ein bischen schöner indem er IRP_MJ_DEVICE_CONTROL (IOCTL_SERIAL_WAIT_ON_MASK) setzt. Das Kommando wird dann erst beendet wenn es was zu lesen gibt. Aber dazu muss das ganz wohl als eigener Thread laufen. Falls du dazu noch ne Idee hast wie man das umsetzten könnte wäre Klasse.

Aber soweit bin ich damit schon sehr glücklich. Vielen Dank nochmal.

Neue Antwort erstellen


Übersicht BlitzMax, BlitzMax NG Allgemein

Gehe zu:

Powered by phpBB © 2001 - 2006, phpBB Group