📄 giaotiep lpt.htm
字号:
if (ioperm(base,1,1)) fprintf(stderr, "Couldn't get the port at %x\n", base), exit(1); outb(value, base);}</PRE>Save the source code to file lpt_test.c and compile it with command:<PRE>gcc -O lpt_test.c -o lpt_test</PRE><P>The user has to have the previledges to have access to the portsfor the program to run, so you have to be root to be able toron this kind of programs without access problems.If you want to make a program which can be run by anybodythen you have to first set the owner of the programto be root (for example do compilation when yhou are root),give the users rights to execute the program and then setthe program to be always executed with owner (root) rightsinstead of the right of the user who runs it. You can setthe programn to be run on owner rights by using following command:<PRE>chmod +s lpt_test</PRE><P>Notes on source code:Some people have reported that for some reason this code does not work on theuir systems. If you have problems in getting this to work, try tho following chagest to code: replace the lines "#include <unistd.h%gt;" and "#include <asm/io.h>" with line "#include <sys/io.h>" and then replace line "#define base 0x378" with "#define base 0x0378".<P>If you want a more useful program, then download my<A HREF="lptout.c">lptout.c parallel port controlling program source code</A>.That program works so that you can give the data to send to parallelport as the command line argument (both decimal and hexadecimal numberssupported) to that program and it will then output that value to parallelport. You can compile the source code to <B>lptout</B> command usingthe following line to do the compilation:<PRE>gcc -O lptout.c -o lptout</PRE><P>After you have compiled the program you can run it easily. For examplerunning <B>./lptout 0xFF</B> will turn all data pins to 1 andrunning <B>./lptout 0x00</B> will turn all data pins to 0.<P>In some systems the I/O port addresses can be different than one used in my example program. In this case you need to modify the address in #define base line. There are different ways to know the port address. First you could try your graphical configuration tools to look for this information. Those tools and how to use them vary quite much between different Linux distributions. There are also some command line tools you can try:<UL> <LI>In many linux systems you can get information on I/O devices and ports they use with command "cat /proc/ioports". This list should include your parallel port or parallel ports in it. The first parallel port (port in motherboard) typically has name parport0. There are some cases where you might not see your device in your list or sometimes you see the sama name twice (usually the first one is the right one). <LI>In some systems you might have additional parallel ports on I/O cards in the PCI bus. In many new Linux systems you can run "lspci -v | more" to get information of each device on your PCI bus (this should tell make and model, interrupt and port and memory block assignments). </UL><P>I have also written a more feature rich program to control. portconrol is a simple general purpose I/O port control program for Linux. It allows you to write and read the supported I/O ports. The software allows writing specified value to port, reading value at given I/O address and printing it out to screen in different formats and bit-level manipulation of the port data.The portcontrol software is available as <A HREF="portcontrol.tar">portcontrol.tar</A> package that includes the source code, instructions for compiling/installing and instructions for use. For more details check the <A HREF="http://www.epanorama.net/circuits/portcontrol/README">README</A> and the <A HREF="http://www.epanorama.net/circuits/portcontrol/portcontrol.c">portcontrol.c source code</A>. <P><H3>Simple Linux GUI</H3><P>I have written a simple GUI program example for controlling parallel port on Linux system. My <A HREF="menu.sh">simple parallel port control GUI</A> is written in such way that it allows you to control parallel port pins. To see what it looks check the <A HREF="menusnapshot1.png">screenshot</A>. <P>This simple control GUI is written in such way that it runs on both GNOME and KDE windowing systems. The program is written as bash script that uses zenity and/or kdialog programs to do the GUI menus itself. The program expects that you have the portcontrol program installed in your Linux system to /usr/local/sbin/portcontrol with suitable rights that you can run it. <P>The program is intended to be a simple example that you can modify for your own uses. Just download <A HREF="menu.sh">menu.sh</A> and start testing yourself. <P><H3>Programming tips</H3><P>If you want to learn more about I/O port programming I recommend to read <A HREF="http://www.epanorama.net/counter.php?url=http://www.faqs.org/docs/Linux-mini/IO-Port-Programming.html">Linux I/O port programming mini-HOWTO</A>. Here are few tips from that document:<UL> <LI>Routines for accessing I/O ports are in /usr/include/asm/io.h (or linux/include/asm-i386/io.h in the kernel source distribution). The routines there are inline macros, so it is enough to #include <asm/io.h>; you do not need any additional libraries. <LI>Because of a limitation in gcc, you have to compile any source code that uses these routines with optimisation turned on (gcc -O1 or higher), or alternatively use #define extern static before you #include <asm/io.h> (remember to #undef externafterwards). <LI>For debugging, you can use gcc -g -O (at least with modern versions of gcc), though optimisation can sometimes make the debugger behave a bit strangely. <LI>Sometimes it is a good idea to put all I/O port access in a separate source file and compile only that with optimisation turned on. <LI>Before you access any ports, you must give your program permission to do so. This is done by calling the ioperm() function declared in unistd.h, and defined in the kernel) somewhere near the start of your program (before any I/O port accesses). The syntax is ioperm(from, num, turn_on), where from is the first port number to give access to, and num the number of consecutive ports to give access to. ioperm() can only give access to ports 0x000 through 0x3ff (or higher ports, you need to use iopl(3) which gives you access to all ports at once). <LI>The ioperm() call requires your program to have root privileges; thus you need to either run it as the root user, or make it setuid root. <LI>You are not required to explicitly drop your port access privileges with ioperm(..., 0) at the end of your program; this is done automatically as the process exits. <LI> You can drop the root privileges after you have called ioperm() to enable the ports you want to use. A setuid() to a non-root user does not disable the port access granted by ioperm(), but a fork() does (the child process does not get access, but the parent retains it). <LI>To input a byte (8 bits) from a port, call inb(port), it returns the byte it got <LI>To output a byte, call outb(value, port) <LI>Note that all port access instructions take at least about a microsecond to execute. <LI>There are manual pages for ioperm(2), iopl(2), and the above macros in reasonably recent releases of the Linux manual page collection <LI>Another way to access I/O ports is to open() /dev/port (a character device, major number 1, minor 4) for reading and/or writing (the stdio f*() functions have internal buffering, so avoid them). Then lseek() to the appropriate byte in the file (file position 0 = port 0x00, file position 1 = port 0x01, and so on), and read() or write() a byte or word from or to it. Naturally, for this to work your program needs read/write access to /dev/port. This method is probably slower than the normal method above, but does not need compiler optimisation nor ioperm(). It doesn't need root access either, if you give a non-root user or group access to /dev/port (potentially dangerous for system security)</UL><P>Be warned that this I/O port accessing as decribed above will only work on i386 system. To be able to use ioperm you need to include the ncessary headers to your software: <PRE>#include <unistd.h> /* for libc5 */ #include <sys/io.h> /* for glibc */ </PRE>The function protype is the following:<PRE>int ioperm(unsigned long from, unsigned long num, int turn_on); </PRE>Ioperm sets the port access permission bits for the process for num bytes starting from port address from to the value turn_on. The use of ioperm requires root privileges. Only the first 0x3ff I/O ports can be specified in this manner. For more ports, the iopl function must be used. Permissions are not inherited on fork, but on exec they are. This is useful for giving port access permissions to non-privileged tasks. This call is mostly for the i386 architecture. On many other architectures it does not exist or will always return an error. On success, zero is returned. On error, -1 is returned, and errno is set appropriately.<P> ioperm is Linux specific and should not be used in programs intended to be portable. Libc5 treats it as a system call and has a prototype in <unistd.h>. Glibc1 does not have a prototype. Glibc2 has a prototype both in <sys/io.h> and in <sys/perm.h> (avoid this latter bacause it is available on i386 only).<P>The I/O accessing can be different on other Linux platforms (for example the alpha uses a library, libio, to emulate inb/outb in user programs).<P>The description above concentrates on the C programming language. It should apply directly to C++ as well. In assembler, you have to call ioperm() or iopl() as in C, but after that you can use the I/O port read/write instructions directly. <P>In other languages, unless you can insert inline assembler or C code into the program or use the system calls mentioned above, it is probably easiest to write a simple C source file with functions for the I/O port accesses or delays that you need, and compile and link it in with the rest of your program. Or use /dev/port as described above. <P><H3>Parallel Port Pin Programming Library for Linux</H3><P>If you want a higher level approach to parallel port controlling than low level directly writign to control registers apprach, there are also tools for this available. <A HREF=">http://www.epanorama.net/counter.php?url=http://parapin.sourceforge.net/">Parapin</A> is an easy to use parallel port pin programming library. You can find this software at <A HREF="http://www.epanorama.net/counter.php?url=http://parapin.sourceforge.net/">http://www.epanorama.net/counter.php?url=http://parapin.sourceforge.net/</A>. Parapin makes it easy to write C code under Linux that controls individual pins on a PC parallel port. This kind of control is very useful for electronics projects that use the PC's parallel port as a generic digital I/O interface. <P>Parapin goes to great lengths to insulate the programmer from the somewhat complex parallel port programming interface provided by the PC hardware, making it easy to use the parallel port for digital I/O. <P>Parapin provides a simple interface that lets programs use pins of the PC parallel port as digital inputs or outputs. Parapin makes it easy to write C code under Linux that controls individual pins on a PC parallel port. You can assert high or low TTL logic values on output pins or poll the state of input pins. This kind of control is very useful for electronics projects that use the PC's parallel port as a generic digital I/O interface. <P>Parapin has two personalities: it can either be used as a user-space C library, or linked as part of a Linux kernel module. There is also a device driver that provides access to the kernel module from user-space, allowing the administrator to use filesystem permissions to control access to the port. Parapin was written with efficiency in mind, so that Parapin can be used in time-sensitive applications. <P>The user-space version of Parapin is compiled and linked very much like any other C library. If you installed Parapin on your system using ``make install'', the library (libparapin.a) was probably installed in /usr/local/lib. The header file with the library's function prototypes and other definitions, parapin.h, is probably also in /usr/local/include. To use the library, first make sure to #include parapin.h in your C source file. When linking, add -lparapin along with any other libraries you might be using. C library initialization is performed using the function <PRE> int pin_init_user(int lp_base);</PRE>whose single argument, lp_base, specifies the base I/O address of the parallel port being controlled.In both the userspace C library version, and the kernel version, pins are configured using one of the following three functions: <PRE> void pin_input_mode(int pins); void pin_output_mode(int pins); void pin_mode(int pins, int mode);</PRE>The pins argument of all three functions accepts the LP_PINnn constants Once Parapin has been initialized (Section 5), and pins have been configured as output pins (Section 6), values can be asserted on those pins using the following functions: <PRE> void set_pin(int pins); void clear_pin(int pins); void change_pin(int pins, int state);</PRE>value being asserted by the ``far end'' can be queried using the following function. Please note that pin state may only be queried only if they are input pins (by hardware or set as input). <PRE> int pin_is_set(int pins);</PRE><P>If you would like to use the kernel version of parapin from a userspace program without writing your own hardware-specific driver, you can load the parapindriver module after loading kparapin. This device driver exposes the functionality of kparapin through a normal character-device interface (except for interrupt handling). The primary advantages are that access to the parallel port functionality of parapin may be controlled through /dev filesystem permissions, and all interaction is done through standard device-oriented system calls such as open(), close(), and ioctl(). When building a userspace program that will make use of the parapindriver interface to kparapin, you must include parapindriver.h. This header file defines the device-specific ioctl commands used to communicate with the device driver. It also includes parapin.h, so your program can make use of all the ``LP_*'' constants. The parapindriver system calls take arguments using these constants and pass them unchanged down to the kparapin routines. <P>Once parapindriver is successfully loaded, and a corresponding /dev entry is in place, initialization and shutdown of the parallel port are easy. To initialize the parapin system, just call open(2) on the /dev entry as you would any other device file: <PREA> int device; device = open("/dev/<device-name>", 0); if (device < 0) { fprintf(stderr, "device open failed\n"); exit(-1); }</PRE>The device name is typically parport0, parport1, parport2, etc... (as found in Fedora Core 4 Linux system).To shutdown the parapin system you simply have to call close(2): <PRE> close(device);</PRE>When using the parapindriver device interface, all functionality related to pins on the parallel port is invoked via the ioctl(2) system call. The ioctl commands for parapindriver are defined in the parapindriver.h header file. The two used to set pins to be either output pins or input pins are ``PPDRV_IOC_PINMODE_OUT'' and ``PPDRV_IOC_PINMODE_IN'', respectively. Examples: <PRE> ioctl(device, PPDRV_IOC_PINMODE_OUT, LP_PIN01 | LP_PIN02); ioctl(device, PPDRV_IOC_PINMODE_IN, LP_PIN11);</PRE>Setting pin state through the device driver interface follows all the same rules as described above. The ioctl commands used are ``PPDRV_IOC_PINSET'' and ``PPDRV_IOC_PINCLEAR''. <PRE> ioctl(device, PPDRV_IOC_PINSET, LP_PIN01 | LP_PIN02); ioctl(device, PPDRV_IOC_PINCLEAR, LP_PIN01);</PRE>Querying pin state through the device driver interface follows all the same rules as described above. The ioctl command used is ``PPDRV_IOC_PINGET''. Please note that pin state may only be queried only if they are input pins (by hardware or set as input). <PRE> int value; value = ioctl(device, PPDRV_IOC_PINGET, DATA);</PRE>Arguments to these ioctl calls use exactly the same constants as are used by the userspace and kernel versions of parapin itself. Return values from these ioctl calls are the same as those defined for the corresponding functions in kparapin (plus value -ENOTTY indicates that an invalid ioctl command value was passed down).<P>The parallel port pins are accessed with constants in form of LP_PIN plus parallel port pin number. For example LP_PIN02 refers to parallel port pin 2 that is D0 data out pin. Programming tip: Usually, it is most convenient to use #define statements to give pins logical names that have meaning in the context of your application. Example: <PRE> #include "parapin.h" #define VCC LP_PIN02 #define CS LP_PIN03 #define CLK LP_PIN04 #define D0 LP_PIN10 /* input pin */ ... clear_pin(CS); /* pull Chip Select low, tell it to acquire */ ... set_pin(CLK); /* clock it */ clear_pin(CLK);</PRE><P>Parapin also supports interrupts through parallel port.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -