📄 use of a pc printer port for control and data acquisition.htm
字号:
incrementing a variable. However, recognize that this is barely scratching the
surface.
<P>Then you might try a more complex ISR of the following form. At the time of
this writing I have not tried this.
<UL>
<LI>disable all interrupts.
<LI>set mask to disable IRQ 7 interrupts.
<LI>outportb(0x20,0x20).
<LI>enable all interrupts.
<LI>.. do whatever needs to be done ..
<LI>disable all interrupts.
<LI>set mask to enable IRQ 7 interrupts.
<LI>enable interrupts. </LI></UL>
<P>Note the difference from the previous. Any further IRQ 7 interrupts are
blocked while in the ISR, but in the middle of the ISR, all other interrupts are
enabled. This should permit all C functions to work.
<P>
<CENTER>
<H3>F. IRQ Enable Bit</H3></CENTER>
<P>Recall that there are three ports associated with the control of a printer
port; Data, Status and Control. Bit 4 of the Control Port is a PC output; IRQ
Enable. Note that Bit 2 of the Status Port is a PC input; /IRQ. Neither of these
bits are associated with the DB-25 connector. Rather, they control logic on the
printer card or PC motherboard.
<P>If the IRQ Enable output is at logic one, an interrupt occurs on a negative
going transition on the /ACK input. (I have yet to figure out what the IRQ input
does).
<P>Thus, in addition to setting the mask to entertain interrupts from IRQ 7 as
discussed above, you must also set IRQ Enable to a logic one. <PRE>
mask=inportb(0x21) & ~0x80;
outportb(0x21,mask); /* as discussed above */
outportb(CONTROL, inportb(CONTROL) | 0x10);
</PRE>
<P>Note that in this implementation, all bits other than Bit 4 on the Control
Port are left as they were.
<P>Prior to exiting from your program, it is good practice to leave things tidy.
That is, set Bit 4 back to a zero. <PRE>
outportb(CONTROL, inportb(CONTROL) & ~0x10);
</PRE>
<HR>
<CENTER><IMG
src="Use of a PC Printer Port for Control and Data Acquisition.files/PHAFIG5.gif">
<P><B>Fig 5. Use of Parallel Printer Port For Interrupts</B> </CENTER>
<HR>
<P>
<CENTER>
<H3>G. Programs</H3></CENTER>
<P>Program PRNT_INT.C simply causes a screen message to indicate an interrupt
has occurred. Note that global variable "int_occurred" is set to false in the
declaration. On interrupt, this is set to true. Thus, the code in main within
the if(int_occurred) is only executed if a hardware interrupt did indeed occur.
<P>Program TIME_INT.C is the same except for main. When the first interrupt
occurs, the time is fetched off the system clock. Otherwise the new time is
fetched and the difference is calculated and displayed.
<HR>
<PRE>
/*
** Program PRNT_INT.C
**
Uses interrupt service routine to note interrupt from printer port.
The interrupt is caused by a negative on /ACK input on Printer Port.
This might be adapted to an intrusion detector and temperature logger.
Note that on my machine the printer port is located at 0x0378 -
0x037a and is associated with IRQ 7. You should run Microsoft
Diagnostics (MSD) to ascertain assignments on your PC.
** Name Address in Table
**
** IRQ2 0x0a
** IRQ4 0x0c
** IRQ5 0x0d
** IRQ7 0x0f
**
** P.H. Anderson, MSU, 12 May 91; 26 July 95
*/
#include <stdio.h>
#include <bios.h>
#include <dos.h>
#define DATA 0x0378
#define STATUS DATA+1
#define CONTROL DATA+2
#define TRUE 1
#define FALSE 0
void open_intserv(void);
void close_intserv(void);
void int_processed(void);
void interrupt far intserv(void);
int intlev=0x0f; /* interrupt level associated with IRQ7 */
void interrupt far (*oldfunc)();
int int_occurred = FALSE; /* Note global definitions */
int main(void)
{
open_intserv();
outportb(CONTROL, inportb(CONTROL) | 0x10);
/* set bit 4 on control port to logic one */
while(1)
{
if (int_occurred)
{
printf("Interrupt Occurred\n");
int_occurred=FALSE;
}
}
close_intserv();
return(0);
}
void interrupt far intserv(void)
/* This is written by the user. Note that the source of the interrupt
** must be cleared and then the PC 8259 cleared (int_processed).
** must be included in this function.
*/
{
disable();
int_processed();
int_occurred=TRUE;
enable();
}
void open_intserv(void)
/* enables IRQ7 interrupt. On interrupt (low on /ACK) jumps to intserv.
** all interrupts disabled during this function; enabled on exit.
*/
{
int int_mask;
disable(); /* disable all ints */
oldfunc=getvect(intlev); /* save any old vector */
setvect (intlev, intserv); /* set up for new int serv */
int_mask=inportb(0x21); /* 1101 1111 */
outportb(0x21, int_mask & ~0x80); /* set bit 7 to zero */
/* -leave others alone */
enable();
}
void close_intserv(void)
/* disables IRQ7 interrupt */
{
int int_mask;
disable();
setvect(intlev, oldfunc);
int_mask=inportb (0x21) | 0x80; /* bit 7 to one */
outportb(0x21, int_mask);
enable();
}
void int_processed(void)
/* signals 8259 in PC that interrupt has been processed */
{
outportb(0x20,0x20);
}
<HR>
/*
* Program TIME_INT.C
*
Uses interrupt service routine to note interrupt from printer port.
The interrupt is caused by a negative on /ACK input on Printer Port.
Calculates time and displays the time in ms between interrupts.
* P.H. Anderson, MSU, 10 Jan, '96
*/
#include <stdio.h>
#include <bios.h>
#include <dos.h>
#include <sys\timeb.h>
#define DATA 0x0378
#define STATUS DATA+1
#define CONTROL DATA+2
#define TRUE 1
#define FALSE 0
void open_intserv(void);
void close_intserv(void);
void int_processed(void);
void interrupt far intserv(void);
int intlev=0x0f; /* interrupt level associated with IRQ7 */
void interrupt far (*oldfunc)();
int int_occured=FALSE; /* Note global definitions */
int main(void)
{
int first=FALSE;
int secs, msecs;
struct timeb t1, t2;
open_intserv();
outportb(CONTROL, inportb(CONTROL) | 0x10);
/* set bit 4 on control port (irq enable) to logic one */
while(1)
{
if (int_occurred)
{
int_occurred=FALSE;
if (first==FALSE)
/* if this is the first interrupt, just fetch the time */
{
ftime(&t2);
first=TRUE;
}
else
{
t1=t2; /* otherwise, save old time, fetch new */
ftime(&t2); /* and compute difference */
secs=t2.time - t1.time;
msecs=t2.millitm - t1.millitm;
if (msecs<0)
{
--secs;
msecs=msecs+1000;
}
printf("Elapsed time is %d\n",1000*secs+msecs);
}
}
}
close_intserv();
return(0);
}
void interrupt far intserv(void)
/* This is written by the user. Note that the source of the interrupt
/* must be cleared and then the PC 8259 cleared (int_processed).
/* must be included in this function.
/*******/
{
disable();
int_processed();
int_occurred=TRUE;
enable();
}
void open_intserv(void)
/* enables IRQ7 interrupt. On interrupt (low on /ACK) jumps to intserv.
/* all interrupts disabled during this function; enabled on exit.
/*******/
{
int int_mask;
disable(); /* disable all ints */
oldfunc=getvect(intlev); /* save any old vector */
setvect(intlev, intserv); /* set up for new int serv */
int_mask=inportb(0x21); /* 1101 1111 */
outportb(0x21, int_mask & ~0x80); /* set bit 7 to zero */
/* -leave others alone */
enable();
}
void close_intserv(void)
/* disables IRQ7 interrupt */
{
int int_mask;
disable();
setvect(intlev, oldfunc);
int_mask=inportb(0x21) | 0x80; /* bit 7 to one */
outportb(0x21,int_mask);
enable();
}
void int_processed(void)
/* signals 8259 in PC that interrupt has been processed */
{
outportb(0x20, 0x20);
}
</PRE></BODY></HTML>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -