Seite 2 von 2

Re: WriteSerialPortString()

Verfasst: 29.04.2024 21:09
von PIC18F2550
:o ES GIBT KEIN "ReadSerialPortString()"!!!!

Mal sehen wie ich das hinbekomme mit ReadSerialPortData.

Code: Alles auswählen

    Print("USBALL -> Byte: "+Str(ReadSerialPortData(0, @Pufferin,4)))
    ou$=Hex(Pufferin(0))+"- "+Hex(Pufferin(1))+"- "+Hex(Pufferin(2))+"- "+Hex(Pufferin(3)) 
Das ergebnis ist Das....Nüscht.

Code: Alles auswählen

OS Windows
Error:  Can't open the serial port: COM6
SerialPort COM7 opened With success
CHECK -> USBALL: 4
USBALL -> Byte: 4  [0-0-0-0]
START I/O -> Byte: 19
OUT I/O 55-55-55 -> Byte: 16
OUT I/O AA-AA-AA -> Byte: 16
OUT I/O 55-55-55 -> Byte: 16
OUT I/O AA-AA-AA -> Byte: 16
OUT I/O 55-55-55 -> Byte: 16
OUT I/O AA-AA-AA -> Byte: 16
STOP I/O -> Byte: 7
Error:  Can't open the serial port: COM8
Drücken Sie eine Taste zum Beenden.
Hat jemand eine Idee?

Re: WriteSerialPortString()

Verfasst: 30.04.2024 06:44
von DePe
Ich verstehe dein Problem nicht. Kannst du mehr Code zeigen, oder besser beschreiben was falsch ist.
Man muss auf die Terminierungszeichen '0A 0D' prüfen, um eine ganze Antwort zu erhalten.

Hier ist die z.B. Ausgabe von dem Kommando für die Identifikation '#00':

Code: Alles auswählen

Länge der Daten: 51 Bytes

00| 40 30 30 2D 30 30 2D 30 41 2D 30 32 2D 32 38 2D |@00-00-0A-02-28-|
10| 30 30 2D 30 30 2D 30 30 2D 30 30 2D 30 30 2D 30 |00-00-00-00-00-0|
20| 30 2D 30 30 2D 30 30 2D 30 30 2D 30 30 2D 30 30 |0-00-00-00-00-00|
30| 2D 0A 0D                                        |-..             |
Peter

Re: WriteSerialPortString()

Verfasst: 30.04.2024 09:21
von H.Brill
Was ist denn Pufferin für ein Datentyp ?
Ich denke mal, ein numerisches Array ?
Ich dachte, du bekommst schon Hex - Zahlen geliefert.
Dann wäre Chr() die richtige Umwandlung.

Perönlich würde ich dafür ein Stückchen Memory nehmen.

Code: Alles auswählen

*Mem = AllocateMemory(15)
PokeC(*Mem, $48)
PokeC(*Mem + 1, $65)
PokeC(*Mem + 2, $6C)
PokeC(*Mem + 3, $6C)
PokeC(*Mem + 4, $6F)
PokeC(*Mem + 5, $20)
PokeC(*Mem + 6, $57)
PokeC(*Mem + 7, $6F)
PokeC(*Mem + 8, $72)
PokeC(*Mem + 9, $6C)
PokeC(*Mem + 10, $64)
PokeC(*Mem + 11, $20)
PokeL(*Mem + 12, 4711)
Debug PeekS(*Mem, 11, #PB_Ascii)

For k = 0 To 10
  Debug(PeekS(*Mem + k, 1, #PB_Ascii))
Next

Debug PeekL(*Mem + 12)

Finde ich irgendwie flexibler, gerade, was das Auslesen betrifft.

Re: WriteSerialPortString()

Verfasst: 30.04.2024 11:42
von PIC18F2550
Ich fasse mal kurz zusammen:
Das Senden über WriteSerialPortString() hab ich hinbekommen.
Klappt super mit 0A oder 0D als Abschluss. :)

Das neue Problem ist ReadSerialPortData(0, @Pufferin,16))
Einige Commandos über WriteSerialPortString() liefern Daten zurück.
es sollen nach der Doku 16Byte sein.

Ich sehe gerade das du den Speicher mit "AllocateMemory()" reservierst.
Ich habe "Dim Pufferin$(16)" genommen.
Ist das entscheident?

Danke DePe für die darstellung des Rückgabestrings.
Hier zeigen sich unterschiede zum Handbuch wo von 16 Byts gesprochen wird in Wirklichkeit sind das aber 51 Byts.
Das muss ich erst einmal umsetzen und Testen.

Danke

Re: WriteSerialPortString()

Verfasst: 30.04.2024 12:49
von NicTheQuick
Ein "Dim Pufferin$(16)" erzeugt dir einen Puffer mit 16 Strings. Das ist ein großer Unterschied zu 16 Bytes.
Also entweder du nutzt "Dim Pufferin.a(16)" um 16 Bytes zu allokieren und dann als Integerwerte im Bereich 0-255 auslesen zu können. Oder du nimmst eben "AllocateMemory(16)" und weist den Pointer einem passenden Datentyp zu.

Re: WriteSerialPortString()

Verfasst: 30.04.2024 12:49
von H.Brill
Ist das entscheident?
Entscheidend nicht unbedingt. Kommt darauf an, was deine Hardware so alles ausgibt.
Bloß in so einem MemoryPuffer kann man alle Zeichen speichern. So z.b. auch die
ersten 32 NICHT druckbaren Zeichen der ASCII - Tabelle, halt alle 256 Zeichen.
Auch ganze Zahlen (Typ i oder Long), die dann 4 Bytes belegen, bekommt man dann
mit PeekL() gut heraus. Und PeekL weiß, daß es 4 Bytes hintereinander abgreifen muß.

Re: WriteSerialPortString()

Verfasst: 30.04.2024 13:22
von NicTheQuick
Doch, es ist ein entscheidender Unterschied, ob man 16 einzelne Strings in einem Array hat und an der Speicherstelle des Arrays nur Pointer zu nicht existierenden Strings stehen oder ob man ein Array aus Bytes oder anderen Zahlentypen erstellt.

Re: WriteSerialPortString()

Verfasst: 30.04.2024 13:24
von PIC18F2550
Danke für eure Tips die waren für mich hilfreich.

So jetzt kann ich auch daten Empfangen :)

Code: Alles auswählen

CHECK -> USBALL: 4
USBALL -> Byte: 51
40-30-30-2D-30-30-2D-30-41-2D-30-32-2D-31-43-2D-30-30-2D-30-30-2D-30-30-2D-30-30-2D-30-30-2D-30-30-2D-30-30-2D-30-30-2D-30-30-2D-30-30-2D-30-30-2D-A-D-0-0-0-0-0-0-0-0-0-0-0-0-0-
 @  0  0  -  0  0  -  0  A  -  0  2  -  1  C  -  0  0  -  0  0  -  0  0  -  0  0  -  0  0  -  0  0  -  0  0  -  0  0  -  0  0  -  0  0  -  0  0  -
Danke.

Re: WriteSerialPortString()

Verfasst: 30.04.2024 13:26
von PIC18F2550
Hier mal den ganzen Block wenn noch jemand danach sucht.

Code: Alles auswählen

*Pufferin=AllocateMemory(64)
OpenConsole("USBALL 10 Test")
CompilerIf #PB_Compiler_OS = #PB_OS_Windows
  PrintN("OS Windows")
  P$ = "COM"
CompilerElse
  PrintN("Information", "OS Linux")
  P$ = "/dev/ttyS"
CompilerEndIf

For l=0 To 10
  Port$=P$+Str(l)
  If OpenSerialPort(0, Port$, 0, #PB_SerialPort_NoParity, 0, 0, #PB_SerialPort_NoHandshake, 0, 0) 
    PrintN("SerialPort "+Port$+" opened With success")
    PrintN("CHECK -> USBALL: "+Str(WriteSerialPortString(0, "#00"+Chr($a), #PB_Ascii)))
    Print ("USBALL -> Byte: "+Str(ReadSerialPortData(0, *Pufferin,51)))
    PrintN ("")
    For g=0 To 63
      Print (Hex(PeekB(*Pufferin+g))+"-")
    Next g
    PrintN("")
    For g=0 To 63
      Print (" "+Chr(PeekB(*Pufferin+g))+" ")
    Next g
    PrintN("")
    PrintN("START I/O -> Byte: "+Str(WriteSerialPortString(0, "#50-01-00-00-00-00"+Chr($a), #PB_Ascii)))
    For z=0 To 5
      PrintN("OUT I/O 55-55-55 -> Byte: "+Str(WriteSerialPortString(0, "#50-02-55-55-55"+Chr($a), #PB_Ascii)))
      Delay(100)
      PrintN("OUT I/O AA-AA-AA -> Byte: "+Str(WriteSerialPortString(0, "#50-02-AA-AA-AA"+Chr($a), #PB_Ascii)))
      Delay(100)
    Next z
    PrintN("STOP I/O -> Byte: "+Str(WriteSerialPortString(0, "#50-00"+Chr($a), #PB_Ascii)))
  Else
    PrintN("Error:  Can't open the serial port: "+Port$)
  EndIf
Next l
  PrintN("Drücken Sie eine Taste zum Beenden.") : Input() : CloseConsole()
End

Re: WriteSerialPortString()

Verfasst: 30.04.2024 16:23
von mk-soft
Wie es aussieht ist es eine ASCII Kommunikation mit Ende Zeichen #LFCR$

Da braucht man nicht Peek oder Poke. PokeC ist eh falsch weil diese Poke Character ist und PB intern Unicode. Somit werden immer bei PokeC zwei byte geschrieben.
Chr($0A) + Chr($0D) braucht man nicht. Dafür gibt es fertige Konstanten bei PB.
Linefeed #LF$, Return #CR$ oder zusammen #LFCR$

Die Kommunikation sollte in einem Thread ablaufen, damit diese nicht durch GUI gestört wird.
Ausserdem sollte der Empfangsbuffer immer ausgelesen werden wenn Daten anstehen.
Ich hatte schon vor langer Zeit mal ein Beispiel zum Senden und Empfangen von Strings mit Erkennung von Ende-Zeichen geschrieben.
Im Beispiel werdende Ende-Zeichen automatisch beim Senden angehängt und beim Empfang entfernt.

Hier mal das Beispiel. In der Procedure InitComport() werden die Einstellungen vorgenommen. Port, Ende-Zeichen, etc

Code: Alles auswählen

;-TOP

; Comment : Comport Manager Over Thread and Callback
; Author  : mk-soft
; Version : v0.07.1
; Created : 26.01.2018
; Updated : 03.09.2022

; *****************************************************************************

CompilerIf #PB_Compiler_Thread = 0
  CompilerError "Use Option Threadsafe!"
CompilerEndIf

Prototype ProtoReceiveCB(Text.s)
Prototype ProtoStatusCB(Status, *ComData)

Enumeration
  #ComThread_Stopped
  #ComThread_Startup
  #ComThread_Running
EndEnumeration

Enumeration
  #ComStatus_Nothing
  #ComStatus_OpenPort
  #ComStatus_ClosePort
  #ComStatus_ErrorOpenPort
  #ComStatus_ErrorSend
  #ComStatus_ErrorReceive
  #ComStatus_ErrorDataSize
EndEnumeration

Structure udtComData
  ; Header
  ThreadID.i
  Exit.i
  Status.i
  ; Port Data
  ComID.i
  Port.s
  Baud.i
  Parity.i
  DataBit.i
  StopBit.i
  Handshake.i
  BufferSize.i
  ; End Of Text
  EndOfText.s
  ; Send Data
  SendSignal.i
  SendCount.i
  SendText.s
  SendError.i
  ; Receive data
  ReceiveCount.i
  ReceiveText.s
  ReceiveError.i
  ; Callback
  *StatusCB.ProtoStatusCB
  *ReceiveCB.ProtoReceiveCB
EndStructure

Procedure thComport(*ComData.udtComData)
  
  Protected *Send, *Receive, SendText.s, SendLen, ReceiveText.s, ReceiveLen, Pos
  
  With *ComData
    ; Startup
    \Status = #ComThread_Startup
    \SendCount = 0
    \ReceiveCount = 0
    \ComID = OpenSerialPort(#PB_Any, \Port, \Baud, \Parity, \DataBit, \StopBit, \Handshake, \BufferSize, \BufferSize)
    If \ComID
      \Status = #ComThread_Running
    Else
      If \StatusCB
        \StatusCB(#ComStatus_ErrorOpenPort, *ComData)
      EndIf
      \Status = #ComThread_Stopped
      ProcedureReturn 0
    EndIf
    If \StatusCB
      \StatusCB(#ComStatus_OpenPort, *ComData)
    EndIf
    *Send = AllocateMemory(\BufferSize)
    *Receive = AllocateMemory(\BufferSize)
    ; Loop
    Repeat
      If \SendSignal
        SendText = \SendText + \EndOfText
        SendLen = StringByteLength(SendText, #PB_Ascii)
        If SendLen <= \BufferSize
          PokeS(*Send, SendText, SendLen, #PB_Ascii)
          If WriteSerialPortData(\ComID, *Send, SendLen) = 0
            \SendError = SerialPortError(\ComID)
            If \StatusCB
              \StatusCB(#ComStatus_ErrorSend, *ComData)
            EndIf
          Else
            \SendError = 0
            \SendCount + 1
          EndIf
        Else
          If \StatusCB
            \StatusCB(#ComStatus_ErrorDataSize, *ComData)
          EndIf
        EndIf
        \SendSignal = #False
      EndIf
      ReceiveLen = AvailableSerialPortInput(\ComID)
      If ReceiveLen
        ReceiveLen = ReadSerialPortData(\ComID, *Receive, ReceiveLen)
        If ReceiveLen = 0
          \ReceiveError = SerialPortError(\ComID)
          If \StatusCB
            \StatusCB(#ComStatus_ErrorReceive, *ComData)
          EndIf
        Else
          \ReceiveError = 0
        EndIf
        ReceiveText + PeekS(*Receive, ReceiveLen, #PB_Ascii)
        Repeat
          pos = FindString(ReceiveText, \EndOfText, 1, #PB_String_NoCase)
          If pos
            \ReceiveText = Left(ReceiveText, pos - 1)
            ReceiveText = Mid(ReceiveText, pos + Len(\EndOfText))
            \ReceiveCount + 1
            If \ReceiveCB
              \ReceiveCB(\ReceiveText)
            EndIf
          EndIf
        Until pos = 0
      EndIf
      Delay(10)
    Until \Exit
    ; Shutdown
    CloseSerialPort(\ComID)
    If \StatusCB
      \StatusCB(#ComStatus_ClosePort, *ComData)
    EndIf
    FreeMemory(*Send)
    FreeMemory(*Receive)
    \Status = #ComThread_Stopped
    \ComID = 0
    \Exit = 0
    ProcedureReturn 1
  EndWith
  
EndProcedure

; ----

Procedure.s SerialPortErrorText(ErrorCode)
  Protected r1.s
  
  Select ErrorCode
    Case #PB_SerialPort_RxOver      : r1 = "An input buffer overflow has occurred."
    Case #PB_SerialPort_OverRun     : r1 = "A character-buffer overrun has occurred."
    Case #PB_SerialPort_RxParity    : r1 = "The hardware detected a parity error."
    Case #PB_SerialPort_Frame       : r1 = "The hardware detected a framing error."
    Case #PB_SerialPort_Break       : r1 = "The hardware detected a break condition."
    Case #PB_SerialPort_TxFull      : r1 = "The application tried to transmit a character but the output buffer was full."
    Case #PB_SerialPort_IOE         : r1 = "An I/O error occurred during communications with the device."
    Case #PB_SerialPort_WaitingCTS  : r1 = "Specifies whether transmission is waiting for the CTS (clear-To-send) signal to be sent."
    Case #PB_SerialPort_WaitingDSR  : r1 = "Specifies whether transmission is waiting for the DSR (Data-set-ready) signal to be sent."
    Case #PB_SerialPort_WaitingRLSD : r1 = "Specifies whether transmission is waiting for the RLSD (receive-line-signal-detect) signal to be sent."
    Case #PB_SerialPort_XoffReceived: r1 = "Specifies whether transmission is waiting because the XOFF character was received."
    Case #PB_SerialPort_XoffSent    : r1 = "Specifies whether transmission is waiting because the XOFF character was transmitted."
    Case #PB_SerialPort_EOFSent     : r1 = "Specifies whether the end-of-file (EOF) character has been received."
    Default                         : r1 = "ErrorCode " + Hex(ErrorCode)
  EndSelect
  ProcedureReturn r1
EndProcedure

; ----

; Threaded String Helper

Procedure AllocateString(String.s)
  Protected *mem
  *mem = AllocateMemory(StringByteLength(String) + SizeOf(Character))
  If *mem
    PokeS(*mem, String)
  EndIf
  ProcedureReturn *mem
EndProcedure

Procedure.s FreeString(*Mem)
  Protected result.s
  If *Mem
    result = PeekS(*Mem)
    FreeMemory(*Mem)
  EndIf
  ProcedureReturn result
EndProcedure

; *****************************************************************************

;- Example

CompilerIf #PB_Compiler_IsMainFile
  
  Global ComData.udtComData
  
  Enumeration EventCustomValue #PB_Event_FirstCustomValue
    #My_Event_NewData
    #My_Event_NewState
  EndEnumeration
  
  ; ---------------------------------------------------------------------------
  
  Procedure ReceiveCB(Text.s)
    PostEvent(#My_Event_NewData, 0, 0, 0, AllocateString(Text))
  EndProcedure
  
  Procedure MyEventNewDataCB()
    Protected Text.s
    Text = FreeString(EventData())
    AddGadgetItem(0, -1, Text)
    SetGadgetState(0, CountGadgetItems(0) - 1)
    SetGadgetState(0, -1)
  EndProcedure
  
  BindEvent(#My_Event_NewData, @MyEventNewDataCB())
  
  ; ---------------------------------------------------------------------------
  
  Procedure StatusCB(Status, *ComData.udtComData)
    PostEvent(#My_Event_NewState, 0, 0, Status, *ComData)
  EndProcedure
  
  Procedure MyEventNewStateCB()
    Protected Text.s, Status, *ComData.udtComData
    Status = EventType()
    *ComData = EventData()
    Select Status
      Case #ComStatus_OpenPort
        Text = "ComStatus: Open Port " + *ComData\Port
      Case #ComStatus_ClosePort
        Text = "ComStatus: Close Port " + *ComData\Port
      Case #ComStatus_ErrorOpenPort
        Text = "ComError: Open Port " + *ComData\Port
      Case #ComStatus_ErrorSend
        Text = "ComError Send: Port " + *ComData\Port + " - " + SerialPortErrorText(*ComData\SendError)
      Case #ComStatus_ErrorReceive
        Text = "ComError Receive: Port " + *ComData\Port + " - " + SerialPortErrorText(*ComData\ReceiveError)
      Case #ComStatus_ErrorDataSize
        Text = "ComError Send: Port " + *ComData\Port + " - Send data size to big."
    EndSelect
    If Bool(Text)
      StatusBarText(0, 0, Text)
    EndIf
  EndProcedure
  
  BindEvent(#My_Event_NewState, @MyEventNewStateCB())
  
  ; ---------------------------------------------------------------------------
  
  Procedure InitComport()
    With ComData
      If \Status
        ProcedureReturn 2 ; Always running
      EndIf
      \Port = "COM4"
      \Baud = 115200
      \Parity = #PB_SerialPort_NoParity
      \DataBit = 8
      \StopBit = 1
      \Handshake = #PB_SerialPort_NoHandshake
      \BufferSize = 2048
      \EndOfText = #LF$ ; #LFCR$
      \StatusCB = @StatusCB()
      \ReceiveCB = @ReceiveCB()
      \ThreadID = CreateThread(@thComport(), ComData)
      If Not \ThreadID
        ProcedureReturn 0 ; Error create thread
      Else
        ProcedureReturn 1 ; ok
      EndIf
    EndWith
  EndProcedure
  
  Procedure Main()
    Protected Event, Text.s, i
    If OpenWindow(0, #PB_Ignore, #PB_Ignore, 800, 600, "Comport", #PB_Window_SystemMenu)
      CreateStatusBar(0, WindowID(0))
      AddStatusBarField(#PB_Ignore)
      ListViewGadget(0, 0, 0, 800, 540)
      StringGadget(1, 5, 545, 590, 25, "")
      ButtonGadget(2, 605, 545, 90, 25, "Send")
      ButtonGadget(3, 695, 545, 90, 25, "On/Off")
      AddKeyboardShortcut(0, #PB_Shortcut_Return, 1000)
      
      CreatePopupMenu(1)
      MenuItem(101, "Copy ListView")
      
      Repeat
        Event = WaitWindowEvent()
        Select Event
          Case #PB_Event_CloseWindow
            If ComData\Status
              MessageRequester("Info", "Comport Is Open!", #PB_MessageRequester_Warning)
            Else
              Break
            EndIf
            
          Case #PB_Event_Gadget
            Select EventGadget()
              Case 0
                If EventType() = #PB_EventType_RightClick
                  DisplayPopupMenu(1, WindowID(0))
                EndIf
                
              Case 2 ; send button
                If ComData\Status = #ComThread_Running And ComData\SendSignal = #False
                  ComData\SendText = GetGadgetText(1)
                  ComData\SendSignal = #True
                EndIf
              Case 3 ; on/off button
                If ComData\Status
                  ComData\Exit = 1
                Else
                  If Not InitComport()
                    StatusBarText(0, 0, "Comport " + ComData\Port + ": Error Create Thread")
                  EndIf
                EndIf
            EndSelect
            
          Case #PB_Event_Menu
            Select EventMenu()
              Case 101 ; popup menu
                Text = ""
                For i = 0 To CountGadgetItems(0) - 1
                  text + GetGadgetItemText(0, i) + #CRLF$
                Next
                SetClipboardText(Text)
                
            EndSelect
        EndSelect
      ForEver
    EndIf
  EndProcedure : Main()
  
CompilerEndIf