Problem mit RS232(Serial Port-USB-Adpter) und _CommAPI_OpenCOMPort()

  • Hallo zusammen,

    ich habe die Funktion _CommAPI_OpenCOMPort() (aus https://www.autoitscript.com/wiki/CommAPI) benutzt, um den RS232-Anschluss zu öffnen und die Daten zu senden/empfangen. Mein Problem ist: Im PCs gibt es keinen physikalischen RS232-Anschluss(COM1), ich muss einen RS232-USB-Adapter benutzen. Dann bekommt der RS232-USB-Adapter einen COM10 oder COM12 (größer als COM9) zugewiesen. Dann kann ich mit _CommAPI_OpenCOMPort den COM10 nicht öffnen(die Handle = 0), aber mit _WINAPI_GetLastError() bekomme ich auch keine Error(auch = 0). Aber Ich kann mit HTerm.exe den COM10 schon öffnen und kommunizieren. Es war auch ab und zu passiert, dass ich den COM10 mit meinem Programm wieder geöffnet habe, nur nachdem ich mit HTerm.exe einmal den COM10 verbunden und dann schlossen habe.

    Warum ist es so? Ich bin Anfänger für Autoit und bitte um Eure Hilfe!


    #include "CommInterface.au3"
    #AutoIt3Wrapper_Au3Check_Parameters=-q -d -w 1 -w 2 -w 3 -w- 4 -w 5 -w 6 -w- 7
    $comPort = _CommAPI_OpenCOMPort ("COM10", "19200", "0", "8", "1")
    If $comPort = 0 Then
    _GUICtrlEdit_AppendText($StatusEdit, "don't open comport"&@CRLF)
    Else
    _CommAPI_ClearCommError($comPort)
    If @error Then Return SetError(@error, @ScriptLineNumber)
    _CommAPI_PurgeComm($comPort)
    If @error Then Return SetError(@error, @ScriptLineNumber)
    Endif

    • Offizieller Beitrag

    _CommAPI_OpenCOMPort will als1. Parameter keine Strings "Com10" haben sondern eine Zahl, also 10


    Der 1. Parameter sollte dann 10 und nicht Com10 sein.

    [autoit]

    $comPort = _CommAPI_OpenCOMPort (10,19200,0,8,"1")

    [/autoit]


    Edit: Parameter 5 Stopbits muss als String übergeben werden, da aus 1 Stopbit als Int 1.5 Stopbits werden.


    Edit: Die Func _CommAPI_OpenCOMPort ruft _CommAPI_CreateModeString auf und macht aus allen Angaben des 1 Prameters, der keine Zahl zwischen 1 und 256 ist automatisch Com1: !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

    Zitat von Auszug aus der Func _CommAPI_CreateModeString

    Switch Number($iPort)
    Case 1 To 256
    $sResult = "COM" & $iPort & ":"
    Case Else
    $sResult = "COM1:"
    EndSwitch

    Number("Com10") ergibt 0 also wird der Else Zweig ausgeführt.

    • Offizieller Beitrag

    @Homer J.S.

    Den Fehler der In der Funtion _CommAPI_OpenCOMPort liegt nicht daran, das die Parameter als String anstatt Integer übergeben werden müssen. Der beseitigte Fehler ist eher ein Zufall. Die API ist Fehlerhaft und zwar die Funktion
    _CommAPI_CreateModeString welche von _CommAPI_OpenCOMPort aufgerufen wird im Teil, wo die Stopbits ausgewertet werden.

    [autoit]

    If IsNumber($iStopBits) Then
    Switch $iStopBits
    Case 0
    $sResult &= " STOP=1"
    Case 1
    $sResult &= " STOP=1.5"
    Case 2
    $sResult &= " STOP=2"
    EndSwitch
    Else
    Switch StringUpper($iStopBits)
    Case "1", "O", "ONE"
    $sResult &= " STOP=1"
    Case "1.5", "F", "FIVE"
    $sResult &= " STOP=1.5"
    Case "2", "T", "TWO"
    $sResult &= " STOP=2"
    EndSwitch
    EndIf

    [/autoit]

    Bei 1 Stopbit als Int kommt 1.5 Stopbits heraus, als String werden 1 Stopbit draus. Da hat der Programmierer gemurkst.
    Also können alle Parameter als Int übergeben werden, ausser die Stopbits.

    Edit:
    Der Bug kann auch ein Feature sein, dann muss man ihn aber auch gescheit dokumentieren.
    Was bei der CommApi fehlt ist eine ausführliche Hilfedatei.

    • Offizieller Beitrag

    Wie sieht denn dein Script jetzt aus?

    Btw, du brauchst hier nicht so förmlich zu sein und Ihr oder Ihre zu schreiben.
    Du reicht vollkommen aus. ;)

  • Ich habe $comPort = _CommAPI_OpenCOMPort (10, 19200, 0, 8, 0) geschrieben. Dann habe heute noch mit Oszilloskop den COM10 analysiert und entdeckt den Handshake-Kontrolle ist aktiviert, d.h. wenn ich CTS-Leitung eine hohen Spannung +8V, dann funktioniert die Kommunikation. Dannach habe ich _CommAPI_OpenPort($sMode) benutzt und wollte $tagDCB komplett initialisieren, um fOutputCts auszuschalten. Aber es klappt nicht.

    Local $sMode =_CommAPI_CreateModeString(10, 19200, "0", 8, 0, "0", "0", "0", "0", "0", "0")
    MsgBox(0, "Smode", $sMode)

    $comPort = _CommAPI_OpenPort($sMode)

    In der _CommAPI_OpenPort() gibt es _CommAPI_BuildCommDCB() Funktion, um den DCB zu initialiseieren. Ich habe in der Funktion eine Zeile hingefügt, damit ich anschauen kann, ob DCB wirklich eingestellt ist wie ich wünsche, aber ich habe ungültigen Daten(Baurate = 0, Bytesize = 7....). :S . Weiß Du, wie man DCB mit Autoit einstellen kann? (DLLCALL("Kern32.dll, ..."BuildCommDCB"...))

    Func _CommAPI_OpenPort(Const $sMode)
    Local $sFileName = "\\.\" & StringLeft($sMode, StringInStr($sMode, ":") - 1)
    Local $hFile = _WinAPI_CreateFile($sFileName, 3, 6)
    If @error Then Return SetError(@error, @ScriptLineNumber, 0)
    If $hFile <= 0 Then Return SetError(-1, @ScriptLineNumber, 0)

    Local $tDCB = DllStructCreate($tagDCB)
    Local $tCommTimeouts = DllStructCreate($tagCOMMTIMEOUTS)

    _CommAPI_BuildCommDCB($sMode, $tDCB)
    MsgBox(0, "DCB", CommAPI_CommStateToString($tDCB)
    If @error Then Return SetError(@error, @extended, 0)

    _CommAPI_SetCommTimeoutsElement($tCommTimeouts, "ReadTotalTimeoutMultiplier", 1)
    If @error Then Return SetError(@error, @extended, 0)

    _CommAPI_SetCommTimeoutsElement($tCommTimeouts, "WriteTotalTimeoutMultiplier", 1)
    If @error Then Return SetError(@error, @extended, 0)

    If Not _CommAPI_SetCommState($hFile, $tDCB) Then Return SetError(@error, @extended, 0)
    If Not _CommAPI_SetCommTimeouts($hFile, $tCommTimeouts) Then Return SetError(@error, @extended, 0)

    Return $hFile
    EndFunc ;==>_CommAPI_OpenPort

    2 Mal editiert, zuletzt von cuboro (12. Januar 2015 um 19:19)

    • Offizieller Beitrag

    Woher hast du die Variable $sMode? Eigentlich wird der Mode String von _CommAPI_CreateModeString gebildet.
    Zeig mal dein Script und benutze dafür die Spoiler und AutoIt Tag im Editor.
    Edit: Laut deiner Beschreibung kann es irgendwie nicht so ganz mit rechten Dingen zugehen, du benutzt _CommAPI_OpenCOMPort und dann _CommAPI_OpenPort, das ist doppelt gemoppelt.
    _CommAPI_OpenPort wird schon von _CommAPI_OpenCOMPort aufgerufen.

  • #include-once
    #include <Array.au3>

    #NoAutoIt3Execute

    #include "RS232CommAPI.au3"
    #include "CommInterface.au3"
    #AutoIt3Wrapper_Au3Check_Parameters=-q -d -w 1 -w 2 -w 3 -w- 4 -w 5 -w 6 -w- 7


    ;Funktion für den Butten der COMPORT-Verbindung
    Func _Connect(ByRef $comPort, ByRef $connectFlg, $RF_Flg, $inicmdTable, $iPort)
    local $pflg = False
    local $tflg = False
    local $aCmdPar[4]

    If GUICtrlRead($CMConnect) = "Connect" Then
    ;Local $iPort = GUICtrlRead($ComPort)
    $iPort = StringTrimLeft ($iPort, 3)

    Local $sMode =_CommAPI_CreateModeString(Int($iPort), 19200, "0", 8, 0, "0", "0", "0", "0", "0", "0")
    MsgBox(0, "Smode", $sMode)

    $comPort = _CommAPI_OpenPort($sMode)
    If $comPort = 0 Then
    _GUICtrlEdit_AppendText($StatusEdit, "don't open comport"&@CRLF)

    Else
    _CommAPI_ClearCommError($comPort)
    If @error Then Return SetError(@error, @ScriptLineNumber)
    _CommAPI_PurgeComm($comPort)
    If @error Then Return SetError(@error, @ScriptLineNumber)

    _Sender(3, 1, $comPort) ;den Befehl zu MatchingCube zu senden
    _Receive($pflg, $tflg, $aCmdPar, $comPort)
    ;_ArrayDisplay($aCmdPar)
    If $pflg Then
    If $aCmdPar[0] = 3 Then
    If $aCmdPar[1] = $SERIAL_PORT_AKNOWLEDGE Then
    GUICtrlSetData($CMConnect, "Disconnect")
    GUICtrlSetState($comPort, $GUI_DISABLE)
    _Initial($cmdTabel, $comPort)
    $connectFlg = True

    EndIf
    Else

    _GUICtrlEdit_AppendText($StatusEdit, "no matched SR_Commandos"&@CRLF)
    ;_GUICtrlStatusBar_SetText($StatusBar, "The send- and receive message aren't matching!")
    EndIf

    ElseIf $tflg And Not $pflg Then

    _GUICtrlEdit_AppendText($StatusEdit, "COM-Connect timeout!"&@CRLF)
    ;_GUICtrlStatusBar_SetText($StatusBar, "Timeout! No feedback from generator")
    EndIf


    EndIf
    ElseIf GUICtrlRead($CMConnect) = "Disconnect" Then
    If $RF_Flg Then

    _GUICtrlEdit_AppendText($StatusEdit, "deactivate RF-OFF"&@CRLF)
    ;_GUICtrlStatusBar_SetText($StatusBar, "Please deactivate with RF-OFF")
    Else

    If _CommAPI_ClosePort($comPort) Then
    GUICtrlSetData($CMConnect, "Connect")
    ;GUICtrlSetState($comPort, $GUI_ENABLE)
    $comPort = 0
    $connectFlg = False

    Else
    _GUICtrlEdit_AppendText($StatusEdit, "dosen't close the comport"&@CRLF)
    EndIf
    EndIf
    EndIf

    EndFunc

    • Offizieller Beitrag

    Poste mal bitte den Inhalt von $sMode.

    Einfach mal

    [autoit]

    MsgBox(0, "Smode", $sMode)

    [/autoit]

    gegen

    [autoit]

    ConsoleWrite($sMode & @CRLF)

    [/autoit]

    austauschen und die Ausgabe der Console hier posten.

    Und bitte füge deine Quellcode in AutoIt Tags(das Autoit Icon im Editor) ein, dann ist der Code besser zu lesen und hat Zeilennummern auf die man sich beziehen kann.