📄 jan axelson's parallel port faq.htm
字号:
another device? </I></P>
<P>A: Yes. </P>
<P><I>Q: Alternatively, if I jumper my I/O card to EPP mode (which doesn't
use DMA channel), should I still set it up in Win95 as an "ECP Port", or
as a regular "Printer Port"? </I></P>
<P>A: Use the ECP setting unless you have problems with it. </P>
<P><I>Q: Which mode (ECP or EPP) would work best with parallel port
devices such as the Snappy and the QuickCam Color? </I></P>
<P>A: As a general rule, because of its FIFOs and DMA support, ECP is good
at transferrring big blocks of data quickly (scanners, printers). EPP is
good for links that switch directions frequently (drives). Specifically,
it depends on the driver for the device, so you might want to experiment
if both options are available. </P>
<P><I>Q: Do I need to use parallel cables and switchboxes which are
SPECIFICALLY labeled to support ECP/EPP to connect my parallel devices, or
will any cable and switchbox work with all ECP/EPP ports and devices (as
long as they have the 25 pins wired straight-through)? </I></P>
<P>A: A cable that is "IEEE 1284-compliant" meets certain standards for
shielding, cable capacitance, etc. Over short links (5-6 feet), any cable
will usually work, but you can run into problems with longer cables and
higher speeds. Get the better cable if you have a choice. </P>
<P><I>Q: I have been communicating in ECP mode with another device. PC to
peripheral transfers work fine. However in peripheral-to-PC transfers,
sometimes the data repeats four times. For instance, If my peripheral
sends a 0, I get four 0s instead of one. </I></P>
<P>A: My ECP controller on the PC side was configured for RLE data
compression. RLE is enabled depending of the state of S7: S7 low is RLE
disable, and S7 high is RLE enable. With RLE, the sending device sends the
number of times to repeat a byte followed by the byte, and the receiving
device automatically creates the requested number of repetitions. Francois
Blouin provided this question and the answer. </P>
<H2>Mode Problems </H2>
<P><I>Q: I am having a problem using a parallel port device I designed and
built,with the newer bidirectional parallel ports. The device works fine
with the old IBM style ports but gags when I try to use it with the newer
styleprinter ports. Is there a standard way to force a printer port into
the old IBM configuration ? </I></P>
<P>A: There is no single standard. There are a couple of different
approaches you could take. </P>
<P>One way is to disable the newer modes entirely. Depending on the port,
you can do this in the CMOS setup, or with a jumper, or a utility on disk.
Select "AT" type, not PS/2, ECP, or EPP. You can do the same thing by
programming the port chip directly, but how to do it varies with the chip.
This method is fine if you use the port only for your OScope. If you use
the same port with other devices, they won't be able to use the newer
modes unless you re-enable them. </P>
<P>The second option is to get a PS/2, EPP, or ECP port to act like an
old-style, "original," SPP, without disabling the new modes entirely. A
PS/2 (simple bidirectional) port or EPP will act like an SPP as long as
you don't set bit 5 of the control port (at base address + 2) to 1.
Setting this bit to 1 disables the data outputs and enables you to read
external signals at the data port. On an SPP, the bit has no effect. (EPP
transfers are done by writing to different port addresses; if you write to
the base address, it acts like an SPP.) </P>
<P>ECPs are a little more complicated. An ECP can operate in several
modes. You select the mode by writing to bits 7, 6, and 5 of the ECR
(extended control register) at (base address + 402h). (Example: for a port
at 378h, the ECR is at 77Ah.) If you want the port to act like an SPP, use
mode 000 (SPP). In mode 011 (ECP), writing to the data port (the base
address) causes the port to try to do an ECP Address Write cycle, with
automatic handshaking, which you don't want. </P>
<P>To test if a port is ECP, read the ECR at (base address + 402h) and
verify that bit 0 (fifo empty) =1 and bit 1 (fifo full) =0. Then write 34h
to the ECR and read it back. Bits 0 and 1 are read-only, so if you read
35h, you almost certainly have an ECP. (This is the test described in
Microsoft's ECP document, on the MS developer's CD-ROM.) </P>
<P>So what can you do if you have an unknown port and want it to emulate
an SPP? First, test for the presence of an ECP and if it exists, select
mode 000 in the ECR. Otherwise, just remember to keep control bit 5 = 0.
</P>
<P>One other thing: in the advanced modes, for faster performance, the
control-port outputs often change from open-collector/open-drain type to
push-pull (totem-pole) type. This means that in an EPP, and in all of the
ECP modes except SPP, you can't count on being able to write "1" to a
control output and then use it as an input bit (as some projects do).
Also, some ports apparently have push-pull control outputs in all of the
modes, so for compatibility with all ports, don't use the control bits as
inputs. </P>
<H2>Accessing Ports Under Windows </H2>
<P><I>Q: How do you output a byte to the parallel port under Windows 95?
I'm using Delphi/Visual C++/Visual Basic. The faqs I've found say to write
directly to the portregister, but I understand that Windows prevents this.
Is this correct? </I></P>
<P>A: You can write directly to the port registers under Window 95/98 (but
not under NT). If the port isn't being used by anything else, there should
be no problem. Here's how to read and write to ports in various
languages:</P>
<P>Visual Basic has no built-in way to access ports. A solution is to use
a DLL written in Delphi or C that enables you to use inp and out routines
in Visual-Basic programs. See <A
href="http://www.lvr.com/">http://www.lvr.com/</A> for inpout32 and other
options. </P>
<P>In 16-bit Delphi, use inport and outport. In 32-bit Delphi (Delphi 2
and higher), use in-line assembly code. Here is Delphi source code for
routines for reading and writing to ports.</P>
<P><FONT face="Courier New">library inpout32;<BR>uses SysUtils;</FONT></P>
<P><FONT face="Courier New">{write a byte to a port}<BR>procedure
Out32(PortAddress:smallint;Value:smallint);stdcall;export;<BR><BR>var<BR>ByteValue:Byte;</FONT></P>
<P><FONT face="Courier New">begin<BR>ByteValue:=Byte(Value);<BR>{in-line
assembly code begins here}<BR>asm<BR>[preserve the contents of the dx
register]<BR>push dx<BR>[write ByteValue to PortAddress]<BR>mov
dx,PortAddress<BR>mov al, ByteValue<BR>out dx,al<BR>{restore the contents
of dx}<BR>pop dx<BR>end;<BR>end;]</FONT></P>
<P><FONT face="Courier New">{read a byte from a port}<BR>function
Inp32(PortAddress:smallint):smallint;stdcall;export;</FONT></P>
<P><FONT face="Courier New">var<BR>ByteValue:byte;</FONT></P>
<P><FONT face="Courier New">begin<BR>{in-line assembly code begins
here}<BR>asm<BR>[preserve the contents of the dx register]<BR>push
dx<BR>[read ByteValue from PortAddress]<BR>mov dx, PortAddress<BR>in
al,dx<BR>mov ByteValue,al<BR>{restore the contents of dx}<BR>pop
dx<BR>end;<BR>Inp32:=smallint(ByteValue) and $00FF;<BR>end;</FONT></P>
<P><FONT face="Courier New">Exports<BR>Inp32,<BR>Out32;</FONT></P>
<P><FONT face="Courier New">begin<BR>end.</FONT></P>
<P>In C, use inp and outp, if available. Some 32-bit compilers don't
support these. In that case, use in-line assembly code, or an inpout
DLL.</P>
<P>Jody Rice has provided this code for using inpout32 with Visual C++
v6:</P>
<P><FONT face="Courier New, Courier, mono">typedef UINT (CALLBACK*
LPFNDLLFUNC1)(INT,INT);<BR>typedef UINT (CALLBACK* LPFNDLLFUNC2)(INT);
<BR>HINSTANCE hDLL; // Handle to DLL <BR>LPFNDLLFUNC1 Output; // Function
pointer <BR>LPFNDLLFUNC2 Input; // Function pointer <BR>INT Addr; <BR>INT
AddrIn; <BR>INT Value; <BR>hDLL = LoadLibrary("Inpout32"); <BR>if (hDLL !=
NULL)<BR>{ <BR> Output =
(LPFNDLLFUNC1)GetProcAddress(hDLL,"Out32"); <BR> Input =
(LPFNDLLFUNC2)GetProcAddress(hDLL,"Inp32"); <BR> if (!Output ||
!Input) <BR> { <BR> // handle the error
FreeLibrary(hDLL); </FONT><BR><FONT
face="Courier New, Courier, mono"> } <BR>} <BR>Addr = 0x378;
<BR>AddrIn = 0x379; <BR>Value = 0; <BR>Output(Addr, Value); <BR>INT
somenum = Input(Addr); </FONT></P>
<P><EM>Q: In Visual Basic, I use MSComm to read and write to serial ports.
How do I do the same for parallel ports?</EM><BR><BR>Unfortunately, things
aren't as simple with the parallel port. If all you need is simple
line-printer-type output (check the status lines and send each byte with a
strobe), you may be able to use the Generic printer object, or the
Createfile and Writefile API calls, or (16-bit only) Open "LPT1".<BR></P>
<P>From Chris Wells: The lpt.vxd driver for Windows 9x may enable you read
external signals on the data lines. Use SetCommTimeouts() to specify a
ReadTotalTimeoutConstant of 1000 or so and call ReadFile<FWIW readfile()
overlapped an use i>.</P>
<P>For anything more complicated (PC-to-PC transfer or anything that
requires reading the port), you're pretty much on your own. Windows and VB
have no built-in support. There are a few vendors of parallel-port
drivers, but these tend to be very expensive (thousands of $$) and are
limited to the IEEE-1284 modes.<BR><BR>To write your own driver (which can
be as simple as a routine in your application), there are various tools
that enable reading and writing to ports. Under W3.x and W95, you can use
an <EM>inpout</EM> DLL, though this offers no system-level protection. The
alternative is a Vxd (W95), kernel-mode driver (NT), or an Ocx or Active-X
Control that can communicate with these.</P>
<P><I>Q: I need to use the parallel port to control a device. I'm told
that the best way is to use a driver like printers and data acquisition
cards use. How do I write a driver for use with Visual Basic?</I> </P>
<P>A: In the most general sense, a driver is just a program or set of
routines that communicates with a specific piece of hardware, such as a
parallel port. It can be as simple or sophisticated as you like. Under
Windows 3.x or Windows 95, <EM>driver</EM> often means a VxD (virtual
device driver). Advantages of using a VxD are the ability to protect a
port by controlling access, and faster hardware-interrupt response.
There's no way to write a VxD in Visual Basic. Most developers use
Microsoft's Device Developers Kit (DDK), which includes an assembler,
examples, and much information about driver development. Some C compilers
also support VxD creation. To write a VxD, you need to be an experienced C
or assembly-language programmer with a good understanding of Windows
programming - or you will be when you're finished! </P>
<P>If all you need is the ability to register a port in the system
registry (to control access to it), to read and write to the port, and to
detect hardware interrupts, you can use one of the commercial OCX's
designed for use with (32-bit) Visual Basic.</P>
<P><EM>Q: My company has a product that connects to the parallel port. The
process of finding the port address via WIN95's properties window is too
much for some customers - we'd like the program to be able to find the
address itself without needing the customer to find and enter the
port<BR>address. How can we find a parallel port's address under software
control?</EM></P>
<P>Here are three options:</P>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -