COM Objekt für RS232 Kommunikation

  • Aaaalso ;)
    Mit der UDF, welche ich gepostet habe, klappt nun das serielle senden und empfangen "ohne" Windows fremde Dll.
    Auch das RTS setzen kann ich.

    Aber ich möchte noch folgendes:
    - DCD Status abfragen
    - RTS Status setzen - unabhängig von der Portinitialisierung (Klar, der Port muss mal geöffnet und initialisiert sein. Aber ich möchte ohne den Port zu schliessen das RTS zurücksetzen können!)

    Danke für Hilfe! Ich poste anschliessend die fertige UDF für alle!
    Das war immer wieder ein Thema!

  • Hallo veronesi,

    ich habe keine Ahnung von serieller Kommunikation, aber wenn ich das richtig verstehe, könnte das RTS vielleicht so oder so ähnlich funktionieren (ungetestet):

    Spoiler anzeigen
    [autoit]

    ;====================================================================================
    ; Function Name: _SetCOMRts($commPort, $RTS)
    ; Description: Sets RTS flow control
    ; Parameters: $CommPort - value returned by _OpenComm
    ; $RTS : 0 = disable, 1 = enable, 2 = handshake, 3 = toggle
    ; Returns: on success, returns 1
    ; on failure returns -1 and sets @error to 1
    ; Note:
    ;====================================================================================
    Func _SetCOMRTS($CommPort, $RTS)
    ; Die globale Variable $dcb_Struct wurde in _OpenCOMPort() aufgebaut und initialisiert
    ; http://msdn.microsoft.com/en-us/library/…28VS.85%29.aspx
    Local Const $RTS_CONTROL_DISABLE = 0x0000
    Local Const $RTS_CONTROL_ENABLE = 0x1000
    Local Const $RTS_CONTROL_HANDSHAKE = 0x2000
    Local Const $RTS_CONTROL_TOGGLE = 0x3000
    Local $CommCtrl
    If Number($CommPort) < 1 Then Return SetError(1, 1, -1)
    $CommState = DllCall($CommDll, "BOOL", "GetCommState", "HWND", $CommPort, "Ptr", DllStructGetPtr($dcb_Struct))
    If @error Or ($CommState[0] = 0) Then Return SetError(1, 1, -1)
    $CommCtrl = DllStructGetData($dcb_Struct, "fBitfields")
    $CommCtrl = BitAND($CommCtrl, 0xFFFCFFFF) ; RTS-Bits löschen
    Switch $RTS
    Case 0
    Case 1
    $CommCtrl = BitOR($CommCtrl, $RTS_CONTROL_ENABLE)
    Case 2
    $CommCtrl = BitOR($CommCtrl, $RTS_CONTROL_HANDSHAKE)
    Case 3
    $CommCtrl = BitOR($CommCtrl, $RTS_CONTROL_TOGGLE)
    Case Else
    Return SetError(1, 1, -1)
    EndSwitch
    DllStructSetData($dcb_Struct, "fBitfields", Number($CommCtrl))
    $CommState = DllCall($CommDll, "BOOL", "SetCommState", "HWND", $CommPort, "Ptr", DllStructGetPtr($dcb_Struct))
    If @error Or ($CommState[0] = 0) Then Return SetError(1, 1, -1)
    Return True
    EndFunc

    [/autoit]


    Aber was zum Teufel ist ein DCD-Status? ;)

  • Danke für den Tipp. Ich muss das morgen oder übermorgen testen.
    Das DCD kennst Du vielleicht als DTR oder DCR.
    Das ist eigentlich auch das RTS aber auf der EMPFÄNGERSEITE!

    Hast Du eine Idee, wie man dessen Status abfragt?
    Lg und bis morgen oder übermorgen!

  • DTR wären dann die Bits 5 und 6 (von 1 an gezählt) in "fBitfields". Ich schaue mir das später noch mal an.

    Bis dann!

  • @Grossvater:
    Nur ganz kurz:
    Müsste anstelle von BitAND($CommCtrl, 0xFFFCFFFF) nicht BitAND($CommCtrl, 0xFFF3FFFF) heissen?
    Wie dem auch sei. Beides funktioniert nicht GANZ.
    Ich kann zwar das RTS setzen, aber dann nie mehr zurücksetzen, bis der Port geschlossen wird....
    (Vielleicht geht das gar nicht anders, weil es steht ja: Enables the RTS line when the device is opened and leaves it on)

    Greenhorn:
    Danke für den Link. Ich habe mal da noch drin gelesen, aber komme leider immer noch nicht ganz von selber auf die Lösung.

    Lg Veronesi

  • Im Dokument von Greenhorn habe ich noch etwas wichtiges gefunden.
    Ich suche gar nicht das DTR oder DCR! Es war das DCD bzw. M$ scheint es DSR zu nennen ;) (Bei Kollegen in einer Delphi Komponente hiess es aber DCD....)

    Also das RTS ist schon mal gut. Leider kann man es nur einmal setzen und nicht mehr zurücksetzen... Aber immerhin.

    Und das DCD sollte man über GetCommModemStatus erfragen können. Aber leider konnte ich noch nicht herausfinden, wie das geht!

  • Hallo, Danke für dein script, aber ich bekomme egal was ich mache die Fehlermeldung "Der Sende... konnte nicht geöffnet werden
    Woran kann das liegen?

  • Und das DCD sollte man über GetCommModemStatus erfragen können. Aber leider konnte ich noch nicht herausfinden, wie das geht!


    Hi, wie sieht denn dein Skript derzeit aus ?

    Remarks

    The GetCommModemStatus function is useful when you are using the WaitCommEvent function to monitor the CTS, RLSD, DSR, or ring indicator signals. To detect when these signals change state, use WaitCommEvent and then use GetCommModemStatus to determine the state after a change occurs.

    The function fails if the hardware does not support the control-register values.

    Remarks

    The WaitCommEvent function monitors a set of events for a specified communications resource. To set and query the current event mask of a communications resource, use the SetCommMask and GetCommMask functions.
    If the overlapped operation cannot be completed immediately, the function returns FALSE and the GetLastError function returns ERROR_IO_PENDING, indicating that the operation is executing in the background. When this happens, the system sets the hEvent member of the OVERLAPPED structure to the not-signaled state before WaitCommEvent returns, and then it sets it to the signaled state when one of the specified events or an error occurs. The calling process can use one of the wait functions to determine the event object's state and then use the GetOverlappedResult function to determine the results of the WaitCommEvent operation. GetOverlappedResult reports the success or failure of the operation, and the variable pointed to by the lpEvtMask parameter is set to indicate the event that occurred.
    If a process attempts to change the device handle's event mask by using the SetCommMask function while an overlapped WaitCommEvent operation is in progress, WaitCommEvent returns immediately. The variable pointed to by the lpEvtMask parameter is set to zero.

    Beispiel: Monitoring Communications Events


    Gruß
    Greenhorn


  • So, meine UDF sieht nun folgendermassen aus:

    Spoiler anzeigen
    [autoit]

    #cs
    UDF cfx.au3
    serial functions using kernel32.dll
    V1.0
    Uwe Lahni 2008
    V2.0
    Andrew Calcutt 05/16/2009 - Started converting to UDF
    V2.1
    Mikko Keski-Heroja 02/23/2011 - UDF is now compatible with Opt("MustDeclareVars",1) and Date.au3. Global variable $dll is renamed to $commDll.
    V2.2
    Veronesi 04/26/2011 - Changed some cosmetics and documentation
    #ce
    #include-once
    Global $commDll
    Global $hSerialPort
    Global $dcb_Struct
    Global $commtimeout
    Global $commtimeout_Struct
    Global $commState
    ;~ Global $commState_Struct
    ;~ Global Const $STX = Chr(2)
    ;~ Global Const $ETX = Chr(3)
    ;~ Global Const $EOT = Chr(4)
    ;~ Global Const $ENQ = Chr(5)
    ;~ Global Const $ACK = Chr(6)
    ;~ Const $NAK = Chr(15)
    ;~ Const $DLE = Chr(16)

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    ;====================================================================================
    ; Function Name: _OpenCOMPort($CommPort, $CommBaud, $CommBits, $CommParity, $CommStop, $SetRTS)
    ; Description: Opens serial port
    ; Parameters: $CommPort
    ; $CommBits - 4-8
    ; $CommParity - 0=none, 1=odd, 2=even, 3=mark, 4=space
    ; $CommStop - 0,1,5,2
    ; $SetRTS - 0 = RTS => 0 / 1 = RTS => 1 / 2 = RTS handshake / 3 = RTS toggle
    ; Returns: on success, returns serial port id?
    ; on failure returns -1 and sets @error to 1
    ; Note:
    ;====================================================================================
    Func _OpenCOMPort($CommPort, $CommBaud = '9600', $CommBits = '8', $CommParity = '0', $CommStop = '0', $SetRTS = 0)
    #cs
    CommCtrl => fBitfields => http://msdn.microsoft.com/en-us/library/…4(v=vs.85).aspx
    http://www.hpcc.ecs.soton.ac.uk/software/Win32API.Txt
    ' The fourteen actual DCB bit-sized data fields within the four bytes of fBitFields can be manipulated by bitwise logical And/Or operations.
    ' FieldName Bit # Description
    ' ----------------- ----- ------------------------------
    ' fBinary 1 binary mode, no EOF check
    ' fParity 2 enable parity checking
    ' fOutxCtsFlow 3 CTS output flow control
    ' fOutxDsrFlow 4 DSR output flow control
    ' fDtrControl 5 DTR flow control type (2 bits)
    ' fDsrSensitivity 7 DSR sensitivity
    ' fTXContinueOnXoff 8 XOFF continues Tx
    ' fOutX 9 XON/XOFF out flow control
    ' fInX 10 XON/XOFF in flow control
    ' fErrorChar 11 enable error replacement
    ' fNull 12 enable null stripping
    ' fRtsControl 13 RTS flow control (2 bits)
    ' fAbortOnError 15 abort reads/writes on error
    ' fDummy2 16 reserved
    #ce

    [/autoit] [autoit][/autoit] [autoit]

    Local Const $RTS_CONTROL_DISABLE = 0x0000
    Local Const $RTS_CONTROL_ENABLE = 0x1000
    Local Const $RTS_CONTROL_HANDSHAKE = 0x2000
    Local Const $RTS_CONTROL_TOGGLE = 0x3000
    Local $CommCtrl
    $commDll = DllOpen("kernel32.dll")
    Local $dcbs = "long DCBlength;long BaudRate; long fBitFields;short wReserved;" & _
    "short XonLim;short XoffLim;byte Bytesize;byte parity;byte StopBits;byte XonChar; byte XoffChar;" & _
    "Byte ErrorChar;Byte EofChar;Byte EvtChar;short wReserved1"

    [/autoit] [autoit][/autoit] [autoit]

    Local $commtimeouts = "long ReadIntervalTimeout;long ReadTotalTimeoutMultiplier;" & _
    "long ReadTotalTimeoutConstant;long WriteTotalTimeoutMultiplier;long WriteTotalTimeoutConstant"

    [/autoit] [autoit][/autoit] [autoit]

    Local Const $GENERIC_READ_WRITE = 0xC0000000
    Local Const $OPEN_EXISTING = 3
    Local Const $FILE_ATTRIBUTE_NORMAL = 0x80
    ;~ Local Const $NOPARITY = 0
    ;~ Local Const $ONESTOPBIT = 0

    [/autoit] [autoit][/autoit] [autoit]

    $dcb_Struct = DllStructCreate($dcbs)
    If @error Then Return SetError(1, 1, -1)

    [/autoit] [autoit][/autoit] [autoit]

    $commtimeout_Struct = DllStructCreate($commtimeouts)
    If @error Then Return SetError(1, 1, -1)

    [/autoit] [autoit][/autoit] [autoit]

    $hSerialPort = DllCall($commDll, "hwnd", "CreateFile", "str", "COM" & $CommPort, _
    "int", $GENERIC_READ_WRITE, _
    "int", 0, _
    "ptr", 0, _
    "int", $OPEN_EXISTING, _
    "int", $FILE_ATTRIBUTE_NORMAL, _
    "int", 0)
    If @error Then Return SetError(1, 1, -1)
    If Number($hSerialPort[0]) < 1 Then Return SetError(1, 1, -1)
    $commState = DllCall($commDll, "long", "GetCommState", "hwnd", $hSerialPort[0], "ptr", DllStructGetPtr($dcb_Struct))

    [/autoit] [autoit][/autoit] [autoit]

    $CommCtrl = BitAND($CommCtrl, 0xFFF3FFFF) ; RTS-Bits löschen
    Switch $SetRTS
    Case 0
    Case 1
    $CommCtrl = BitOR($CommCtrl, $RTS_CONTROL_ENABLE)
    Case 2
    $CommCtrl = BitOR($CommCtrl, $RTS_CONTROL_HANDSHAKE)
    Case 3
    $CommCtrl = BitOR($CommCtrl, $RTS_CONTROL_TOGGLE)
    Case Else
    Return SetError(1, 1, -1)
    EndSwitch

    [/autoit] [autoit][/autoit] [autoit]

    If @error Then Return SetError(1, 1, -1)
    DllStructSetData($dcb_Struct, "DCBLength", DllStructGetSize($dcb_Struct))
    If @error Then Return SetError(1, 1, -1)
    DllStructSetData($dcb_Struct, "BaudRate", $CommBaud)
    If @error Then Return SetError(1, 1, -1)
    DllStructSetData($dcb_Struct, "Bytesize", $CommBits)
    If @error Then Return SetError(1, 1, -1)
    DllStructSetData($dcb_Struct, "fBitfields", Number($CommCtrl))
    If @error Then Return SetError(1, 1, -1)
    DllStructSetData($dcb_Struct, "Parity", $CommParity)
    If @error Then Return SetError(1, 1, -1)
    DllStructSetData($dcb_Struct, "StopBits", '0x' & $CommStop)
    If @error Then Return SetError(1, 1, -1)
    DllStructSetData($dcb_Struct, "XonLim", 2048)
    If @error Then Return SetError(1, 1, -1)
    DllStructSetData($dcb_Struct, "XoffLim", 512)
    If @error Then Return SetError(1, 1, -1)
    $commState = DllCall($commDll, "short", "SetCommState", "hwnd", $hSerialPort[0], "ptr", DllStructGetPtr($dcb_Struct))
    If @error Then Return SetError(1, 1, -1)

    [/autoit] [autoit][/autoit] [autoit]

    If $commState[0] = 0 Then Return SetError(1, 1, -1)
    DllStructSetData($commtimeout_Struct, "ReadIntervalTimeout", -1)
    $commtimeout = DllCall($commDll, "long", "SetCommTimeouts", "hwnd", $hSerialPort[0], "ptr", DllStructGetPtr($commtimeout_Struct))
    If @error Then Return SetError(1, 1, -1)
    Return Number($hSerialPort[0])
    EndFunc ;==>_OpenCOMPort

    [/autoit] [autoit][/autoit] [autoit]

    ;====================================================================================
    ; Function Name: _CloseCOMPort($CommSerialPort)
    ; Description: Closes serial port
    ; Parameters: $CommSerialPort - value returned by _OpenComm
    ; Returns: on success, returns 1
    ; on failure returns -1 and sets @error to 1
    ; Note:
    ;====================================================================================
    Func _CloseCOMPort($CommSerialPort)
    Local $closeerr = DllCall($commDll, "int", "CloseHandle", "hwnd", $CommSerialPort)
    DllClose($commDll)
    If @error Then Return SetError(1, 1, -1)
    Return ($closeerr[0])
    EndFunc ;==>_CloseCOMPort

    [/autoit] [autoit][/autoit] [autoit]

    ;====================================================================================
    ; Function Name: _SendSerialString($CommSerialPort, $sSensString)
    ; Description: Send a String
    ; Parameters: $CommSerialPort - value returned by _OpenComm
    ; $sSendString - String to send
    ; Returns: on success, returns 1
    ; on failure returns -1 and sets @error to 1
    ; Note:
    ;====================================================================================
    Func _SendSerialString($CommSerialPort, $sSendString)
    Local $lptr0 = DllStructCreate("long_ptr")
    DllCall($commDll, "int", "WriteFile", "hwnd", $CommSerialPort, _
    "str", $sSendString, _
    "int", StringLen($sSendString), _
    "long_ptr", DllStructGetPtr($lptr0), _
    "ptr", 0)
    If @error Then Return SetError(1, 1, -1)
    EndFunc ;==>_SendSerialString

    [/autoit] [autoit][/autoit] [autoit]

    ;====================================================================================
    ; Function Name: _ReceiveStringWait($CommSerialPort, $MinBufferSize, $MaxWaitTime)
    ; Description: Recieves data
    ; Parameters: $CommSerialPort - value returned by _OpenComm
    ; $MinBufferSize - Buffer size to wait for
    ; $MaxWaitTime - Maximum time to wait before failing
    ; Returns: on success, returns String
    ; on failure returns -1 and sets @error to 1
    ; Note:
    ;====================================================================================
    Func _ReceiveStringWait($CommSerialPort, $MinBufferSize, $MaxWaitTime)
    Local $rxbuf
    Local $jetza = TimerInit()
    Local $lptr0 = DllStructCreate("long_ptr")

    [/autoit] [autoit][/autoit] [autoit]

    Local $rxr, $rxl, $to
    Do
    $rxr = DllCall($commDll, "int", "ReadFile", "hwnd", $CommSerialPort, _
    "str", " ", _
    "int", 1, _
    "long_ptr", DllStructGetPtr($lptr0), _
    "ptr", 0)
    If @error Then Return SetError(1, 1, -1)
    $rxl = DllStructGetData($lptr0, 1)
    If $rxl >= 1 Then
    $rxbuf &= $rxr[2]
    EndIf
    $to = TimerDiff($jetza)
    Until StringLen($rxbuf) >= $MinBufferSize Or $to > $MaxWaitTime
    Return ($rxbuf)
    EndFunc ;==>_ReceiveStringWait

    [/autoit] [autoit][/autoit] [autoit]

    ;====================================================================================
    ; Function Name: _SetCOMRTS($commPort, $RTS)
    ; Description: Sets RTS flow control
    ; Parameters: $CommPort - value returned by _OpenComm
    ; $RTS : 0 = disable, 1 = enable, 2 = handshake, 3 = toggle
    ; Returns: on success, returns 1
    ; on failure returns -1 and sets @error to 1
    ; Note:
    ;====================================================================================
    Func _SetCOMRTS($CommPort, $RTS)
    ; http://msdn.microsoft.com/en-us/library/…28VS.85%29.aspx
    Local Const $RTS_CONTROL_DISABLE = 0x0000
    Local Const $RTS_CONTROL_ENABLE = 0x1000
    Local Const $RTS_CONTROL_HANDSHAKE = 0x2000
    Local Const $RTS_CONTROL_TOGGLE = 0x3000
    Local $CommCtrl
    If Number($CommPort) < 1 Then Return SetError(1, 1, -1)
    $CommState = DllCall($CommDll, "BOOL", "GetCommState", "HWND", $CommPort, "Ptr", DllStructGetPtr($dcb_Struct))
    If @error Or ($CommState[0] = 0) Then Return SetError(1, 1, -1)
    $CommCtrl = DllStructGetData($dcb_Struct, "fBitfields")
    $CommCtrl = BitAND($CommCtrl, 0xFFF3FFFF) ; RTS-Bits löschen
    Switch $RTS
    Case 0
    Case 1
    $CommCtrl = BitOR($CommCtrl, $RTS_CONTROL_ENABLE)
    Case 2
    $CommCtrl = BitOR($CommCtrl, $RTS_CONTROL_HANDSHAKE)
    Case 3
    $CommCtrl = BitOR($CommCtrl, $RTS_CONTROL_TOGGLE)
    Case Else
    Return SetError(1, 1, -1)
    EndSwitch
    DllStructSetData($dcb_Struct, "fBitfields", Number($CommCtrl))
    $CommState = DllCall($CommDll, "BOOL", "SetCommState", "HWND", $CommPort, "Ptr", DllStructGetPtr($dcb_Struct))
    If @error Or ($CommState[0] = 0) Then Return SetError(1, 1, -1)
    Return True
    EndFunc ;==>_SetCOMRTS

    [/autoit] [autoit][/autoit] [autoit]

    ;====================================================================================
    ; Function Name: _GetCOMDCD($commPort)
    ; Description: Gets DCD status (Set from RTS in 0-Modem Cable)
    ; Parameters: $CommPort - value returned by _OpenComm
    ; Returns: on success, returns value
    ; on failure returns -1 and sets @error to 1
    ; Note:
    ;====================================================================================
    Func _GetCOMDCD($CommPort)
    ; http://msdn.microsoft.com/en-us/library/…8(v=vs.85).aspx
    Local $CommCtrl, $lpModemStat
    If Number($CommPort) < 1 Then Return SetError(1, 1, -1)
    $lpModemStat = DllStructCreate("DWORD")
    $CommState = DllCall($CommDll, "BOOL", "GetCommModemStatus", "HWND", $CommPort, "Ptr", DllStructGetPtr($lpModemStat))
    If @error Or ($CommState[0] = 0) Then Return SetError(1, 1, -1)
    $CommCtrl = DllStructGetData($lpModemStat, 1)
    If BitAND($CommCtrl, 0x80) Then Return 1 ; Isolate DCD (RLSD)
    Return 0
    EndFunc ;==<GetCOMDCD

    [/autoit]

    Es ist mir nun gelungen, das DCD abzufragen.
    Ich weiss zwar nicht, warum das DCD auf der Empfängerseite gesetzt wird, wenn ich das RTS setze, aber ich habe es bei unseren Geräten getestet und mit einem gekauften seriellen Programm geprüft. Es ist so...!
    Nun müsste ich nur noch das RTS im laufenden Betrieb setzen können! Das habe ich noch nicht geschafft!

    Veronesi

  • So, nun konnte ich das RTS auch noch im laufenden Betrieb setzen!
    Nun funktioniert alles (was ich wollte) einwandfrei.
    Und das ohne externe (bzw. ohne M$ fremde) Dll!

    Hier die "fertige" UDF:

    Spoiler anzeigen
    [autoit][/autoit] [autoit][/autoit] [autoit]

    #cs
    UDF cfx.au3
    serial functions using kernel32.dll
    V1.0
    Uwe Lahni 2008
    V2.0
    Andrew Calcutt 05/16/2009 - Started converting to UDF
    V2.1
    Mikko Keski-Heroja 02/23/2011 - UDF is now compatible with Opt("MustDeclareVars",1) and Date.au3. Global variable $dll is renamed to $commDll.
    V2.2
    Veronesi 04/26/2011 - Changed some cosmetics and documentation / Add Function to set RTS and to get DCD Status
    #ce
    #include-once
    Global $commDll
    Global $hSerialPort
    Global $dcb_Struct
    Global $commtimeout
    Global $commtimeout_Struct
    Global $commState

    [/autoit] [autoit][/autoit] [autoit]

    ;====================================================================================
    ; Function Name: _OpenCOMPort($CommPort, $CommBaud, $CommBits, $CommParity, $CommStop, $SetRTS)
    ; Description: Opens serial port
    ; Parameters: $CommPort
    ; $CommBits - 4-8
    ; $CommParity - 0=none, 1=odd, 2=even, 3=mark, 4=space
    ; $CommStop - 0 => 1 Stop bit / 1 => 1.5 Stop bits / 2 => 2 Stop bits
    ; $SetRTS - 0 = RTS => 0 / 1 = RTS => 1 / 2 = RTS handshake / 3 = RTS toggle
    ; Returns: on success, returns serial port id?
    ; on failure returns -1 and sets @error to 1
    ; Note:
    ;====================================================================================
    Func _OpenCOMPort($CommPort, $CommBaud = '9600', $CommBits = '8', $CommParity = '0', $CommStop = '0', $SetRTS = 0)
    #cs
    CommCtrl => fBitfields => http://msdn.microsoft.com/en-us/library/…4(v=vs.85).aspx
    http://www.hpcc.ecs.soton.ac.uk/software/Win32API.Txt
    ' The fourteen actual DCB bit-sized data fields within the four bytes of fBitFields can be manipulated by bitwise logical And/Or operations.
    ' FieldName Bit # Description
    ' ----------------- ----- ------------------------------
    ' fBinary 1 binary mode, no EOF check
    ' fParity 2 enable parity checking
    ' fOutxCtsFlow 3 CTS output flow control
    ' fOutxDsrFlow 4 DSR output flow control
    ' fDtrControl 5 DTR flow control type (2 bits)
    ' fDsrSensitivity 7 DSR sensitivity
    ' fTXContinueOnXoff 8 XOFF continues Tx
    ' fOutX 9 XON/XOFF out flow control
    ' fInX 10 XON/XOFF in flow control
    ' fErrorChar 11 enable error replacement
    ' fNull 12 enable null stripping
    ' fRtsControl 13 RTS flow control (2 bits)
    ' fAbortOnError 15 abort reads/writes on error
    ' fDummy2 16 reserved
    #ce

    [/autoit] [autoit][/autoit] [autoit]

    Local Const $RTS_CONTROL_DISABLE = 0x0000
    Local Const $RTS_CONTROL_ENABLE = 0x1000
    Local Const $RTS_CONTROL_HANDSHAKE = 0x2000
    Local Const $RTS_CONTROL_TOGGLE = 0x3000
    Local $CommCtrl
    $commDll = DllOpen("kernel32.dll")
    Local $dcbs = "long DCBlength;long BaudRate; long fBitFields;short wReserved;" & _
    "short XonLim;short XoffLim;byte Bytesize;byte parity;byte StopBits;byte XonChar; byte XoffChar;" & _
    "Byte ErrorChar;Byte EofChar;Byte EvtChar;short wReserved1"

    [/autoit] [autoit][/autoit] [autoit]

    Local $commtimeouts = "long ReadIntervalTimeout;long ReadTotalTimeoutMultiplier;" & _
    "long ReadTotalTimeoutConstant;long WriteTotalTimeoutMultiplier;long WriteTotalTimeoutConstant"

    [/autoit] [autoit][/autoit] [autoit]

    Local Const $GENERIC_READ_WRITE = 0xC0000000
    Local Const $OPEN_EXISTING = 3
    Local Const $FILE_ATTRIBUTE_NORMAL = 0x80

    [/autoit] [autoit][/autoit] [autoit]

    $dcb_Struct = DllStructCreate($dcbs)
    If @error Then Return SetError(1, 1, -1)

    [/autoit] [autoit][/autoit] [autoit]

    $commtimeout_Struct = DllStructCreate($commtimeouts)
    If @error Then Return SetError(1, 1, -1)

    [/autoit] [autoit][/autoit] [autoit]

    $hSerialPort = DllCall($commDll, "hwnd", "CreateFile", "str", "COM" & $CommPort, _
    "int", $GENERIC_READ_WRITE, _
    "int", 0, _
    "ptr", 0, _
    "int", $OPEN_EXISTING, _
    "int", $FILE_ATTRIBUTE_NORMAL, _
    "int", 0)
    If @error Then Return SetError(1, 1, -1)
    If Number($hSerialPort[0]) < 1 Then Return SetError(1, 1, -1)
    $commState = DllCall($commDll, "long", "GetCommState", "hwnd", $hSerialPort[0], "ptr", DllStructGetPtr($dcb_Struct))

    [/autoit] [autoit][/autoit] [autoit]

    $CommCtrl = BitAND($CommCtrl, 0xFFFCFFF) ; RTS-Bits löschen
    Switch $SetRTS
    Case 0
    Case 1
    $CommCtrl = BitOR($CommCtrl, $RTS_CONTROL_ENABLE)
    Case 2
    $CommCtrl = BitOR($CommCtrl, $RTS_CONTROL_HANDSHAKE)
    Case 3
    $CommCtrl = BitOR($CommCtrl, $RTS_CONTROL_TOGGLE)
    Case Else
    Return SetError(1, 1, -1)
    EndSwitch

    [/autoit] [autoit][/autoit] [autoit]

    If @error Then Return SetError(1, 1, -1)
    DllStructSetData($dcb_Struct, "DCBLength", DllStructGetSize($dcb_Struct))
    If @error Then Return SetError(1, 1, -1)
    DllStructSetData($dcb_Struct, "BaudRate", $CommBaud)
    If @error Then Return SetError(1, 1, -1)
    DllStructSetData($dcb_Struct, "Bytesize", $CommBits)
    If @error Then Return SetError(1, 1, -1)
    DllStructSetData($dcb_Struct, "fBitfields", Number($CommCtrl))
    If @error Then Return SetError(1, 1, -1)
    DllStructSetData($dcb_Struct, "Parity", $CommParity)
    If @error Then Return SetError(1, 1, -1)
    DllStructSetData($dcb_Struct, "StopBits", '0x' & $CommStop)
    If @error Then Return SetError(1, 1, -1)
    DllStructSetData($dcb_Struct, "XonLim", 2048)
    If @error Then Return SetError(1, 1, -1)
    DllStructSetData($dcb_Struct, "XoffLim", 512)
    If @error Then Return SetError(1, 1, -1)
    $commState = DllCall($commDll, "short", "SetCommState", "hwnd", $hSerialPort[0], "ptr", DllStructGetPtr($dcb_Struct))
    If @error Then Return SetError(1, 1, -1)

    [/autoit] [autoit][/autoit] [autoit]

    If $commState[0] = 0 Then Return SetError(1, 1, -1)
    DllStructSetData($commtimeout_Struct, "ReadIntervalTimeout", -1)
    $commtimeout = DllCall($commDll, "long", "SetCommTimeouts", "hwnd", $hSerialPort[0], "ptr", DllStructGetPtr($commtimeout_Struct))
    If @error Then Return SetError(1, 1, -1)
    Return Number($hSerialPort[0])
    EndFunc ;==>_OpenCOMPort

    [/autoit] [autoit][/autoit] [autoit]

    ;====================================================================================
    ; Function Name: _CloseCOMPort($CommSerialPort)
    ; Description: Closes serial port
    ; Parameters: $CommSerialPort - value returned by _OpenComm
    ; Returns: on success, returns 1
    ; on failure returns -1 and sets @error to 1
    ; Note:
    ;====================================================================================
    Func _CloseCOMPort($CommSerialPort)
    Local $closeerr = DllCall($commDll, "int", "CloseHandle", "hwnd", $CommSerialPort)
    DllClose($commDll)
    If @error Then Return SetError(1, 1, -1)
    Return ($closeerr[0])
    EndFunc ;==>_CloseCOMPort

    [/autoit] [autoit][/autoit] [autoit]

    ;====================================================================================
    ; Function Name: _SendSerialString($CommSerialPort, $sSensString)
    ; Description: Send a String
    ; Parameters: $CommSerialPort - value returned by _OpenComm
    ; $sSendString - String to send
    ; Returns: on success, returns 1
    ; on failure returns -1 and sets @error to 1
    ; Note:
    ;====================================================================================
    Func _SendSerialString($CommSerialPort, $sSendString)
    Local $lptr0 = DllStructCreate("long_ptr")
    DllCall($commDll, "int", "WriteFile", "hwnd", $CommSerialPort, _
    "str", $sSendString, _
    "int", StringLen($sSendString), _
    "long_ptr", DllStructGetPtr($lptr0), _
    "ptr", 0)
    If @error Then Return SetError(1, 1, -1)
    EndFunc ;==>_SendSerialString

    [/autoit] [autoit][/autoit] [autoit]

    ;====================================================================================
    ; Function Name: _ReceiveStringWait($CommSerialPort, $MinBufferSize, $MaxWaitTime)
    ; Description: Recieves data
    ; Parameters: $CommSerialPort - value returned by _OpenComm
    ; $MinBufferSize - Buffer size to wait for
    ; $MaxWaitTime - Maximum time to wait before failing
    ; Returns: on success, returns String
    ; on failure returns -1 and sets @error to 1
    ; Note:
    ;====================================================================================
    Func _ReceiveStringWait($CommSerialPort, $MinBufferSize, $MaxWaitTime)
    Local $rxbuf
    Local $jetza = TimerInit()
    Local $lptr0 = DllStructCreate("long_ptr")

    [/autoit] [autoit][/autoit] [autoit]

    Local $rxr, $rxl, $to
    Do
    $rxr = DllCall($commDll, "int", "ReadFile", "hwnd", $CommSerialPort, _
    "str", " ", _
    "int", 1, _
    "long_ptr", DllStructGetPtr($lptr0), _
    "ptr", 0)
    If @error Then Return SetError(1, 1, -1)
    $rxl = DllStructGetData($lptr0, 1)
    If $rxl >= 1 Then
    $rxbuf &= $rxr[2]
    EndIf
    $to = TimerDiff($jetza)
    Until StringLen($rxbuf) >= $MinBufferSize Or $to > $MaxWaitTime
    Return ($rxbuf)
    EndFunc ;==>_ReceiveStringWait

    [/autoit] [autoit][/autoit] [autoit]

    ;====================================================================================
    ; Function Name: _SetCOMRTS($commPort, $RTS)
    ; Description: Sets RTS flow control
    ; Parameters: $CommPort - value returned by _OpenComm
    ; $RTS : 0 = disable, 1 = enable
    ; Returns: on success, returns 1
    ; on failure returns -1 and sets @error to 1
    ; Note:
    ;====================================================================================
    Func _SetCOMRTS($CommPort, $SetRTS)
    ;http://msdn.microsoft.com/en-us/library/…4(v=vs.85).aspx
    Local $EscapeComm, $RTS
    If Number($CommPort) < 1 Then Return SetError(1, 1, -1)
    Switch $SetRTS
    Case 0
    $RTS = 4
    Case 1
    $RTS = 3
    Case Else
    Return SetError(1, 1, -1)
    EndSwitch
    $EscapeComm = DllCall($CommDll, "BOOL", "EscapeCommFunction", "HWND", $CommPort, "DWORD", $RTS)
    If @error Or ($EscapeComm[0] = 0) Then Return SetError(1, 1, -1)
    Return True
    EndFunc ;==>_SetCOMRTS

    [/autoit] [autoit][/autoit] [autoit]

    ;====================================================================================
    ; Function Name: _GetCOMDCD($commPort)
    ; Description: Gets DCD status (Set from RTS in 0-Modem Cable)
    ; Parameters: $CommPort - value returned by _OpenComm
    ; Returns: on success, returns value
    ; on failure returns -1 and sets @error to 1
    ; Note:
    ;====================================================================================
    Func _GetCOMDCD($CommPort)
    ; http://msdn.microsoft.com/en-us/library/…8(v=vs.85).aspx
    Local $CommCtrl, $lpModemStat
    If Number($CommPort) < 1 Then Return SetError(1, 1, -1)
    $lpModemStat = DllStructCreate("DWORD")
    $CommState = DllCall($CommDll, "BOOL", "GetCommModemStatus", "HWND", $CommPort, "Ptr", DllStructGetPtr($lpModemStat))
    If @error Or ($CommState[0] = 0) Then Return SetError(1, 1, -1)
    $CommCtrl = DllStructGetData($lpModemStat, 1)
    If BitAND($CommCtrl, 0x80) Then Return 1 ; Isolate DCD (RLSD)
    Return 0
    EndFunc ;==>_GetCOMDCD

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit][/autoit]

    Grüsse
    Veronesi

    2 Mal editiert, zuletzt von veronesi (27. April 2011 um 08:22)

  • Moin veronesi,

    zu spät, Du hast es ja jetzt selbst hingekriegt. Was ich eigentlich noch sagen wollte:

    Müsste anstelle von BitAND($CommCtrl, 0xFFFCFFFF) nicht BitAND($CommCtrl, 0xFFF3FFFF) heissen?


    Eher nicht, es sollte aber wohl BitAND($CommCtrl, 0xFFFFCFFF) sein.

    Viel Erfolg weiterhin! ;)

  • @Rene
    Wenn Du für die Relaiskarte 1 Stop-Bit brauchst, musst Du das Stop-Bit auf 0 setzen! (War in der alten UDF falsch/irreführend beschrieben.)
    Also irgendwie so:

    Spoiler anzeigen
    [autoit]

    #include "Func_Serial.au3"
    #Include <String.au3>

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    ;Alle Konstanten müssen angepasst werden!
    ;Gemäss Spezifikationen der Karte!
    Global Const $ComPort = 3
    Global Const $Baudrate = 19200
    Global Const $Bits = 8
    Global Const $Parity = 0
    Global Const $Stop = 0
    Global Const $Rts = 0

    [/autoit] [autoit][/autoit] [autoit]

    Global Const $Byte1 = 0x01
    Global Const $Byte2 = 0x02
    Global Const $Byte3 = 0xFF
    Global Const $Byte4 = BitXOR($Byte1, $Byte2, $Byte3)

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    Local $SendPort = _OpenCOMPort($ComPort, $Baudrate, $Bits, $Parity, $Stop, $Rts)
    If $SendPort = -1 Then MsgBox(0, "Fehler", "Der COM-Port konnte nicht geöffnet werden!")

    [/autoit] [autoit][/autoit] [autoit]

    _SendSerialString($SendPort, _HexToString($Byte1 & $Byte2 & $Byte3 & $Byte4))
    Sleep(500)
    _CloseCOMPort($SendPort)

    [/autoit]

    @Grossvater / @all
    Vielen Dank für Deine / Eure Unterstützung.
    Ich habe nun eine sehr gute UDF, welche ich einsetzen kann. Mal sehen ob später noch Fehler darin auftauchen!

    Beste Grüsse und Danke!

  • @ veronesi, ja das habe ich schon mitbekommen das da was mit dem stopbit ist, das läuft mitlerweile!
    aber senden tut der was er will
    ich habe nun mal in den quellcode für VB6 geschaut da machen Sie überall chr() und senden das dann, aber irgendwie sendet er mit den Chr(0) nicht als 00 sondern als 30

  • @ veronesi
    Ja das hab ich auch schon geschaut, wenn ich Chr(48) mache sendet er mir ein 30, ich braüchte aber eine 00
    ich werd hier bald zum hirschen.....:-)

  • keine ahnung wo er mir die 3 da her holt

    Habe ich mi6lerweile anders gelöst, da ich die flgende Zeichenfolge irgendwie nicht hinbekommen habe:

    03 01 00 02
    Er schrieb mir mimmer
    03 01 30 02

    Einmal editiert, zuletzt von Rene_RNI (27. April 2011 um 13:11)

  • Nun habe ich nur noch ein Problem,
    ich müsste an den Comport einen Taster anschließen, wenn der betätigt wird muss weiter gemacht werden im Programm

    Die sachen mit den Befehlen senden an den Comport habe ich alles hinbekommen