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!
Announcement
Collapse
No announcement yet.
Serial Port Control Lines
Collapse
X
-
(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
Lance
mailto:[email protected]
-
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 BurnsMichael Burns
Comment
-
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
------------------
Lance
PowerBASIC Support
mailto:[email protected][email protected]</A>Lance
mailto:[email protected]
Comment
-
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
sigpic
Mobile Solutions
Sys Analyst and Development
Comment
-
Roger,
but with issues in it blocking the thread
as well as the port from having anything done to it
Paul.
Comment
-
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
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 '------------------
Engineer's Motto: If it aint broke take it apart and fix it
"If at 1st you don't succeed... call it version 1.0"
"Half of Programming is coding"....."The other 90% is DEBUGGING"
"Document my code????" .... "WHYYY??? do you think they call it CODE? "
Comment
-
Originally posted by Paul Dixon View PostRoger,
...
Isn't that what the lpOverlapped parameter in WaitCommEvent is for?
Paul.
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.sigpic
Mobile Solutions
Sys Analyst and Development
Comment
-
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)Engineer's Motto: If it aint broke take it apart and fix it
"If at 1st you don't succeed... call it version 1.0"
"Half of Programming is coding"....."The other 90% is DEBUGGING"
"Document my code????" .... "WHYYY??? do you think they call it CODE? "
Comment
-
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 2005Michael Mattias
Tal Systems (retired)
Port Washington WI USA
[email protected]
http://www.talsystems.com
Comment
-
Originally posted by Cliff Nichols View PostRoger,
By the way...what is it that you are trying to communicate with??? (Simplifies things a lot)
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).sigpic
Mobile Solutions
Sys Analyst and Development
Comment
-
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?sigpic
Mobile Solutions
Sys Analyst and Development
Comment
-
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!sigpic
Mobile Solutions
Sys Analyst and Development
Comment
Comment