Working out delay loops

Thread Starter

vk4tec

Joined Feb 19, 2009
4
Could someone walk me through how to work out a delay loop in assembly ?

I have a 20 MHz rock.

16F628

I understand it is loops inside loops, but how do you work out the values ?

Clock delay ?

Andrew
 

AlexR

Joined Jan 16, 2008
732
High languages such as C or basic make programming much easier but are useless for programing delay loops because you have no control over how the code gets translated into machine language hence no idea of how long any loop will take. To program an accurate delay loops you have to go back to assembler and count machine cycles.

If you are a PIC user there are a couple of tools that do the hard work for you, just plug in the clock frequency and the desired delay and they churn out the assembler code for your delay loops.

An on-line delay loop calculator can be found at http://www.golovchenko.org/cgi-bin/delay.
If you want a stand alone free calculator go to http://www.biltronix.com/picloops.html.
 

mik3

Joined Feb 4, 2008
4,843
For PICs there is the 'delay' function which causes a delay with a duration which depends on a number you put it.

By delay loop doesn't means a delay?
 

AlexR

Joined Jan 16, 2008
732
For PICs there is the 'delay' function which causes a delay with a duration which depends on a number you put it.

By delay loop doesn't means a delay?
By delay loop definitely does mean a delay in the program. What else could it mean??

There is no in delay function built into the PIC. Various C and basic compilers do have built-in delay functions (written in assembler) but there are still situations (even using C) when you have to write your own assembler delay loops. For example if you have a program that uses interrupts, you can't use the C delay function in the interrupt routine if it is also used in the main body of the program. In this case you would write an in-line assembler loop to do the delay in the interrupt function.
 

n9352527

Joined Oct 14, 2005
1,198
Code the loops, put in arbitrary values and simulate it with MPSIM. Display the Stopwatch window, go to the entry point of the loop, reset the watch and put a debug point at the exit point of the loop. Run. There you go, you will have the delay time, no calculation! Adjust the loop values to get the time you want.
 

jpanhalt

Joined Jan 18, 2008
11,087
Here's another calculator. Just plug in your values and it generates assembly code. I have found it to be fairly accurate. You may need to trim it a little to account for other delays (e.g., call's) in your program, if accuracy is absolutely critical.

John
 

AlexR

Joined Jan 16, 2008
732
Alberto:
I'm not doubting the accuracy of the delays in your basic compiler but using any function (including delay functions) in both the interrupt routine and in the main program is asking for trouble.

Just think your way through what happens when an interrupt occurs.

The PIC pushes the program counter onto the stack and loads the program counter with the interrupt vector.

As part of the interrupt routine your compiler will then save the contents of the STATUS register and the W register into temporary memory locations (for PIC16s, PIC18s do it automatically as part of the interrupt)

You do whatever you have to do in interrupt service routine, the compiler restores the STATUS and W registers and issues a return command which causes the PIC to pull the program counter off the stack and you carry on from where you left off. All very nice.

Now consider what happens if you are in a delay routine in the main program when an interrupt occurs that also calls a delay routine in the ISR.

Unless its a very short delay there are going to to be nested delay loops and the number of times the loops are to be executed will be held in memory locations.

You call the delay routine, it saves the parameters in memory and starts executing the delay loop, part way through you get an interrupt.

The PIC pushes the PC on the stack and you save the STATUS and W registers. That is all that gets saved!

You go to the ISR and it calls the delay routine. Now the delay routine will over-write the values that were being used by the same delay routine in the main program.

You finish doing whatever needed to be done in the IRS and return from interrupt restoring the STATUS and W registers and the program counter. Everything would seen to be fine but your interrupt routine has altered the values that your delay routine was using so your timing will be wrong.

This sort of problem is not limited to delays and can occur with any routine/function that is used in both the main body of the program and the interrupt service routine.
 
Last edited:

AlexR

Joined Jan 16, 2008
732
Alberto:
I think we are talking at cross purposes here and we actually agree. You seem to have missed the last part of the sentence in your quote and objection to what I said.
What I said was:
For example if you have a program that uses interrupts, you can't use the C delay function in the interrupt routine if it is also used in the main body of the program.
With emphasis on "if it is also used in the main body of the program".
The point I was making was that if you need delays in both the main program and the ISR then you should write an assembler delay loop for one of them so they don't clash.
 
Top