//--------------------------------------------------------------- // EXAMPLE EX19.C : Demonstrate use of an 80188 TIMER INTERRUPT. // // C.P. Diduch, Dec 1999. //--------------------------------------------------------------- #define KEY_PA 0x138 // 82C55A port addresses for PA, #define KEY_PB 0x13A // PB, #define KEY_PC 0x13C // PC and the #define KEY_CON 0x13E // Control Register. #define TRUE 1 #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 max count register. #define T2CMPA 0xFF62 // 80C188 TIMER2 max count register. #define I_TYPE 18 // 80C188 Interrupt TYPE for TIMER1. #define TCUCON 0xFF32 // 80C188 Control reg addr for TIMERS. #define EOI 0xFF22 // 80C188 End of interrupt register. #include // Prototypes for enable(), disable(). #include // conio.h contains prototypes for // inportb() and outportb(). void delay(unsigned MILLISECS); void int_vect_init(void); void timer_init(void); void interrupt isr_0(void); //--------------------------------------------------------------- unsigned N; // N is a global variable! void main() { unsigned X; outportb(KEY_CON, 0x82); // Initialize 82C55A PPI with ports // KEY_PC and KEY_PA as OP ports and // port PB as an IP port. N = 0; disable(); // Clear 80C188 interrupt flag' int_vect_init(); timer_init(); enable(); // 'Set 80C188 interrupt flag' while (TRUE) { delay(10000); } } //--------------------------------------------------------------- void int_vect_init(void) { // Initialize interrupt vector table // entry for an interrupt type = I_YPE. asm { push ax push bx push ds mov ax, 0 mov ds, ax mov bx, I_TYPE*4 mov word ptr[bx], offset isr_0 mov word ptr[bx+2], seg isr_0 pop ds pop bx pop ax } } //--------------------------------------------------------------- // Timer Interrupt Service Routine void interrupt isr_0(void) { if (N < 10) { outportb(KEY_PC, 0x80^inportb(KEY_PC)); N = N + 1; } else { outport(TCUCON, 0x0008); // 'Mask off timer interrupts by } // setting bit-3 in TCUCON' outport(EOI, 0x0008); // 'End of interrupt command' } //--------------------------------------------------------------- void timer_init(void) { // Initialize the 80C188XL TIMER-COUNTER UNIT and INTERRUPT // CONTROLLER for a 1.0 second Periodic Interrupt. outport(T2CNT,0); // 'Clear TIMER2 count register' outport(T1CNT,0); // 'Clear TIMER1 count register' outport(T2CMPA,40000); // 'Set TIMER2 COUNT value for a // freq = 4 MHz / 40000 = 100 Hz' outport(T1CMPA,100); // 'Set TIMER1 count value for a // freq = 100 Hz / 100 = 1.0 Hz' outport(T2CON,0xC001); // 'TIMER2 control word for // continuous counting' outport(T1CON,0xE009); // 'TIMER1 control word to enable // interrupt generation and // pre-scaling by TIMER2' outport(TCUCON, 0); // 'Set up interrupt controller // and unmask internal timer // interrupts' //--------------------------------------------------------------- void delay(unsigned MILLISECS) { // Implements a software delay. unsigned M; while (MILLISECS != 0) { M = 320; while (M != 0) { M--; } MILLISECS--; } }