home *** CD-ROM | disk | FTP | other *** search
/ ProfitPress Mega CDROM2 …eeware (MSDOS)(1992)(Eng) / ProfitPress-MegaCDROM2.B6I / PROG / BASIC / QBSER20.ZIP / QBSERIAL.DOC < prev    next >
Encoding:
Text File  |  1990-10-31  |  25.8 KB  |  561 lines

  1.  
  2.  
  3.  
  4.                                   QBserial version 2.0
  5.  
  6.                   Serial I/O Routines for use with QuickBASIC & BC6/7
  7.  
  8.           This library will provide you with serial I/O communications
  9.           routines for use in QuickBASIC 4.x (with or without PDQ), and the
  10.           Microsoft Basic Compiler 7.x Professional Development System. No
  11.           longer are you forced to use the poor communications support
  12.           provided by QB.  This program will allow you to control 8250 type
  13.           communications ports at speeds of up to 115200 baud. Communication
  14.           ports 1 - 4, and non-standard addresses are supported. You will no
  15.           longer have problems with the DTR signal. DTR is left in the same
  16.           state it was in when before you called this driver, or it can be
  17.           controlled by your program. The serial driver includes XON/XOFF and
  18.           CTS handshaking. Serial input is interrupt driven, using any IRQ
  19.           you specify (1 - 7), with incoming XOFF flow control (if enabled)
  20.           to prevent overrunning the input buffer. These are the same serial
  21.           I/O routines used in Sparkware's Qmail door, and the User Database
  22.           System Doors "Query Door" and "Upload Door".
  23.  
  24.           The driver is written in Microsoft's QuickC version 2.51. This
  25.           driver is useable with QuickBASIC version 4.x, and Basic Compiler
  26.           6.x & 7.x PDS. (With or without PDQ). BC 1.x, QuickBASIC 2.x, and
  27.           3.x are not supported by this driver. The reason is that versions
  28.           of QuickBASIC prior to 4.0 do not support the extensive multi-
  29.           language interface that QB4.x has (via the DECLARE statement and
  30.           Microsoft language extensions). Throughout this manual QB will be
  31.           used to refer to both QuickBASIC and the Basic Compilers (6.x & 7.x
  32.           PDS).
  33.  
  34.           Before the driver can be used, the following DECLARE statements
  35.           must be added to the beginning of your QB program:
  36.  
  37.           DECLARE SUB OpenComm CDECL ALIAS "_open_comm" (BYVAL Port%, BYVAL_
  38.                                IRQ%, BYVAL Wlen%, BYVAL Parity%, BYVAL Baud&,
  39.                                BYVAL HS%) 
  40.           DECLARE SUB CloseComm CDECL ALIAS "_close_comm" () 
  41.           DECLARE FUNCTION WriteChar% CDECL (BYVAL Ascii%) 
  42.           DECLARE FUNCTION ReadChar% CDECL () 
  43.           DECLARE SUB Transmit CDECL ALIAS "_transmit_string" (addr$) 
  44.           DECLARE FUNCTION DataWaiting% CDECL ALIAS "_data_waiting" () 
  45.           DECLARE SUB ClearInputBuffer CDECL ALIAS "_clear_input_buffer" () 
  46.           DECLARE SUB CarrierDetect CDECL ALIAS "_carrier_detect_flag"_
  47.                                     (BYVAL OnOff%) 
  48.           DECLARE FUNCTION CarrierLost% CDECL ALIAS "_carrier_state" ()
  49.           DECLARE SUB DTRcontrol CDECL ALIAS "_dtr" (BYVAL OnOff%)
  50.           DECLARE FUNCTION DriverCopyright% CDECL ()
  51.  
  52.           These declarations specify all the entry points into the serial
  53.           driver, They are in the include file QBSERIAL.DEC. DO NOT change
  54.           them or the driver may not function.
  55.  
  56.  
  57.         QBSERIAL User Manual - V 2.0                               Page 1
  58.  
  59.  
  60.           Refer to the included sample programs SIMPLE.BAS & PCBDOOR.BAS,
  61.           they use most of the calls described below.
  62.  
  63.  
  64.  
  65.                                   Port Initialization
  66.  
  67.           OpenComm Port%, IRQ%, Wordlen%, Parity%, Baudrate&, HS%
  68.  
  69.           Port%     This is an integer value. If the specified port is 1 to
  70.                     4, the driver opens that port. If you specify the port as
  71.                     ZERO (0) the driver enters "LOCAL" mode. This allows you
  72.                     to call the driver with data, but the driver won't send
  73.                     anything. This is useful when working with "doors". if
  74.                     you specify the port as any other value, QBserial will
  75.                     use that as the base address for the port. This allows
  76.                     you to work with non-standard I/O addresses. Note however
  77.                     that if you open a non-standard port, you must specify an
  78.                     IRQ value of 1 to 7
  79.  
  80.           IRQ%      Specifies which interrupt to use with this port. If the
  81.                     value of IRQ% is ZERO (0), then the default IRQ values
  82.                     are used (COM1 & COM3 use IRQ4, COM2 & COM4 use IRQ3).
  83.                     This is what most applications will use. Specify an IRQ
  84.                     value of 1 through 7 when you want to use an IRQ value
  85.                     other than the default. Such as when you want to use IRQ7
  86.                     with COM3. NOTE: Be careful when choosing an IRQ value
  87.                     other than the default. Most machines use the other IRQ
  88.                     inputs for other machine functions such as the Hard drive
  89.                     and system clock. QBserial DOES NOT chain the interrupt,
  90.                     it takes it over entirely. If you choose an IRQ that is
  91.                     used for something already, your machine will most
  92.                     certainly operate improperly.
  93.  
  94.           Wordlen%  an integer specifying the word length of the serial data.
  95.                     It has a value of 7 or 8.
  96.  
  97.           Parity%   an integer, 0 = NONE, 1 = ODD, 2 = EVEN.
  98.  
  99.           BaudRate& is a LONG INTEGER representing the desired baud rate.
  100.                     Valid numbers are 0, 300, 1200, 2400, 4800, 9600, 19200,
  101.                     38400, 57600, and 115200. The value you send is NOT
  102.                     checked and I assume you could generate crazy baud rates
  103.                     if desired. 115200 is the absolute maximum rate that can
  104.                     be generated. If you specify a baud rate of ZERO then the
  105.                     serial port is used AS-IS. The rate, word length, &
  106.                     parity are NOT changed. This is useful for door operation
  107.                     since the port is already initialized at the proper
  108.                     settings when you get control.
  109.  
  110.           HS%       an integer specifying the type of handshake you wish to
  111.                     use between the CPU and Modem (or destination device).
  112.  
  113.         QBSERIAL User Manual - V 2.0                               Page 2
  114.  
  115.  
  116.                     Valid numbers are: 0 = NO handshake, 1 = XON/XOFF, 2 =
  117.                     CTS, 3 = XON/XOFF and CTS.
  118.  
  119.  
  120.  
  121.                                      Serial Output
  122.  
  123.           To send a string of data out the serial port, you use the
  124.           "Transmit" call as follows:
  125.  
  126.                Temp$ = "Transmit this..."
  127.                Transmit Temp$
  128.  
  129.                     or
  130.  
  131.                Transmit "Send this also...."
  132.  
  133.           If you want to transmit single characters, you can use the
  134.           "WriteChar" function. Transmit calls WriteChar to send the actual
  135.           characters to the port. If you wish to use WriteChar, it has the
  136.           following format:
  137.  
  138.                Status% = WriteChar(Char%)
  139.  
  140.           Char% is the integer value of the character you want to send, it is
  141.           not a string. Status% is an integer returned by WriteChar, it is
  142.           NON-ZERO if the character was actually sent to the port, and ZERO
  143.           if the character was not sent. WriteChar will loop indefinitely on
  144.           CTS hold, XOFF hold, or Transmit Buffer Busy. These loops will exit
  145.           if carrier is lost in FULL or PARTIAL modes and return a ZERO
  146.           status%. WriteChar gives you more low level control of the sending
  147.           of characters, but you must send each character separately and
  148.           monitor its status.
  149.  
  150.           The Transmit function monitors the status of its calls to WriteChar
  151.           and triggers QuickBASIC's User Event trap (UEVENT) if a carrier
  152.           loss occurs in FULL mode. The UEVENT trap (FULL mode) is used by
  153.           default. You can disable the use of this event trap in the event
  154.           you already use the UEVENT trap for something else (PARTIAL mode).
  155.           Therefore, by default, carrier loss detection in your program is
  156.           done with the ON UEVENT GOSUB/UEVENT ON statements. The example
  157.           programs show the use of this method. By default UEVENT is also
  158.           used for catching carrier loss on keyboard input. this is described
  159.           below.
  160.  
  161.  
  162.  
  163.                                       Serial Input
  164.  
  165.           Serial input is managed with three functions: DataWaiting,
  166.           ReadChar, & ClearInputBuffer. DataWaiting is used to test the input
  167.           buffer to see if any characters need to be read from it. ReadChar
  168.  
  169.         QBSERIAL User Manual - V 2.0                               Page 3
  170.  
  171.  
  172.           is then called to get the characters. ClearInputBuffer flushes the
  173.           input buffer of any existing characters. Both example programs
  174.           contain a subroutine called "KeyboardInput" that demonstrates the
  175.           use of these calls. It also properly handles input from the local
  176.           and remote keyboards, and can be the routine you use in your
  177.           programs if you wish. Basically the procedure for reading the
  178.           remote keyboard (serial input) is as follows:
  179.  
  180.                IF DataWaiting THEN
  181.                     C$ = CHR$(ReadChar)
  182.                END IF
  183.  
  184.           The DataWaiting function also monitors the state of the carrier
  185.           detect signal and triggers, in FULL mode, the user event trap
  186.           (UEVENT) if carrier is lost. As you can see a singular trap routine
  187.           catches carrier loss on output as well as input. You will notice
  188.           that the "KeyboardInput" subroutine loops using DataWaiting, and as
  189.           such, carrier is constantly checked while waiting for input. If the
  190.           ReadChar function is called when no data is available (as indicated
  191.           by DataWaiting) a NULL character is returned.
  192.  
  193.           If XOFF/XON or BOTH is enabled, then the serial buffer will be
  194.           protected from overfills. When the buffer reaches 75% of capacity,
  195.           an XOFF will be sent on the serial output. When the buffer empties
  196.           out to 25% of capacity, an XON will be sent. The capacity of the
  197.           input buffer is 1024 bytes.
  198.  
  199.  
  200.  
  201.                                  Carrier Detect Control
  202.  
  203.           There are three modes of carrier detection: Full, Partial, & None.
  204.           Each has it own distinct use for a particular purpose. The driver
  205.           defaults to FULL carrier detection unless you change it. The
  206.           following call is used to change control modes:
  207.  
  208.                CarrierDetect 0 [or] 1 [or] 2
  209.  
  210.           Specifying a TWO (2) sets carrier detection to FULL. This is the
  211.           default mode. When a loss of carrier occurs while transmitting,
  212.           polling for input data, or sitting in a wait loop (XOFF/XON or
  213.           CTS), the driver will return to the calling program and trip the
  214.           UEVENT flag. Tripping the UEVENT flag causes Basic to go to the
  215.           User Event trap routine (providing ON UEVENT GOSUB/UEVENT ON has
  216.           been set up in the user program). You should use this mode only if
  217.           you want to use the UEVENT trap for carrier loss detection. You
  218.           cannot transmit data (with the Transmit function) in this mode if
  219.           there is no carrier. You can send characters in this mode with the
  220.           WriteChar function.
  221.  
  222.           Specifying a ONE (1) sets carrier detection to PARTIAL. This mode
  223.           is similar to FULL with the exception that the UEVENT flag is not
  224.  
  225.         QBSERIAL User Manual - V 2.0                               Page 4
  226.  
  227.  
  228.           tripped when carrier is lost. This mode should be used if UEVENT is
  229.           used for something else in your program, or you don't wish to
  230.           utilize UEVENT. This mode can also be used for talking to a modem
  231.           when there is no carrier signal present (such as dialing and
  232.           initialization commands). The Transmit and WriteChar routines will
  233.           always transmit data in this mode with or without carrier present.
  234.  
  235.           Specifying a ZERO (0) sets carrier detection to NONE. An example of
  236.           this mode would be where "plain Jane" serial I/O is required (such
  237.           as communicating with a "dumb" terminal). In this application there
  238.           are no modem handshake signals (3 wire EIA/RS-232). Carrier
  239.           detection must be disabled in this mode to prevent calls to Uevent
  240.           and disable the no carrier escape mechanisms built into the
  241.           XON/XOFF loops. Important: if you are using the XOFF/XON protocol
  242.           in this mode and receive an XOFF while transmitting, you will sit
  243.           forever waiting for an XON. This is a normal condition, with the
  244.           exception that there is no escape from this loop other than XON.
  245.  
  246.  
  247.                            Carrier Loss Detection by Polling
  248.  
  249.           As mentioned above, by default, the UEVENT trap is used to detect
  250.           when a loss of carrier occurs. There is also a function that allows
  251.           you to detect loss of carrier without using the UEVENT trap. While
  252.           I feel that using UEVENT is the simplest way to catch a carrier
  253.           loss in a program, it is possible that UEVENT might need to be used
  254.           by something else. This function is:
  255.  
  256.                X% = CarrierLost
  257.  
  258.           This function call allows to you to 'poll' for the state of
  259.           carrier. CarrierLost returns a NON-ZERO value when there is NO
  260.           carrier, and a ZERO when there IS carrier. CarrierLost is a real
  261.           time function, it returns the current carrier condition at the time
  262.           of the call. This allows you to code simple IF or DO loops to
  263.           detect loss:
  264.  
  265.                IF CarrierLost THEN
  266.                     ..process carrier loss
  267.                END IF
  268.  
  269.  
  270.  
  271.                                   Program Termination
  272.  
  273.           Since "OpenComm" seizes interrupt vectors, these vectors need to be
  274.           restored BEFORE your program ends. If you neglect to restore these
  275.           vectors, you are guaranteed a crash. The routine used to reset the
  276.           vectors is: CloseComm. Only use CloseComm if you specified a port
  277.           value of 1, 2, 3, 4, or a non-standard port address in the OpenComm
  278.           call. If you specified a port value of ZERO (Local mode) the
  279.           interrupt vectors are NOT grabbed, and do not need to be reset.
  280.  
  281.         QBSERIAL User Manual - V 2.0                               Page 5
  282.  
  283.  
  284.           CloseComm also resets any UART registers to their original value,
  285.           it also resets the programmable interrupt controller (8259 PIC) to
  286.           its original settings.
  287.  
  288.  
  289.  
  290.                                Data Terminal Ready (DTR)
  291.  
  292.           Everybody that has used QuickBASIC's OPEN COMn statement is very
  293.           familiar with the problems of the DTR signal. Apparently Microsoft
  294.           felt that DTR would never be needed after a program terminates.
  295.           Anybody who has ever tried to write a door, or chain from one
  296.           program to another has cursed this decision at some time during
  297.           their programs development. This driver handles the DTR with a
  298.           different view. When you close the comm channel the DTR signal is
  299.           left in the same state it was when you opened the comm channel. For
  300.           door applications, this is a must. 
  301.  
  302.           A function call is provided however that allows your program to
  303.           control the DTR signal:
  304.  
  305.           DTRcontrol 1 [or] 0           ' 0 = DTR OFF, 1 = DTR ON
  306.  
  307.           Additionally when you use DTRcontrol to change the state of the DTR
  308.           signal it also instructs the driver to leave it this way when the
  309.           CloseComm function is called. Remember that the driver leaves DTR
  310.           the way it found it when OpenComm was called. If you used some
  311.           other method to change DTR after OpenComm was called, it would
  312.           automatically return to that original state when you called
  313.           CloseComm. Therefor only DTRcontrol should be used if you wish to
  314.           change the state of DTR.
  315.  
  316.  
  317.                               Driver Version and Copyright
  318.  
  319.           A function is available to access the drivers version and copyright
  320.           string. This would be used if you wish to display in your final
  321.           product the version of QBserial that your are using, and/or my
  322.           copyright along with yours. In order to access the copyright
  323.           string, the following lines should be added to your Basic program:
  324.  
  325.                     X& = DriverCopyright
  326.                     WHILE (PEEK(X&))
  327.                          CP$ = CP$ + CHR$(PEEK(X&))
  328.                          X& = X& + 1
  329.                     WEND
  330.  
  331.           This places the version/copyright string into string variable CP$.
  332.           This string may now be handled in whatever method you choose.
  333.  
  334.  
  335.                                  Cresent's PDQ Library
  336.  
  337.         QBSERIAL User Manual - V 2.0                               Page 6
  338.  
  339.  
  340.  
  341.           An object module for use with PDQ is also included. PDQ does not
  342.           support UEVENT, so all references to UEVENT in the text should be
  343.           ignored. You will need to do carrier checking by polling with the
  344.           CarrierLost function. If you use FULL mode and carrier is lost it
  345.           will operate the same way as PARTIAL mode. The only exception to
  346.           this is the Transmit function, which when in FULL mode, will not
  347.           transmit data.
  348.  
  349.           NOTE:     An additional note for PDQ users. Since PDQ replaces the
  350.                     Microsoft run time libraries, the public variable
  351.                     ACRTUSED is not satisfied during the link stage. A dummy
  352.                     stub file, ACRTUSED.OBJ is included with QBserial to
  353.                     prevent this error from occurring. The next paragraph
  354.                     explains the proper linking sequence.
  355.  
  356.  
  357.                                         Linking
  358.  
  359.           Since object modules are provided for QB4.x, BC7, and PDQ, you will
  360.           need to select which one to use for your program. The additional
  361.           library (SERIAL.LIB) only contains routines from the C library that
  362.           are required by the driver. The file QBSER.OBJ should be used for
  363.           programs compiled with QuickBASIC, BC7SER.OBJ is to be used for
  364.           programs compiled with BC7 PDS, and QBSERPDQ.OBJ is for PDQ users.
  365.           Typical link command lines would look like this:
  366.  
  367.           Link yourprog qbser,,,serial;                (For QuickBASIC)
  368.  
  369.           Link yourprog bc7ser,,,serial;               (For BC7 PDS)
  370.  
  371.           Link yourprog qbserpdq acrtused,,,serial;    (For PDQ)
  372.  
  373.  
  374.  
  375.                                     Quick Libraries
  376.  
  377.           If you wish to develop programs from within the environment, you
  378.           will first need to create a Quick library using one of the object
  379.           modules (QBSER.OBJ, BC7SER.OBJ, QBSERPDQ.OBJ) and the SERIAL.LIB
  380.           file. To create a Quick lib for QuickBASIC 4.x, use the following
  381.           Link command:
  382.  
  383.                Link QBSER,,,SERIAL BQLB4x/q
  384.  
  385.           Where "BQLB4x" is one of the following: BQLB40.LIB, BQLB41.LIB, or
  386.           BQLB45.LIB. Use the one that came with your compiler. If you use
  387.           the wrong BQLB file you might get an "Invalid Format" error when
  388.           attempting to start QuickBASIC. QBSER.OBJ & SERIAL.LIB may also be
  389.           added to Quick Libraries containing other routines and OBJ's as
  390.           well.
  391.  
  392.  
  393.         QBSERIAL User Manual - V 2.0                               Page 7
  394.  
  395.  
  396.           To create a Quick Library for use within QBX (BC7's environment)
  397.           use the following link command (be sure to use Link v5.xx that came
  398.           with BC7):
  399.  
  400.                Link BC7SER,,,SERIAL QBXQLB/q;
  401.  
  402.           For PDQ, use the method for QB4.x, since you will be using the
  403.           built in run time routines built into the environment. You ONLY use
  404.           QBSERPDQ.OBJ when you link the EXEcutable file.
  405.  
  406.           Remember too, that you can also add BC7SER.OBJ & SERIAL.LIB to
  407.           Quicklibs containing other routines.
  408.  
  409.  
  410.  
  411.                                      Specifications
  412.  
  413.           The following port addresses and default interrupts are used:
  414.  
  415.                Comm      Base Address        IRQ (Default)
  416.  
  417.                 1          3F8 hex            4
  418.                 2          2F8 hex            3
  419.                 3          3E8 hex            4
  420.                 4          2E8 hex            3
  421.  
  422.           Please read the section explaining the OpenComm function for
  423.           information on how to use addresses or IRQ's other than the
  424.           defaults.
  425.  
  426.  
  427.                                         Support
  428.  
  429.           I'm reachable in the ILINK Basic conference, or the number below.
  430.           I'll help there if you have questions. No other support is
  431.           necessary. Bugs will be tended to if required, and good suggestions
  432.           tend to be implemented.
  433.  
  434.           This driver is copyrighted by me, but is being distributed as
  435.           shareware. You may copy and distribute it freely. In the spirit of
  436.           programmer to programmer I am not requesting any registration fee
  437.           for the use of these routines. All I ask is that you acknowledge in
  438.           your documentation that you are using them (Non-commercial use
  439.           only). If you want display my version/copyright notice in your
  440.           final product to give me a bit of free advertising, see the section
  441.           pertaining to this. If you feel that this driver is worth something
  442.           and you would like to send some sort of registration (say $20), I
  443.           won't refuse it! If you are using them in a PCBoard door, a copy of
  444.           the door for our system would be a nice gesture!
  445.  
  446.  
  447.  
  448.  
  449.         QBSERIAL User Manual - V 2.0                               Page 8
  450.  
  451.  
  452.           If you plan to use QBserial in a commercial product for resale, you
  453.           will need to license the driver first. please contact me for
  454.           details.
  455.  
  456.  
  457.                                       Source Code
  458.  
  459.           The source code for QBserial is available. The source is ONLY
  460.           available by signing a license agreement. The source may be used
  461.           for you own internal uses only. The source may not be distributed
  462.           by you to any other person, even if you make changes to it. Nor can
  463.           the resulting object code be sold or distributed. Modifications can
  464.           only be used in your end product, and without any type of royalty.
  465.           The license fee for the QBserial source code is $75.00. Please
  466.           contact me if you are interested.
  467.  
  468.                                       Jeff Sumberg
  469.                                 Sysop(2) - SailBoard BBS
  470.                                 Wayne, NJ, 201-831-8152
  471.  
  472.                                         [ or ]
  473.  
  474.                                         Box 212
  475.                                   Ringwood, NJ, 07456
  476.  
  477.  
  478.  
  479.                                     Acknowledgments
  480.  
  481.           Thanks go out to Mark "Sparky" Herring for using these routines in
  482.           his highly successful Qmail door (versions 3 & 4). Since his door
  483.           runs on so many systems of varied configuration, it has made
  484.           testing and proving out much easier.
  485.  
  486.           Thanks to Mark Wilson for some very good ideas.
  487.  
  488.  
  489.                                  Changes and Revisions
  490.  
  491.           06/09/89  1.0       Initial Release
  492.  
  493.           06/21/89  1.1       Added carrier detection control. Calling
  494.                               program can turn detection off and on as
  495.                               desired. Necessary if data sending/receiving
  496.                               required if carrier isn't present.
  497.  
  498.           09/01/89  1.2       Fixed a bug in Readchar where 'extended'
  499.                               characters (ASCII 128 to 255) were causing an
  500.                               Illegal Function Call in the CHR$() conversion
  501.                               (because they were being returned as negative
  502.                               numbers). Extended character may now be
  503.  
  504.  
  505.         QBSERIAL User Manual - V 2.0                               Page 9
  506.  
  507.  
  508.                               received properly. Added three new functions:
  509.                               CDtrap, CarrierLost, and DTRcontrol.
  510.  
  511.                     1.3
  512.                     1.4       Un-released interim versions.
  513.  
  514.           03/24/90  1.5       Added support for Basic Compiler 7.0 PDS and
  515.                               PDQ. Added sections to manual about Linking,
  516.                               Source code availability, and updated section
  517.                               on Quicklibs. Separate object files now
  518.                               supplied for QB, BC7, and PDQ.
  519.  
  520.           05/01/90  1.6       Oops! PDQ users found out fast that I forgot to
  521.                               compile the PDQ module with stack checking
  522.                               removed. I also forgot to include ACRTUSED.OBJ
  523.                               to satisfy linking requirements. Sorry 'bout
  524.                               that! Released only as beta to those that
  525.                               needed it.
  526.  
  527.           11/01/90  2.0       Added capability to specify non-standard port
  528.                               addresses and which IRQ to use when the port is
  529.                               opened. Removed CDtrap function. Created new
  530.                               carrier detection modes using the CarrierDetect
  531.                               function. (0 = NONE, 1 = PARTIAL, 2 = FULL).
  532.                               Also added DriverCopyright function to allow
  533.                               program access to the driver version.
  534.  
  535.  
  536.  
  537.  
  538.  
  539.  
  540.  
  541.  
  542.  
  543.  
  544.  
  545.  
  546.  
  547.  
  548.  
  549.  
  550.  
  551.  
  552.  
  553.  
  554.  
  555.  
  556.  
  557.  
  558.  
  559.  
  560.  
  561.         QBSERIAL User Manual - V 2.0                              Page 10