Searching \ for 'Delay loops' in subject line. ()
Help us get a faster server
FAQ page: www.piclist.com/techref/timers.htm?key=delay
Search entire site for: 'Delay loops'.

Truncated match.
'Delay loops'
2002\08\05@172006 by

Hi,

I am using the following code on a PIC16F877 @ 4MHz:

bsf PORTB, 4
bsf PORTB, 1  ;---------------------
; delay for at least 2ms
movlw 0x95
movwf Dlay
movlw 0x02
movwf Dlay + 1
decfsz Dlay
goto \$ - 1
decfsz Dlay + 1
goto \$ - 3

bcf PORTB, 4 ; --------------------

I intended for 2ms to elapse  between the execution of the dashed lines.
My formula: 1us per instruction
3us per subtraction iteration
2000us / 3us = 667 cycles
667 - 6 (overhead instructions) = 0x295

When I measured this on an oscilloscope, the actual delay came to be 1.2 ms.
If anything, it should be greater than 2 ms because I did not take the extra
cycles that occur each borrow.  Does each subtraction that does not borrow
take 3us to complete? (1us for decfsz, 2us for goto)

Thanks,
-Mike

--

I don't really understand your working, but it looks like you have a bug for a
start. When you do the second iteration of the outer loop, you don't
re-initialise Dlay, so the first decfsz wil decrement to 0xff and it will
count from there. So the timing will be as follows between your ----------
delimiters:

first iteration of inner loop: (0x94 * 3) + 2 + 3
second iteration of inner loop: (0xff * 3) + 2 + 2

total delay: 1218us

So, your oscilloscope appears to be well calibrated.

Just to explain the numbers, all PIC instructions (mid-range at least) take
one instruction cycle (clk/4) except those which result in the program counter
being altered. So, with a 4MHz clock, a decfsz will count 1us if there's no
skip and 2us if the skip happens. A goto will always count 2us.

So, the first iteration will be:
0x94 times (a non-skipping decfsz and a goto = 3us) = 444us
the final skipping decfsz (2us)

Then the decfsz as Dlay1 goes from 2 to 1, then the goto, total 3us
The goto takes us (incorrectly I assume) back to the decfsz, which
decrements the zero-value Dlay to 0xff, so:

0xff times (a non-skipping decfsz and a goto = 3us) = 765us
the final skipping decfsz (2us)

plus the final skipping decfsz as Dlay+1 goes from 1 to zero (2us)

I hope this is clear, it's difficult to spell these things out without going
into btuse details, but if you work through it it should become clear.

There is a useful C routine that someone wrote which can calculate these kind
of delay loops for you - I don't remember where it is offhand but I'm sure
someone on the list could poit us to it.

Cheers,
Simon.
---

On Mon, Aug 05, 2002 at 05:19:50PM -0400, Michael A. Powers wrote:
{Quote hidden}

--

At 05:19 PM 8/5/02 -0400, Michael A. Powers wrote:

>  bsf PORTB, 4
>  bsf PORTB, 1  ;---------------------
>  ; delay for at least 2ms
>  movlw 0x95
>  movwf Dlay
>  movlw 0x02
>  movwf Dlay + 1
>  decfsz Dlay
>   goto \$ - 1
>  decfsz Dlay + 1
>   goto \$ - 3
>
>  bcf PORTB, 4 ; --------------------
>
>When I measured this on an oscilloscope, the actual delay came to be 1.2 ms.
>If anything, it should be greater than 2 ms because I did not take the extra
>cycles that occur each borrow.  Does each subtraction that does not borrow
>take 3us to complete? (1us for decfsz, 2us for goto)

The problem is your last 'goto' - you jump back to 'decfsz Dlay', you
should be jumping back to 'movlw 0x02'.

But - you should be using labels in your code!  This business of 'goto \$-3'
is BAD PROGRAMMING!  What happens when you add 1 extra line of code?

I cheat too - I will sometimes use 'goto \$-1'.  But NO more than 1!

Here is how I think the code should be written:

movlw     0x95
movwf     Dlay
Delay_loop
movlw     0x02
movwf     Dlay + 1
decfsz    Dlay
goto    \$ - 1
decfsz    Dlay + 1
goto    Delay_loop

dwayne

--
Dwayne Reid   <dwaynerplanet.eon.net>
Trinity Electronics Systems Ltd    Edmonton, AB, CANADA
(780) 489-3199 voice          (780) 487-6397 fax

Celebrating 18 years of Engineering Innovation (1984 - 2002)
.-.   .-.   .-.   .-.   .-.   .-.   .-.   .-.   .-.   .-
`-'   `-'   `-'   `-'   `-'   `-'   `-'   `-'   `-'
Do NOT send unsolicited commercial email to this email address.
This message neither grants consent to receive unsolicited
commercial email nor is intended to solicit commercial email.

--

Ok, it's the morning and I re-read your original working and I see where
you're going wrong.

Essentially, there are two problems with the original code:

1. The goto bug
2. The reasoning for coming up with 0x295

The first has been well-explained, but just doing as suggested below is not
enough.

You correctly calculated 3us for the inner loop, then reasoned that you needed
660 or so iterations, ignoring all those twos and threes. Then you converted
this to hex, all ok so far, but then you split the resulting figure into two
bytes and used these for the initial values. This is wrong. The number of
iterations is approximately Dlay * Dlay+1, **not** Dlay*256 + (Dlay+1)

So, the reasoning should be something like Dlay * (Dlay+1) = 660

the same comment about variable names. It doesn't cost anything to use two
variable names and avoid Dlay+1. Here would be my code to give an approximate
2ms using 3x220 to give the 660:

movlw  3
movwf  d1
loop
movlw  220
movwf  d2
decfsz d2,f
goto   \$-1

decfsz d1,f
goto   loop

Note that I put the big number in the inner loop to reduce the error from the
loop termination. Note also the ",f" which will avoid assembler warnings.

As I said in my last post, the best way to do this is to use a template and
something to calculate the values. This way is easier, and gives precise
delays. I will get this and post it later.

Simon.
---

On Mon, Aug 05, 2002 at 08:59:00PM -0600, Dwayne Reid wrote:
{Quote hidden}

--
http://www.piclist.com hint: The list server can filter out subtopics
(like ads or off topics) for you. See http://www.piclist.com/#topics

More... (looser matching)
- Last day of these posts
- In 2002 , 2003 only
- Today
- New search...