DTR and RTS control in QBASIC 
Author Message
 DTR and RTS control in QBASIC

KI>I haven't been progarmming in BASIC for a while so this may have been
KI>discussed many times and I have missed the discussions.


   Not at all. Only a few brave souls dare to tread on this subject.
   The rest stand back and look on in awe! <g>
     I don't know much but what follows below is where my current
   understanding stands.

KI>I need to do some simple control of some devices and need 12 volt
KI>signals to do the communication.  DTR and RTS from a serial port seem
KI>to be obvious choices but I am having trouble controling them from
KI>QBASIC.  I thought it would be as easy as poking ones to bits 0 and 1
KI>of h2FC or h3FC but that doesn't work.  I can easily PEEK and POKE those
KI>addresses but I am not getting the modem control registers.  Since all
KI>of my other software says that the com port base addresses are h2F8 and
KI>h3F8, I must conclude that QBASIC is not talking to the correct physical
KI>address.  Is there an easy way to get QBASIC to the right place?

KI>  I can use OPEN "com... but that doesn't give me independent control
KI>of DTR and RTS.

   You'll want to use QB's INP and OUT commands for accessing the UART.
   To access the UART registers you first get the baseport address of
   the com port and then add the UART register number (zero-based)
   to the baseport address to access a specific UART register.
    For example, if you wanted to access the UART's Line Control register
   you would add 3 to the baseport address of the serial port since the
   LCR is the 3rd register in the UART.

   See the SetNewBPS sub below which shows how to access the UART's
   LCR (Line Control Register). All it's doing is taking the baseport
   address of the serial port and adding 3 to that to access the LCR
   which is UART register 3.
    The following line of code allows access to UART registers zero
   and one.

   LCR% = INP(BaseAddr% + 3)         ' Get & Store Line Control Register
   OUT BaseAddr% + 3, LCR% OR &H80   ' Set DLAB (Divisor Latch Access Bit)

   When our routine is done (whatever it may be), the Line Control
   Register is returned to its original state with the following line
   of code:

   OUT BaseAddr% + 3, LCR%           ' Restore LCR

   Since we saved a copy of the LCR before we did anything with or to it,
   we can restore it to its state before we accessed it.

   To access registers zero and one, bit 7 of the LCR must be set first.
   That is what the   OUT BaseAddr% + 3, LCR% OR &H80    code does.
   The &H80 is hex for 128 which is the value of bit 7 when it is set.
   ORing it with &H80 assures that it will be set.

   Bit 7 of register 3 (LCR) is called the Divisor Latch Access Bit
   (DLAB) cause it controls access to registers zero and one of the UART.
   IOWs it must be set before we can access registers zero and one.

   Here's some QB code that may help shine some light on this subject
   for you. If you are serious about this you might consider buying ($$$)
   a copy of Frank Van Gilluwe's book "The Undocumented PC". He has
   very good coverage of serial and parallel ports and more. The example
   code is mostly assembler with some C and no BASIC, but it's a good
   book to have for this subject matter.

' ----------- CUT HERE ---------------- CUT HERE -------------------------
'The following routine will get the correct base port address for
'Com ports 1,2,3 or 4 from BIOS Data Area where BIOS stores them on
' bootup.
'If you use this routine to get the base port address do it BEFORE
'opening the Com port with the OPEN COM statement as BASIC will erase
'the memory cells that contain the base port address for any Com port
'it opens.
a% = ((Comport% - 1) MOD 4) * 2 ' ComPort% can be 1 thru 4
DEF SEG = &H40                  ' Switch to BIOS DATA AREA segment
   BasePort% = (PEEK(a%) + (PEEK(a% + 1) * 256)) ' Read the base address
DEF SEG  ' Switch back to QB's default DGROUP data segment

REM Returns Carrier true (-1) if bit 7 of of the UART's modem
REM status register is set or false (0) is bet 7 is not set.
REM Uses: BasePort FUNCTION to get com port's I/O memory address
REM Example use:
REM    PRINT "* WARNING * Carrier lost!"
REM    Do whatever to allow your program to handle a dropped carrier
MSR% = INP(BaseAddr% + 6)     ' Get MSR (Modem Status Register)
IF MSR% AND &H80 THEN         ' Bit 7 set?
   Carrier% = -1              ' Yes so we have a carrier
   Carrier% = 0               ' No we don't have a remote carrier
OUT BaseAddr% + 6, MSR%       ' Restore MSR

REM This routine bumps up the BPS (Bits Per Second) rate to the value
REM in the BPS& long integer variable that is passed to this routine.
IF BPS& >= 1200 THEN                 ' BPS of at least 1200 BPS
   BaudDiv% = 115200 \ BPS&          ' Calculate the baud rate divisor
   LCR% = INP(BaseAddr% + 3)         ' Get & Store Line Control Register
   OUT BaseAddr% + 3, LCR% OR &H80   ' Set DLAB (Divisor Latch Access Bit)
   OUT BaseAddr%, BaudDiv% AND &HFF  ' Set Low byte of new baud rate divsr
   OUT BaseAddr% + 1, BaudDiv% \ 256 ' Set High byte of new baud rate divsr
   OUT BaseAddr% + 3, LCR%           ' Restore LCR
' ----------- CUT HERE ---------------- CUT HERE -------------------------
Hope that helps. Good luck!

-Robert Fortune

 * OLX 2.1 TD * "Kiss the crack below my back."

Tue, 28 Aug 2001 03:00:00 GMT  
 [ 4 post ] 

 Relevant Pages 

1. Controlling RTS and DTR from basic (com port)

2. DTR, RTS in QB 4.5

3. How to change RTS or DTR ?

4. rts enable nd dtr enable with mscomm

5. DTR control with MSCOMM

6. Controlling CTS and RTS from QB

7. Serial Comm Break and RTS control

8. Controlling RTS

9. using Serial port with RTS/CTS flow control

10. MSCOMM, Direct control of RTS

11. MSComm - Control of RTS

12. Control RTS to trigger Plug/Play


Powered by phpBB® Forum Software