I have devised a routine to run on a 20-MHz PIC that gives you EXACT 1 us increments from 1 us to 65.535 ms. In the application there was some idle time during which the constants were calculated (admittedly, it took another 2us or so). The nice thing is that routine exits with one instruction spare before the time duration is over, so you can use this to perform output/input instructions as required. (It's the NOP at the end of the routine). In short, it's a 16-bit UP-counter which terminates when the count 0x0000 is reached. If you need 2 iterations, you put 0xFFFE in the counter. It will count to 0xFFFF, and then 0x0000, and then exit. The list output of the code is given below. (Because I had to duplicate the code several times I didn't use a label as a loop reference - so shoot me !) Regarding adapting it automatically for the clock speed, you are looking for trouble if you want the PIC to multiply/divide the value in W to adapt to the clock frequency. Assuming you know the clock speed at compile time I suggest you write some MACROs that take a DELAY value in msec, then convert it to a constant suitable for the delay routine. E.g., 00000010 00007 delay1LSB equ 0x10 00000011 00008 delay1MSB equ 0x11 00009 00000004 00010 CLOCK_FREQUENCY equ d'4' ; for 4MHz 00011 00012 mydelay MACRO MSEC_DELAY 00013 LOCAL NUMBER 00014 NUMBER set MSEC_DELAY * d'1000' * CLOCK_FREQUENCY / d'20' 00015 movlw HIGH NUMBER 00016 movwf delay1MSB 00017 movlw LOW NUMBER 00018 movwf delay1LSB 00019 ENDM 00020 0000 00021 org 0x0 00022 mydelay d'83' 0000 M LOCAL NUMBER 000040D8 M NUMBER set d'83' * d'1000' * CLOCK_FREQUENCY / d'20' 0000 0C40 M movlw HIGH NUMBER 0001 0031 M movwf delay1MSB 0002 0CD8 M movlw LOW NUMBER 0003 0030 M movwf delay1LSB 00023 ;+--------------------------------------------+ 0004 0270 00024 comf delay1LSB,f ;| The actual constant is modified so that | 0005 0271 00025 comf delay1MSB,f ;| it can be used in a loop that counts UP. | 0006 03F0 00026 incfsz delay1LSB,f ;| (UP count loops execute faster) | 0007 00F1 00027 decf delay1MSB,f ;| | 0008 02B1 00028 incf delay1MSB,f ;| | 00029 ;+--------------------------------------------+ 00030 ; +-----------------------------------------------------------------------+ 00031 ; | DELAY delay LOOP | 00032 ; +-----------------------------------------------------------------------+ 00033 ;+--------------------------------------------+ 0009 03F0 00034 incfsz delay1LSB,f ;| The LSB is always incremented. When it | 000A 00F1 00035 decf delay1MSB,f ;| reaches 0x00, the counter-decrement for | 000B 03F1 00036 incfsz delay1MSB,f ;| the MSB is skipped so that the MSB is | 000C 0A09 00037 goto $-3 ;| incremented. When the MSB becomes zero, | 000D 0000 00038 nop ;| the loop exists | 00039 ;+--------------------------------------------+ 00040 end If you need any more explanation, mail me. At 07:28 PM 12/17/96 +0000, you wrote: >Does anyone know any good delay routines for the 16c84 and 16c74? >I want to be able to enter a value for the clock speed (usually 4MHz, 10MHz >and 20MHz) and the routine will adapt to the speed. It must function as a >subroutine taking the value in the w register as a delay in mS and then >delay that amount of time. > >Any help on this subject would be most appreciated. > >Have a happy Christmas > Tim > > Jan van der Watt [i SAW Elvis. He sAt BETween mE anD BigFOOt on THE uFo.]