//--------------------------------------------------------------------------- // L351.C // Program that uses the 80C188 Internal Timer for periodic interrupt // interrupt generation. LED-5 is toggled 80-times with each interrupt. // // C/C++ code for the SBC188 boards. // C.P. Diduch, March 1999. //--------------------------------------------------------------------------- #define KEY_PA 0x0138 // Parallel port 'KEY BOARD' addresses. #define KEY_PB 0x013A #define KEY_PC 0x013C #define KEY_CON 0x013E #define EOI 0xFF22 // 80C188XL EOI (end of interrupt) port. #define IT_TYPE 18 // 80C188XL Interrupt TYPE no. for TIMER1. #define TCUCON 0xFF32 // 80C188XL Interrupt control port for TIMERS. #define T1CNT 0xFF58 // 80C188 TIMER1 count register. #define T2CNT 0xFF60 // 80C188 TIMER2 count register. #define T1CON 0xFF5E // 80C188 TIMER1 control register. #define T2CON 0xFF66 // 80C188 TIMER2 control register. #define T1CMPA 0xFF5A // 80C188 TIMER1 maximum count register. #define T2CMPA 0xFF62 // 80C188 TIMER2 maximum count register. #define TRUE 1 #include #include void int_vect_init(void); // Function prototypes. void ppi_init(void); void int_con_init(void); void timer_80188_init(void); void delay(unsigned MILLISECS); void interrupt far timer_80188_int_handler(void); int N; //--------------------------------------------------------------------------- void main(void) { disable(); // Clear interrupt flag. N = 0; // Number of times interrupt handler has run. ppi_init(); // Initialize parallel ports. int_vect_init(); // Initialize interrupt vector table. enable(); // Set interrupt flag. timer_80188_init(); int_con_init(); // Initialize interrupt controllers. while(TRUE) { // Main program simply waits delay(5000); // for interrupts to occur. } } //--------------------------------------------------------------------------- // Timer Interrupt Service Routine void far interrupt timer_80188_int_handler(void) { if((N++) < 80) { outportb(KEY_PC, 0x20^inportb(KEY_PC)); } else { // Turn 80188 TIMER1 interrupt off outport(TCUCON, 0x0009); } outport(EOI, 0x0008); // Specific End of Interrupt for TIMER1. // Reqired TYPE = 08D for all TIMERS. } //--------------------------------------------------------------------------- void int_vect_init(void) { asm { push ds push bx push ax mov ax, 0 mov ds, ax mov bx, IT_TYPE*4 mov word ptr [bx], offset timer_80188_int_handler mov word ptr [bx+2], seg timer_80188_int_handler pop ax pop bx pop ds } } //--------------------------------------------------------------------------- void timer_80188_init(void) { // Initialize the 80C188XL internal TIMER-COUNTER and INTERRUPT CONTROLLER // for a 2.0 Hz. periodic interrupt. Refer to Chapter 8 and 9 in the // 80C188XL/80C186XL Microprocessor Unsers Manual. outport(T1CON, 0x4009); // Disable TIMER1. outport(T2CON, 0x4009); // Disable TIMER2. outport(T1CNT, 0); // Clear TIMER1 count register. outport(T2CNT, 0); // Clear TIMER2 count register. outport(T2CMPA, 20000); // Set TIMER2 COUNT value time-out // periodically at 4 MHz/20000 = 200 Hz. outport(T1CMPA, 50); // TIMER1 is programmed to generate a // periodic interrupt at 200 Hz/100 = 4 Hz. outport(T1CON, 0xE009); // TIMER1 control word for enabling // interrupt generation and pre-scaling // by TIMER2. outport(T2CON, 0xC001); // TIMER2 control word for continuous counting. } //--------------------------------------------------------------------------- void ppi_init(void) { // Inititialize 8255A KEYBOARD port outportb(KEY_CON, 0x92); // PA as output. } //--------------------------------------------------------------------------- void int_con_init(void) { outport(TCUCON, 0x01); // Set up interrupt controller and // unmask internal timer interrupts with // priority 001. } //--------------------------------------------------------------------------- void delay(unsigned MILLISECS) { int M; while (MILLISECS != 0) { M = 375; while (M != 0) { M--; } MILLISECS--; } }