Listing and additional info for DI #2277: The default 80186 Timer Register Address are as follows: Register Name Timer0 Timer1 Timer2 Mode/Control Word FF56H FF5EH FF66H Max Count B FF54H FF5CH NOT PRESENT Max Count A FF52H FF5AH FF62H Count Register FF50H FF58H FF60H The timer control word bits are as follows: Bit 0 Set to 1 for Continous mode running/0 for one shot mode Bit 1 1 for Timer to alternate between Max Count reg A & B, 0 for A only Bit 2 1 to select External Clock for the timer, 0 for Internal i.e. CPU clock/4 Bit 3 If 1, Timer2 output is used as clock, else internal clock(CPU Clock/4) is used Bit 4 if 0 the Input level gates the timer on or off (timer will count for a Hi) Bit 5 This is a read only bit set when the timer reaches its maximum value Bit 11 This bit has to be 0 Bit 12 This read only bit Indicates which Max count Reg is in Use(0 indicates A) Bit 13 If set, interrupts will be generated on every terminal count Bit 14 If 0, Bit 15(Enable/Disable) is ignored, else Bit 15 will take effect Bit 15 If set, the timer is enabled, 0 will stop the timer Note: All bits except bit 5 and 12 are read/write. Bit 5 & 12 are read only. Bits not shown above are don't care */ /* For compiling and linking; the following make batch file is used. libs file contains names of library files which are to be linked. Note that all addresses are system specific. ic86 %1.c link86 %1.obj,& void delay(word count) { word i; for (i=0;i #include /* Starts and stops the counter with Max Reg A in use so that timer1_out is High */ void MakeHi() { outword(0xff5e,0x4004); /* Stop timer 1 */ outword(0xff58,0x0); /* Count = 0 */ outword(0xff5a,0xffff); /* Large Max Count A */ outword(0xff5e,0xc000); /* Start Counter, with int clk, A only, No cont 0xc004 */ outword(0xff5e,0x4004); /* Stop Timer */ } /* Starts the timer with Max Reg A and B alternating, Max Reg A is set for only 1 count and B for a large count. The timer is stopped as soon as Max Reg B is in use so that timer1_out is Lo */ void MakeLo() { outword(0xff5e,0x4003); /* Stop Timer1 */ if ((inword(0xff5e) & 0x1000) != 0x1000) /* If output is now high; ie. A is in use, Make output Lo */ /* Else output already Low; do nothing */ { outword(0xff58,0x0); /* Count = 0 */ outword(0xff5a,0x1); /* Max Count A = 1 */ outword(0xff5c,0xffff);/* Max Count B = Large value */ /* Start Counter, with int clk, Max Reg A&B, not continuous mode */ outword(0xff5e,0xc002); /* Wait till B in use ie. Output goes Low */ while ((inword(0xff5e) & 0x1000) != 0x1000); outword(0xff5e,0x4002); /* Stop Timer */ } } /* Timer0 is kept running with RTG bit = 0 so that the timer is turned on or off depending on whether the Timer0_in is Hi or Lo. This routine tests the state of Timer0_in pin by checking if the timer is incrementing */ byte ReadInput(void) { outword(0xff50,0); /* reset count register */ delay(3); if (inword(0xff50) > 0) /* if counting */ return(1); /* Timer0_in is High */ else return(0); } main() { byte string[300]; byte chr; init_stack(); /* Assembly routine for initialising stack pointer SP and base SS .*/ outword(0xff56,0xc001); /* Start timer0 in continuous mode,RTG=0 */ while (1) { PrintString("Enter Level to be Output(1/0):"); chr = GetChar(); if(chr == '1') { PrintChar('1'); MakeHi(); /* Output Level 1 */ } else { PrintChar('0'); MakeLo(); /* Output Level 0 */ } PrintChar(' '); PrintString("Input Level is = "); if(ReadInput()) PrintChar('1'); else PrintChar('0'); crlf(); } }