This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

How could I make a adjustable delay function in "micro-second" level

Hello Every :

I use AT89C52 and 11.059MHz oscillator.
1 instuction takes about 1 micro-second.(10^-6 sec.)

I write a delay function in *.asm.

It works well , but I want it adjustable.
I want to delay according to the parameter I pass.My goal is to modify delay time for some protocol time slot testing.

I found it some how difficult to achieve.
Because the basic instruction , for example : _nop_ , take 1 micro-second.
I can't add more decision. It will takes more time.

How could I implement such kind of delay?
Please give me a hand , thanks a lot~~

Parents Reply Children
  • Just for grins, I created the following assembler file using MPL macros:

    NAME	NOPS
    
    ?PR?NOPS?NOPS	SEGMENT CODE
    	RSEG	?PR?NOPS?NOPS
    
    %DEFINE (GenNops) (
    %SET (cnt, 200)
    
    %WHILE (%cnt GT 0) (
      %SET(b_ones,(%cnt / 1) mod 10)
      %SET(b_tens,(%cnt / 10) mod 10)
      %SET(b_huns,(%cnt / 100) mod 10)
    PUBLIC	NOPS_%substr(%b_huns,2,1)%substr(%b_tens,2,1)%substr(%b_ones,2,1)
    NOPS_%substr(%b_huns,2,1)%substr(%b_tens,2,1)%substr(%b_ones,2,1):	nop
      %SET (cnt, %cnt - 1)
      )
    )
    
    %GenNops
    
    	RET
    	END
    

    When youassemble this file, you'll get something like the following:

                          19     PUBLIC  NOPS_200
    0000 00               20     NOPS_200:       nop
                          21
                          22     PUBLIC  NOPS_199
    0001 00               23     NOPS_199:       nop
                          24
                          25     PUBLIC  NOPS_198
    0002 00               26     NOPS_198:       nop
                          27
                          28     PUBLIC  NOPS_197
    0003 00               29     NOPS_197:       nop
    .
    .
    .
                         613     PUBLIC  NOPS_002
    00C6 00              614     NOPS_002:       nop
                         615
                         616     PUBLIC  NOPS_001
    00C7 00              617     NOPS_001:       nop
                         618
                         619
                         620
    00C8 22              621             RET
    
    

    The assembler file is simply a table of NOP instructions with a public label for each. You can control how many are generated with the %SET (cnt, 200).

    The only overhead for calling a "function" in this table is the time it takes to execute the CALL and RET instructions.

    The following shows how to delay for 10 NOPs (plus the CALL and RET).

    extern void NOPS_010 (void);
    
    void main (void)
    {
    while (1)
      {
      NOPS_010 ();
      }
    }
    

    An improvement which could be made to this is to change the labels so that there was no 0 prefix for numbers less than 100.

    Jon

  • Thank You all , I learned a lot from you all.

    But Jon , Maybe you just solved half of my question.
    All of You did give me some great solution of how to delay in micro-second level.
    But , I still can't decide "delay count" in run time.
    Your method is calling certain non-parametered sub-routine in the program.
    For example , if I want to delay 10 uS , I could call NOPS_010 (),and 20 uS ,call NOPS_020().
    This is great when implementing any protocol.
    But , if I want to adjust Signal time slot (protocol) in run time.
    I want to input "delay count" to decide how long to delay.
    I tried the method in this article :
    http://www.keil.com/forum/docs/thread2938.asp (the one Graham Cole wrote).
    And I declare a variable for storing "delay count".
    Then , I could just change "delay count" by passing different parameter.
    Or I can call the major function that includes "delay function".

    This method seems doesn't work.
    Because when I call by constant (ex:NOPS(10)), it almost meet my require.But when I call by variable (ex:NOPS(delay_count) where delay_count = 10)
    it has serious overhead . It delays about (delay_count + 20~30) uS.

    Are there any more solutions ?
    Anyway , thank you all. I did learn a lot.

  • "when I call by constant (ex:NOPS(10)), it almost meet my require.But when I call by variable (ex:NOPS(delay_count) where delay_count = 10) it has serious overhead ."

    See my post dated 11/17/03 15:26:56 in the thread I cited earlier:
    http://www.keil.com/forum/docs/thread2938.asp
    It specifically describes a way to cope with this overhead!

  • That MACRO was originally written by me in the following thread:

    http://www.keil.com/forum/docs/thread1940.asp

    There, I made the following important note:

    NOTE: Do not use variables with this macro. Use constants only. Using a variable causes actual code to be generated for each ternary operator. Using constants causes the ternary operator to be evaluated by the preprocessor (which is what we want).

    Jon

  • OK - So, I used standard macros to create the same thing...

    NAME	NOPS
    
    ?PR?NOPS?NOPS	SEGMENT CODE
    	RSEG	?PR?NOPS?NOPS
    
    NUMNOPS	EQU	200
    
    MakeNOP MACRO X
    	PUBLIC	NOPS_&X
    	NOPS_&X:	NOP
    	ENDM
    
    NOP_LIST:
    REPT	NUMNOPS
    	MakeNOP %(NUMNOPS - ($ - NOP_LIST))
    	ENDM
    
    	RET
    	END
    

    Jon