Announcement

Collapse
No announcement yet.

Serial Port Control Lines

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • Roger Garstang
    replied
    Yeah, from the documentation and after going through 50+ pages of Google results the only thing that makes sense is a comment in one of the results about Parity being the type of Parity to send and fParity being if you use it or not on receive. It could be unsupported on the 3 ports/devices I tried it on. Everything seems to work fine though. A 0-1% CPU usage on wait is nice!

    Leave a comment:


  • Tom Hanlin
    replied
    It looks as though fParity is intended to specify error trapping for parity errors. Whether it does anything at all is at the mercy of the comm driver.

    Leave a comment:


  • Roger Garstang
    replied
    I've got this working pretty slick and fast. Only weird thing I've noticed now is the fParity value doesn't appear to get set with SetCommState. After setting it I can perform a GetCommState and it shows 0. The value itself is a little odd since it is just T/F and there is a Parity value already that has all the types of Parity and None, so fParity isn't really needed.

    PB's built in COM doesn't appear to use or be able to set it either since I can set parity using it, disconnect, then connect with the API seeing all values set but fParity. Hyper Terminal doesn't have any luck either...so, how was this flag intended to be used?

    Leave a comment:


  • Roger Garstang
    replied
    Originally posted by Cliff Nichols View Post
    Roger,
    By the way...what is it that you are trying to communicate with??? (Simplifies things a lot) :coffee4:
    In the end it is going to be a wedge type application to send handheld scanner data to the keyboard. I made it Overlapped and it didn't seem to do much other than not hanging now and still no way of closing the port. Making it overlapped seemed to almost make WaitCommEvent redundant too. I think it would be easier just to do the Readfile Call and a Wait function. Using WaitCommEvent seems to imply I can get my event set by other ways like Breaks and Errors, but I'd think Readfile would set it for those too.

    A little bit more work to get the data, but I think it will be quicker and less CPU intense to Wait rather than poll. I may combine it with some of the Window code from my other Sendy app I posted here a while back to activate specific windows to give keys to, etc. I'm still debating if I want to monitor more than one COM port too (Other Wedge applications do, but I think the keys have too much of a chance of getting out of sync).

    Leave a comment:


  • Michael Mattias
    replied
    Handle thread blocking calls with abort?

    Put your 'blocking calls' in their own threads of execution and adapt this code:

    Terminate Worker Threads Using Windows Events (and Using Thread Local Storage) Demo Dec 23 2005

    Leave a comment:


  • Cliff Nichols
    replied
    Roger,
    The PB wrapper functions are GREAT!!! (In most cases), in the few cases that PB did not make easier (For users to learn from, and lets face it "Windows API is quite intimidating" at first look)

    One thing you will find (if working with multiple serial port devices) is that they each take their own spin on different settings. So be warned that if things work great at first, but years later does not work, then the most likely cause is another device used a setting that you did not think of (or change) when using your own code.

    By the way...what is it that you are trying to communicate with??? (Simplifies things a lot) :coffee4:

    Leave a comment:


  • Roger Garstang
    replied
    Originally posted by Paul Dixon View Post
    Roger,
    ...

    Isn't that what the lpOverlapped parameter in WaitCommEvent is for?

    Paul.
    Yes, but how do you make an overlapped Com Port using internal PB commands? PB's COM and an non-Overlapped CreateFile API both hang when trying to close the port. I even tried things like Setting Break and having WaitCommEvent watch for it too, but it still hung.

    I created the API version fine now. I have yet to create the needed event and overlapped stuff, but it is fairly quick. Main difference I notice is the API is picky about certain combinations of Stop Bits/Bits Per Byte/Parity and doesn't allow setting them and the PB docs for Com Set don't mention that...haven't tried them, but I'm curious if the calls fail there too or if it corrects them to be valid and re-submits them.

    Leave a comment:


  • Cliff Nichols
    replied
    For quite some time now I have been working on and off on my SerialPort.inc file that would make handling the serial port much easier.

    But from my archives (Sorry I do not know who to give credit to, as I found this years ago) is serial port routines to directly control lines (may need some modifications, since I think I got it back in PB6???)

    Anyways, this should help :coffee4:
    Code:
    'enhanced serial port functions including handshake
    'signal manipulation/checking etc.
    '
    'Requires WINAPI32.INC
    '
    'Sets default parameters for COM port
    SUB INITCOMM(HCOM AS LONG,COMMSTR AS STRING)
        COMM OPEN COMMSTR AS HCOM
        COMM RESET HCOM,FLOW
        COMM SET HCOM, BAUD = 9600 ' 9600 baud
        COMM SET HCOM, BYTE = 8 ' 8 bits
        COMM SET HCOM, PARITY = 0 ' No parity
        COMM SET HCOM, STOP = 0 ' 1 stop bit
        COMM SET HCOM, TXBUFFER = 1024 ' 1k transmit buffer
        COMM SET HCOM, RXBUFFER = 32768 '32k receive buffer
    END SUB
    'Write single binary byte to COM port
    SUB SERWRTBIN(HCOM AS LONG,DAT AS BYTE)
        COMM SEND HCOM,CHR$(DAT)
    END SUB
    'Get single binary byte from COM port
    'TOSEC specifies timeout in seconds,error status is returned in SERERR
    'Timeout must guard against midnight rollover for timer
    FUNCTION SERRDBIN(HCOM AS LONG,TOSEC AS LONG,SERERR AS LONG) AS BYTE
        DIM LL1 AS LONG,LL2 AS LONG,LL3 AS LONG,SS AS STRING
        LL1=TIMER
        LL2=(LL1 + TOSEC)-86399
        IF LL2>0 THEN
            DO
                LL3=TIMER
            LOOP UNTIL LL3<LL1
            LL1=LL3
            TOSEC=LL2
        END IF
        DO
            LL2=TIMER
            LL3=COMM(HCOM,RXQUE)
        LOOP UNTIL LL2>(LL1+TOSEC) OR LL3>0
        IF LL2>(LL1+TOSEC) THEN
            SERERR=255
            FUNCTION=0
            EXIT FUNCTION
        END IF
        COMM RECV HCOM, 1,SS
        FUNCTION=ASC(SS)
    END FUNCTION
    'Write string to COM port
    SUB SERWRTSTR(HCOM AS LONG,DAT AS STRING)
        COMM SEND HCOM,DAT
    END SUB
    'Get received string from COM port
    FUNCTION SERGETSTR(HCOM AS LONG) AS STRING
        DIM LL AS LONG,SS AS STRING
        LL=COMM(HCOM,RXQUE)
        COMM RECV HCOM,LL,SS
        FUNCTION=SS
    END FUNCTION
    'Get string terminated by linefeed-TOSEC specifies timeout,error status returned in SERERR
    'Linefeed is last byte in string
    FUNCTION SERGETLINESTR(HCOM AS LONG,TOSEC AS LONG,SERERR AS LONG) AS STRING
        DIM SS AS STRING,BB AS BYTE,LL AS LONG
        LL=TOSEC
        SERERR=0
        SS=""
        DO
            BB=SERRDBIN(HCOM,LL,SERERR)
            SS=SS + CHR$(BB)
        LOOP UNTIL BB=10 OR SERERR>0
        FUNCTION=SS
    END FUNCTION
    'Gets single byte string from COM port-TOSEC specifies timeout
    'Error status is returned in SERERR
    FUNCTION SERRDSTR(HCOM AS LONG,TOSEC AS LONG,SERERR AS LONG) AS STRING
        DIM BB AS BYTE,SS AS STRING
        BB= SERRDBIN(HCOM,TOSEC,SERERR)
        FUNCTION=CHR$(BB)
    END FUNCTION
    'Clear receive buffer
    SUB RXCLEAR(HCOM AS LONG)
        DIM SS AS STRING
        SS=SERGETSTR(HCOM)
    END SUB
    'SETS RTS
    SUB SETRTS(HCOM AS LONG)
        DIM APIHCOM AS LONG
        DIM LL AS LONG
        APIHCOM=FILEATTR(HCOM,2)
        LL&=ESCAPECOMMFUNCTION(APIHCOM,%SETRTS)
    END SUB
    'CLEARS RTS
    SUB CLRRTS(HCOM AS LONG)
        DIM APIHCOM AS LONG
        DIM LL AS LONG
        APIHCOM&=FILEATTR(HCOM,2)
        LL&=ESCAPECOMMFUNCTION(APIHCOM&,%CLRRTS)
    END SUB
    'SETS DTR
    SUB SETDTR(HCOM AS LONG)
        DIM APIHCOM AS LONG
        DIM LL AS LONG
        APIHCOM&=FILEATTR(HCOM,2)
        LL&=ESCAPECOMMFUNCTION(APIHCOM&,%SETDTR)
    END SUB
    'CLEAR DTR
    SUB CLRDTR(HCOM AS LONG)
        DIM APIHCOM AS LONG
        DIM LL AS LONG
        APIHCOM&=FILEATTR(HCOM,2)
        LL&=ESCAPECOMMFUNCTION(APIHCOM&,%CLRDTR)
    END SUB
    'ASSERT BREAK
    SUB SETBREAK(HCOM AS LONG)
        DIM APIHCOM AS LONG
        DIM LL AS LONG
        APIHCOM&=FILEATTR(HCOM,2)
        LL&=ESCAPECOMMFUNCTION(APIHCOM&,%SETBREAK)
    END SUB
    'CLEAR BREAK
    SUB CLRBREAK(HCOM AS LONG)
        DIM APIHCOM AS LONG
        DIM LL AS LONG
        APIHCOM&=FILEATTR(HCOM,2)
        LL&=ESCAPECOMMFUNCTION(APIHCOM&,%CLRBREAK)
    END SUB
    'GET MODEM STATUS SIGNALS
    FUNCTION GETCOMSTS(HCOM AS LONG)AS LONG
        DIM APIHCOM AS LONG
        DIM LL AS LONG
        DIM STS AS LONG
        APIHCOM&=FILEATTR(HCOM,2)
        LL=GETCOMMMODEMSTATUS(APIHCOM&,STS )
        FUNCTION=STS
    END FUNCTION
    'CHECK CTS
    FUNCTION GETCTS(HCOM AS LONG) AS LONG
        FUNCTION=GETCOMSTS(HCOM) AND %MS_CTS_ON
    END FUNCTION
    'CHECK DSR
    FUNCTION GETDSR(HCOM AS LONG) AS LONG
        FUNCTION=GETCOMSTS(HCOM) AND %MS_DSR_ON
    END FUNCTION
    'CHECK CD
    FUNCTION GETCD(HCOM AS LONG) AS LONG
        FUNCTION=GETCOMSTS(HCOM) AND %MS_RLSD_ON
    END FUNCTION
    'CHECK RING
    FUNCTION GETRING(HCOM AS LONG) AS LONG
        FUNCTION=GETCOMSTS(HCOM) AND %MS_RING_ON
    END FUNCTION
    '------------------

    Leave a comment:


  • Paul Dixon
    replied
    Roger,
    but with issues in it blocking the thread
    If something is blocking your thread then a common solution is to create a new thread and run the blocking code in that. The new thread then blocks but the original thread continues.

    as well as the port from having anything done to it
    Isn't that what the lpOverlapped parameter in WaitCommEvent is for?

    Paul.

    Leave a comment:


  • Roger Garstang
    replied
    The only thread I could find about setting up all these values is using the old BIT commands...

    I have a need to use WaitCommEvent, but with issues in it blocking the thread as well as the port from having anything done to it so I can abort the wait I have to use example code from CodeProject and http://www.powerbasic.com/support/pb...=WaitCommEvent to create a WinAPI version. For anyone using this with current compilers a better/easier layout is (Hopefully this will make it to .06 builds):

    Code:
    Type DCBnew
      DCBlength As Dword
      BaudRate As Dword
      fBinary As Bit * 1 In Dword
      fParity As Bit * 1
      fOutxCtsFlow As Bit * 1
      fOutxDsrFlow As Bit * 1
      fDtrControl As Bit * 2
      fDsrSensitivity As Bit * 1
      fTXContinueOnXoff As Bit * 1
      fOutX As Bit * 1
      fInX As Bit * 1
      fErrorChar As Bit * 1
      fNull As Bit * 1
      fRtsControl As Bit * 2
      fAbortOnError As Bit * 1
      fDummy2 As Bit * 17
      wReserved As Word
      XonLim As Word
      XoffLim As Word
      ByteSize As Byte
      Parity As Byte
      StopBits As Byte
      XonChar As Byte
      XoffChar As Byte
      ErrorChar As Byte
      EofChar As Byte
      EvtChar As Byte
      wReserved2 As Integer
    End Type

    Leave a comment:


  • Lance Edmonds
    replied
    I don't know whether this will help you, but the following is some code I put together to open a serial port via the API. It was for PB/CC 1.0 (before the advent of the COMM statements in PB/C 2.0).
    Code:
    FUNCTION OpenPort&(szPort AS ASCIIZ)
        DIM hComm AS LONG, fSuccess AS LONG, CommMask AS LONG
        DIM cDCB AS DCB, ComProp AS COMMPROP, CTO AS COMMTIMEOUTS
        DIM szDCB AS ASCIIZ * 64
        DIM x%
    
        hComm = CreateFile( szPort, _
                              %GENERIC_READ OR %GENERIC_WRITE, _
                              BYVAL 0, _
                              BYVAL 0, _
                              BYVAL %OPEN_EXISTING, _
                              BYVAL 0, _
                              BYVAL 0)
        IF hComm = %INVALID_HANDLE_VALUE OR hComm = %ERROR_FILE_NOT_FOUND THEN
            PRINT "ComPort Open Error!"
            EXIT FUNCTION
        END IF
    
        fSuccess = GetCommState(hComm, cdcb)
        IF ISFALSE fSuccess THEN
            PRINT "ComPort GetState Error!"
            EXIT FUNCTION
        END IF
    
        szDCB = "19200,n,8,1,p"
        IF ISFALSE BuildCommDCB(szDCB, cdcb) THEN
            PRINT "BuildCommDCB failure"
            EXIT FUNCTION
        END IF
    
        cdcb.BaudRate = 19200
        cdcb.ByteSize = 8
        cdcb.Parity   = %NOPARITY
        cdcb.StopBits = %ONESTOPBIT
    
        BIT SET cdcb.fBits,2          ' CTS       (set to 1)
        BIT RESET cdcb.fBits,3        ' DSR       (set to 0)
    
    '$IF 0
        BIT SET cdcb.fBits,4          ' DTR 1/2    (= DTR_CONTROL_ENABLE) (set to 1)
        BIT RESET cdcb.fBits,5        ' DTR 2/2    (= DTR_CONTROL_ENABLE) (set to 0)
    
        BIT SET cdcb.fBits,6          ' DSRSensitivity
        BIT SET cdcb.fbits,7          ' ContinueOnXOFF
    
        BIT RESET cdcb.fBits,8        ' XON/XOFF output (Set to 0)       ' Halts Class 2 XON!!! Force to 0!
        BIT RESET cdcb.fBits,9        ' XON/XOFF input  (Set to 0)
    
        BIT SET cdcb.fBits,12       ' RTS 1/2    (= RTS_CONTROL_ENABLE)
        BIT SET cdcb.fBits,13       ' RTS 2/2    (= RTS_CONTROL_ENABLE)
    '$ENDIF
    
        fSuccess = SetCommState(hComm, cdcb)
        IF ISFALSE fSuccess THEN
            PRINT "ComPort SetState Error!"
            EXIT FUNCTION
        END IF
    
    $IF 0
    PRINT "DCB Bits..."
    FOR x% = 0 TO (LEN(cdcb.fbits) -1) * 8
        PRINT BIT(cdcb.fbits,x%);
    NEXT x%
    PRINT
        PRINT "Baud Rate         ", cdcb.BaudRate
        PRINT "ByteSize          ", cdcb.ByteSize
        PRINT "Parity            ", cdcb.Parity
        PRINT "Stop Bits         ", cdcb.StopBits
    
        PRINT "0  fBinary        ", BIT(cdcb.fbits,0)
        PRINT "1  fParity        ", BIT(cdcb.fbits,1)
        PRINT "2  fOutxCtsFlow   ", BIT(cdcb.fbits,2)
        PRINT "3  fOutxDsrFlow   ", BIT(cdcb.fbits,3)
        PRINT "45 fDtrControl    ", BIT(cdcb.fbits,4) BIT(cdcb.fbits,5)
        PRINT "6  fDsrSensitivity", BIT(cdcb.fbits,6)
        PRINT "7  fContinueOnXoff", BIT(cdcb.fbits,7)
        PRINT "8  fOutX          ", BIT(cdcb.fbits,8)
        PRINT "9  fInX           ", BIT(cdcb.fbits,9)
        PRINT "10 fErrorChar     ", BIT(cdcb.fbits,10)
        PRINT "11 fNull          ", BIT(cdcb.fbits,11)
        PRINT "12 fRtsControl    ", BIT(cdcb.fbits,12) BIT(cdcb.fbits,13)
        PRINT "14 fAbortOnError  ", BIT(cdcb.fbits,14)
    WAITKEY$
    $ENDIF
    
        fSuccess = GetCommProperties(hComm, ComProp)
        IF ISFALSE fSuccess THEN
            PRINT "ComPort GetCommProperties Error!"
            EXIT FUNCTION
        END IF
    
        IF (ComProp.dwProvCapabilities AND %PCF_RTSCTS) THEN _
            PRINT "RTS/CTS capable modem detected"
    
        SetupComm hComm, MAX%(%BufferSize,Comprop.dwCurrentRxQueue), MAX%(%BufferSize,Comprop.dwCurrentTxQueue)
        fSuccess = GetCommProperties(hComm, ComProp)
        PRINT "TX Que size =" Comprop.dwCurrentTxQueue
        PRINT "RX Que size =" Comprop.dwCurrentRxQueue
    
        IF ISFALSE (ComProp.dwMaxBaud AND %BAUD_19200) AND ComProp.dwMaxBaud <> %BAUD_USER THEN
            PRINT "Modem does not support 19200 Baud!"
            EXIT FUNCTION
        END IF
    
        IF ISFALSE (ComProp.dwProvSubType AND %PST_FAX) THEN
            PRINT "Modem does not support Fax mode!"
            EXIT FUNCTION
        END IF
    
        GetCommTimeouts hComm, CTO
        IF ISFALSE (ComProp.dwProvCapabilities AND %PCF_INTTIMEOUTS) THEN
            PRINT "Modem Timeouts NOT available"
        ELSE
            CTO.ReadIntervalTimeout = %MAXDWORD
            CTO.ReadTotalTimeoutMultiplier = 50
            CTO.ReadTotalTimeoutConstant = 50
            CTO.WriteTotalTimeoutMultiplier = 1
            CTO.WriteTotalTimeoutConstant = 20000
    
            SetCommTimeouts hComm, CTO
        END IF
    
        PurgeComm hComm, %PURGE_TXCLEAR OR %PURGE_RXCLEAR OR %PURGE_TXABORT OR %PURGE_RXABORT
    
    '    sleep 100
        FUNCTION = hComm
    END FUNCTION
    From there you use ReadFile() and WriteFile(), and finally CloseHandle().


    ------------------
    Lance
    PowerBASIC Support
    mailto:[email protected][email protected]</A>

    Leave a comment:


  • Michael Burns
    replied
    Did you ever find a solution?

    I'm running into a problem right now that
    seems to stem from PowerBASIC opening the
    serial port and THEN setting the control
    line behavior. I'm talking to an instrument
    that resets (and loses all of its data) whenever
    the DTR line goes high. The instrument makers
    programming environment clearly can open the
    serial port without having the DTR go high, but
    PowerBASIC DLL always opens with it high, and then
    lowers it when DTRLINE = %FALSE is set in a following
    COMM SET command. Anyone know how to get PB to
    set the control line behavior before the serial port
    is opened?



    ------------------
    Michael Burns

    Leave a comment:


  • Guest's Avatar
    Guest replied
    Thank you, Lance. You're just great!

    Loren

    Leave a comment:


  • Lance Edmonds
    replied
    (Also see the thread in the PB/DOS forum).

    In Windows, you'll need to use the Win32 API to manipulate a comm port. PowerBASIC and libraries such as WSC4PB wrap these API calls into a "programmer friendly" set of functions to make your life easier. While doing this with native PB code is admirable, it's a huge task! If you consider that it will take more than just a few hours to write your own functions (which it will definitely do), then a commercial library for less than US$100 is actually very economic. I do have some raw API code around here somewhere (written by a PB/DLL 5.0 user) that may help you get started.

    I dont mean to be too negative on this, but I've "been there, done that, brought the T-Shirt"...

    Lance
    PowerBASIC Support

    Leave a comment:


  • Guest's Avatar
    Guest started a topic Serial Port Control Lines

    Serial Port Control Lines

    I love PowerBASIC and the tech support team. VERY helpful! Now, I want to directly control CTS, RTS, DSR and DTR status lines in an embedded system. Can I do this directly in PB/DLL (and PowerBASIC for DOS) without using third-party software like MarshallSoft stuff? Thanks, everybody!
Working...
X