Continue to Site

Welcome to our site!

Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

  • Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

help>>>long delay

Status
Not open for further replies.

solidsnike

New Member
hi every body

can any one help me and give me code for delay more than 15 or 30 minutes in assembly language

i'm using pic16f84a
and oscilator 4Mz

and thanks
 
shoow, thats 1uS per command

That makes 1000000 cycles per second

Multply that by 60 to delay a minute = 6000000

Now I could throw alot of numbers around, or, just use **broken link removed**

and it will do it for me. Heres the routine for a 1 minute delay. Call this X times to delay X minutes.

Code:
;PIC Time Delay = 60.0000010 s with Osc = 4.000000 MHz
	movlw	D'2'
	movwf	CounterD
	movlw	D'51'
	movwf	CounterC
	movlw	D'146'
	movwf	CounterB
	movlw	D'18'
	movwf	CounterA
loop	decfsz	CounterA,1
	goto	loop
	decfsz	CounterB,1
	goto	loop
	decfsz	CounterC,1
	goto	loop
	decfsz	CounterD,1
	goto	loop
	retlw
 
I use interrupt routine to count my delay time for my counter, quite accurate and can be very long.
 
I agree, though this method may seem a bit advanced to a beginner.

Use timer based interrupts to derive a 1 second "heart beat" in your ISR and implement one or more count down timers in your ISR where they then become simple background tasks.

Here's a relatively simple and tight ISR count down timer example, 16 instructions in all, that can easily provide a 1 second (00:00:01) to 256 hour (255:59:59) delay;

Code:
;
;  unsigned char Timer [] = { 23, 00, 00 };  // hrs, mins, secs
;
;  if (TimerEnabled)            // if Count Down Timer enabled
;  { n = 2;                     // index seconds array element
;    while (!Timer[n]--)        // while value 00 (post dec value)
;      Timer[n--] = 59;         // set to 59 and bump array index
;    if (!(TimerEnabled = Timer[0]+Timer[1]+Timer[2]))
;    {                          // perform timed out code here
;    }
;  }
;
ISR_TMR
        btfss   TMRENA          ; is TMR turned on?               |B0
        goto    ISR_Next        ; no, branch, else                |B0
        movlw   TMRSEC          ;                                 |B0
        movwf   FSR             ; setup indirect access           |B0
ISR_T0  movf    INDF,W          ; is value 0?                     |B0
        bnz     ISR_T1          ; no, branch, else                |B0
        movlw   h'59'           ;                                 |B0
        movwf   INDF            ; reset to '59'                   |B0
        decf    FSR,f           ; decrement array index           |B0
        goto    ISR_T0          ; test next array element         |B0
ISR_T1  decf    INDF,F          ; post decrement array element    |B0
        movf    TMRHRS,W        ; check for time-out              |B0
        addwf   TMRMIN,W        ;                                 |B0
        addwf   TMRSEC,W        ; timed out (00:00:00)?           |B0
        bnz     ISR_Next        ; no, branch, else                |B0
        bcf     TMRENA          ; turn off timer enabled flag     |B0
                                ; perform timed out code here     |B0
ISR_Next
 
Last edited:
thankx gramo for your help ..... and for your program ...it very good program but when i need delay for one hour ... i need call the delay 60 times that a lot to my code

thankx Mike, K8LH fo help .... but i need to explain to me what is yuor meaning by
Use timer based interrupts to derive a 1 second "heart beat" in your ISR and implement one or more count down timers in your ISR where they then become simple background tasks
 
Thanks for doing this lamer's college work for him! :rolleyes:
 
Homework or not it's still someone asking for it on a plate. They've probably been turned away from other forums before and thereofre have learnt to disguise requests for homework.

Anyway if all I wanted was a timer and I wasn't bothered about accuracy I wouldn't bother programming a PIC, I would use a simple CMOS oscillator/counter IC.
 
Please remember that examples may benefit other Forum members and not just the OP. In this case I felt it was important to build on Bananasiong's comments for an interrupt based solution. I was hoping that providing a simple and elegant partial solution that demonstrates some of the power and capabilities of an ISR might encourage readers who haven't used an ISR yet to do some research.

While it seems the OP is a relative novice and doesn't seem interested in doing much research or studying code examples (on PICLIST or elsewhere) on his own, I would hope that other readers may still benefit from the example I provided.
 
Last edited:
It is very good using interrupt for counter, no matter how, it keeps counting every set interval time.
I've made a dual counter with a PIC and a few 7-segment display, previously I start with a single counter using delay routine, works fine. When come to dual counter, I was going to be crazy, because both counter have to count independently.
I was told to use interrupt early, but just couldn't figure out how to do it, until I faced the problem and found the solution, my job becomes easier a lot.
 
solidsnike said:
thankx gramo for your help ..... I need call the delay 60 times that a lot to my code

You have to learn how to take a raw resource and modify it for your purposes!
No, you do not call a delay sequentially to achieve your desired time. Instead, you make it parameterized.

Code:
No No:
          call minute1
          call minute1
          call minute1
          call minute1
          call minute1
          call minute1
          call minute1
          call minute1
          call minute1
          call minute1

Acceptable:
movlw .10
movwf time_minute
call delay_minute


Acceptable:
movlw .10
call delay_minute2



delay_minute:
dmstart
             do1minutedelay
             decfsz time_minute, f
             goto dm_start
return

delay_minute2:
            movwf time_minute
dmstart2
             do1minutedelay
             decfsz time_minute, f
             goto dm_start2
return


So now take whatever delay routine you like, parameterize it by intializing or importing a timer_variable parameter at the top, and use decfsz time_variable at the bottom. This way the "delaying" is automated.

This type is a blocking delay, nothing else in code takes place except for interrupts and peripherals. If you actually need to be running code during the delay, then its called a timer. Timers will be in the interrupt, better explained, checked for inside an interrupt.
 
Ya, you cannot call the delay for 60 times. Imagine if you want to count for one day or more o_O
decfsz a defined constant is a good choice.
 
i have this code is generated by code generator software .. number of cycles in that code is 300000000 but when i calculated the number of cycles it dosenot much or approximates .... the different is a large can anyone tell me what is the wrong


Code:
Delay = 300 seconds 
; Clock frequency = 4 MHz 

; Actual delay = 300 seconds = 300000000 cycles 
; Error = 0 % 

   cblock 
   d1 
   d2 
   d3 
   d4 
   endc 

         ;299999995 cycles 
   movlw   0x54 
   movwf   d1 
   movlw   0xA1 
   movwf   d2 
   movlw   0xFD 
   movwf   d3 
   movlw   0x02 
   movwf   d4 
Delay_0 
   decfsz   d1, f 
   goto   $+2 
   decfsz   d2, f 
   goto   $+2 
   decfsz   d3, f 
   goto   $+2 
   decfsz   d4, f 
   goto   Delay_0 

         ;5 cycles 
   goto   $+1 
   goto   $+1 
   nop
 
solidsnike said:
i have this code is generated by code generator software .. number of cycles in that code is 300000000 but when i calculated the number of cycles it dosenot much or approximates .... the different is a large can anyone tell me what is the wrong

How did you calculate it?, I suspect you did it wrong!.
 
solidsnike said:
can you caculate it and give me the answer >>

The answers already there - 30 seconds, 0% error - it's a nested loop, and it's quite difficult to work out manually. But assuming it's from the PICList generator?, it's fully accurate as it says.
 
Just use the MPLAB stopwatch function. The routine is 5 usecs short of 300 seconds (the stopwatch recorded 5 usecs to my first breakpoint which was the start of the loop delay code).
 

Attachments

  • stopwatch.PNG
    stopwatch.PNG
    45.6 KB · Views: 136
Mike, some instructions are missing in your simulation?
Code:
         ;5 cycles 
   goto   $+1 
   goto   $+1 
   nop

By the way, the code generated by the Delay Code Generator usually consider the call and the retlw instructions (4 cycles).
 
Yep, you're right. I didn't scroll that code window to pick up those last three instructions. Sorry.

So it seems that code block is exactly 300,000,000 cycles just like the comments say.

I agree that if the delay code is to be used as a subroutine then it should be trimmed to include 4 cycles for the call and return instructions.

Mike
 
Whatever you use, your own code or anything you find anywhere, it can be tested in the simulator inside MPLAB using the "stopwatch" function for an accurate counting of the elapsed time.

Do a favor to yourself and explore it!
 
Status
Not open for further replies.

Latest threads

New Articles From Microcontroller Tips

Back
Top