⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 intrpts.c

📁 源代码PC104用户手册PC104用户手册PC104用户手册
💻 C
字号:
/*
   Science & Technology CO.,LTD.
   W2-B5 High-Tech Industrial Park, ShenZhen, GuangDong, P.R.C.

   Tel:   86-755-6544000
   Fax:   86-755-6549140
   Zip:   518057

   Board:       SF93A-0102
   Compiler:    Turbo C (r) version 1.0, 1.5, 2.0
		Turbo C++ (r) version 1.0
		Borland C++ (r) version 2.0, 3.0

   Last update: Feb 22, 2002

  DESCRIPTION
  ~~~~~~~~~~~
  This program sets up the user PIT to generate interrupts at a selected
  rate.  An interrupt service routine (ISR) is provided that simply
  samples from one channel on the ADT600 each time the interrupt is
  activated.  The value is displayed on the screen as a foreground
  process.  Although the ISR in this program is trivial, all the
  ingredients for powerful interrupt driven data are included.

  NOTES
  ~~~~~
  You must change the first two lines in the main function to reflect the
  base address and IRQ settings for your ADT600.

*/


#include <dos.h>
#include <conio.h>
#include <stdio.h>

#include "ADT600.h"
#include "ADT600.inc"


unsigned char OldIMRMask,     /* Interrupt Mask Register storage variable */
              IRQ;            /* IRQ used to generate interrupts */


int      ADValue;            /* Value read from A-D converter */

void interrupt (*OldINT) (void);  /* Original interrupt storage */

/**********

   ClearBitInIMR

   This function clears a bit in the 8259 Interrupt controller that will
   enable interrupts on the appropriate IRQ line.  For example to enable
	 interrupts from IRQ 3 bit 3 must be cleare.  Remember that bits are
   numbered 0..7.


**********/

void ClearBitInIMR(unsigned char Bit)
{
 unsigned char Twos[8] = { 1, 2, 4, 8, 16, 32, 64, 128};
 unsigned char OldIMR, IMR;

 OldIMR = inportb(0x21);                /* Read in current IMR */
 IMR = OldIMR & (255 - Twos[Bit]);      /* Clear desired bit */
 outportb(0x21, IMR);                   /* cprintf out new IMR */
}

/**********

   SetBitInIMR

   This function sets a bit in the 8259 Interrupt controller that will
   mask out interrupts on the appropriate IRQ line.  For example to disable
	 interrupts from IRQ 3 bit 3 must be set.  Remember that bits are
   numbered 0..7.

**********/

void SetBitInIMR(unsigned char Bit)
{
 unsigned char Twos[8] = { 1, 2, 4, 8, 16, 32, 64, 128};
 unsigned char OldIMR, IMR;

 OldIMR = inportb(0x21);                /* Read in current IMR */
 IMR = OldIMR | Twos[Bit];              /* Set desired bit */
 outportb(0x21, IMR);                   /* cprintf out new IMR */
}

/**********

   VectorInterrupt

   The VectorInterrupt function is used to assign a new vector for the
   designated interrupt.

**********/

void VectorInterrupt(int InterruptNumber, void interrupt (*ISR) ())
{
 disable();                      /* Don't want int called during revector */
 setvect(InterruptNumber, ISR);  /* Set the vector */
 enable();                       /* Reenable interrupts */
}

/**********

  NewISR

  The NewISR function is called whenever an interrupt is generated on the
  specified IRQ. It simply gets a single value from the A-D board.  An
  ISR is generally quite a bit more complex and one could be placed within
  the shell of this function.  Do not try to access any functions that use
  DOS calls (disk access, screen cprintfs, read keyboard, etc) and do not use
  floating point operations in this function.  DOS and the Floating Point
  Emulator are not reentrant and will cause unexpected happenings if used
  inside an interrupt.

  Before exiting the function passes the End of Interrupt (EOI) command
  to the 8259 interrupt controller.  Don't forget the EOI command; it is
  required even if your ISR does nothing.

**********/

void interrupt NewISR(void)
{
 StartConversion();              /* Start a conversion */
 while (ConversionDone() == 0);  /* Wait until converted data is ready */
 ADValue = ReadData();           /* Transfer data from converter */

 outportb(BaseAddress + CLEAR_INT, 0);  /* Clear Interrupt on ADT600 */
 outportb(0x20, 0x20);           /* End of interrupt command to controller */
}

/***********

  The ConfigureIRQ procedure saves the startup Interrupt Mask Register (IMR)
  and the startup value of the interrupt vector, then sets the interrupt
  vector to point at the NewISR procedure.  Remember to use the
  RestoreStartupIRQ procedure (below) before exiting your program to restore
  things to their original state.

***********/

void ConfigureIRQ(unsigned char IRQ)
{
 SetIRQStatus(ENABLED);
 OldIMRMask = inportb(0x21);           /* Save original IMR Mask */
 OldINT = getvect(IRQ + 8);            /* Save startup vector */
 VectorInterrupt(IRQ + 8, NewISR);     /* Set New vector */
}

/***********

  The RestoreStartupIRQ procedure restores the startup IMR and interrupt
  vectors that were saved in the ConfigureIRQ procedure.  Do not call this
  procedure without first calling the ConfigureIRQ procedure.

***********/

void RestoreStartupIRQ(void)
{
 disable();                         /* Don't want interrupts occuring
                                       while switching vectors */
 outportb(0x21, OldIMRMask);           /* Reset IMR to startup value */
 VectorInterrupt(IRQ + 8, OldINT);  /* Revector original interrupt */
 enable();                          /* Reenable interrupts */
}

/**********

  ProgramTitle

**********/

void ProgramTitle(char St[80])
{
 gotoxy(1,1); clreol();
 cprintf("ADT600  Sample Program");
 gotoxy(80 - strlen(St), 1);
 cprintf(St);
}

void main(void)
{
 IRQ = 5;
 InitializeBoardSettings(0x300, 10.0, BIPOLAR);  /* Set base address and volt
						  range */
 clrscr();
 ProgramTitle("Interrupt driven sampling.");
 gotoxy(1, 25);
 cprintf("Press any key to quit. . .");
 gotoxy(28,12);
 cprintf("Volts: ");

 ResetBoard();                      /* Reset the board */

 ConfigureIRQ(IRQ);                 /* setup the IRQ */

 SetChannel(0);                     /* Sample from channel 0 */
 SetUserClock(100);                 /* Clock will generate interrupts 100
				       times a second. */

 ClearBitInIMR(IRQ);                /* Enable interrupts on specified IRQ */

 SetIRQStatus(ENABLED);             /* Allow interrupts from ADT600 */

/*
  The following loop displays the value read from the A-D board during
  the last interrupt. If you have a signal connected to channel 0 on your
  board you will see the voltage of that signal displayed.  Note that ADValue
  is never updated inside of this loop yet its value changes with your signal.
  This is because ADValue is updated in the interrupt routine.
*/

 while (kbhit() == 0)
  {
   gotoxy(35, 12);
   cprintf("%6.2f", DigitalToSBS(ADValue));  /* display value as volts */
  }

 getch();                           /* Read character from keyboard */

 SetIRQStatus(DISABLED);
 RestoreStartupIRQ();               /* Restore interrupt system to startup
                                       configuration */
 clrscr();
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -