Pic16F88 delay routine

Thread Starter

Dodgydave

Joined Jun 22, 2012
11,285
I am trying to make a 1sec delay using a pic16f88 with the following>>

int osc set to 8mhz,
so does that mean each instruction cycle takes 1/2 micro-second 2 mhz clock cycles?

so 250 x 250 x 32 =2000000 1/2 micro seconds( 1 second)

and this is my programme

DELAY_1S
movlw .32
movwf t3
more1 movlw .250
movwf t2
more movlw .250
movwf t1
decfsz t1,f
goto $-1
decfsz t2,f
goto more
decfsz t3,f
goto more1
return


will this work or not, or do you have an easier way?:confused:
 

Markd77

Joined Sep 7, 2009
2,806
The instructions don't all take 1 instruction cycle, goto takes two and decfsz takes one or two. Also there are more than one instruction in each loop. That code will take several seconds assuming everything else is right.
You can use trial and error along with the stopwatch in MPLab simulator.
There is also a calculator here:
http://www.golovchenko.org/cgi-bin/delay

If accuracy is critical, don't forget the 4 cycles for the call and return.
 

takao21203

Joined Apr 28, 2012
3,702
messy to adjust and to use.

Better use the timer interrupt for instance to get 1/100 sec. ticks,
and then use counter variable to accumulate timer ticks.

In C this is just a few lines, in assembler, can become lenghty,
if you use different delays. I had clocking distribution systems stretching over 3 pages or so.

Imagine taking care about the cycles each time, and calculate the values!
 

t06afre

Joined May 11, 2009
5,934
I am trying to make a 1sec delay using a pic16f88 with the following>>

int osc set to 8mhz,
so does that mean each instruction cycle takes 1/2 micro-second 2 mhz clock cycles?

so 250 x 250 x 32 =2000000 1/2 micro seconds( 1 second)

and this is my programme

DELAY_1S
movlw .32
movwf t3
more1 movlw .250
movwf t2
more movlw .250
movwf t1
decfsz t1,f
goto $-1
decfsz t2,f
goto more
decfsz t3,f
goto more1
return


will this work or not, or do you have an easier way?:confused:
Here is an example. I also noticed that you are skimping on comments. Not a good practice
Rich (BB code):
    cblock 0x20
Delay1                   ; Define two file registers for the
Delay2                   ; delay loop
     endc
      
     org 0
Start:
     bsf       STATUS,RP0          ; select Register Page 1
     bcf       TRISC,0             ; make IO Pin B.0 an output
     bcf       STATUS,RP0          ; back to Register Page 0
MainLoop:
     bsf       PORTC,0             ; turn on LED C0
OndelayLoop:
     decfsz    Delay1,f            ; Waste time.  
     goto      OndelayLoop         ; The Inner loop takes 3 instructions per loop * 256 loopss = 768 instructions
     decfsz    Delay2,f            ; The outer loop takes and additional 3 instructions per lap * 256 loops
     goto      OndelayLoop         ; (768+3) * 256 = 197376 instructions / 1M instructions per second = 0.197 sec.
                                   ; call it a two-tenths of a second.
      
     bcf       PORTC,0             ; Turn off LED C0
OffDelayLoop:
     decfsz    Delay1,f            ; same delay as above
     goto      OffDelayLoop
     decfsz    Delay2,f
     goto      OffDelayLoop
     goto      MainLoop            ; Do it again...
     end
 

Thread Starter

Dodgydave

Joined Jun 22, 2012
11,285
Here is an example. I also noticed that you are skimping on comments. Not a good practice
Rich (BB code):
    cblock 0x20
Delay1                   ; Define two file registers for the
Delay2                   ; delay loop
     endc
 
     org 0
Start:
     bsf       STATUS,RP0          ; select Register Page 1
     bcf       TRISC,0             ; make IO Pin B.0 an output
     bcf       STATUS,RP0          ; back to Register Page 0
MainLoop:
     bsf       PORTC,0             ; turn on LED C0
OndelayLoop:
     decfsz    Delay1,f            ; Waste time.  
     goto      OndelayLoop         ; The Inner loop takes 3 instructions per loop * 256 loopss = 768 instructions
     decfsz    Delay2,f            ; The outer loop takes and additional 3 instructions per lap * 256 loops
     goto      OndelayLoop         ; (768+3) * 256 = 197376 instructions / 1M instructions per second = 0.197 sec.
                                   ; call it a two-tenths of a second.
 
     bcf       PORTC,0             ; Turn off LED C0
OffDelayLoop:
     decfsz    Delay1,f            ; same delay as above
     goto      OffDelayLoop
     decfsz    Delay2,f
     goto      OffDelayLoop
     goto      MainLoop            ; Do it again...
     end
Thanks for that this helps me, your delay uses 197376 cycles, so would preloading 10 to Delay1 add an extra 30cycles?

So if i pre loaded files "Delay1 & Delay2" with say 10, how many more cycles would it take?

if you can explain how to work it out it would be helpful to me?
 
Last edited:

t06afre

Joined May 11, 2009
5,934
Thanks for that this helps me, your delay uses 197376 cycles, so would preloading 10 to Delay1 add an extra 30cycles?

So if i pre loaded files "Delay1 & Delay2" with say 10, how many more cycles would it take?

if you can explain how to work it out it would be helpful to me?
The example is taken from here http://www.microchip.com/Microchip.WWW.SecureSoftwareList/secsoftwaredownload.aspx?device=en023805&lang=en&ReturnURL=http://www.microchip.com/stellent/idcplg?IdcService=SS_GET_PAGE&nodeId=1406&dDocName=en023805## the Low Pin Count User's Guide. However the best teacher is often your self. And a very useful tool in self teaching is to learn how to do debugging. Like using the MPLAB software simulator single stepping, watches and different types of break points. Take a look at the first post here http://forum.allaboutcircuits.com/showthread.php?t=44852
 

Markd77

Joined Sep 7, 2009
2,806
If you set the inner loop variable to 10 at some point before the loops then instead of counting down from 0 to 0 (it rolls over from 0 to 255 when counting down), it counts down from 10 to 0 so shortens the time by 3X245 cycles. If you set the inner loop variable each time it goes through the outer loop then the reduction gets multiplied by 256 (with some adjustment for the code that changes the counter).
If you want to make it longer try adding a nop to after "OnedelayLoop" or before "decfsz Delay2,f"
The first should make the delay about 33% longer, the second should add 256 cycles.

The first time through the delay could take any time below the normal time because the variables are not initialised.
 

Thread Starter

Dodgydave

Joined Jun 22, 2012
11,285
Can some one help me solve this as i am banging my head ,its just a simple 1hz led flasher on pin RA0,

i have built the asm file, programmed it and put the pic in the circuit board, all that happens is all the pins are at 2v op,with 2.6v ac signal , except the supply pins at 5volts .

Is there some thing in the programme i have done wrong or are my pics faulty?? :mad:

;This is to flash an led on pin ra0 at 1hz



LIST p=16F88 ;tell assembler what chip we are using
#include <P16F88.inc> ;include the defaults for the chip
;set up config register

__CONFIG _CONFIG1, _CP_OFF & _CCP1_RB0 & _DEBUG_OFF & _WRT_PROTECT_OFF & _CPD_OFF & _LVP_OFF & _BODEN_OFF & _MCLR_OFF & _PWRTE_ON & _WDT_OFF & _INTRC_IO
__CONFIG _CONFIG2, _IESO_OFF & _FCMEN_OFF

org 0x0000 ;org sets the origin, 0x0000 for the 16F88,
;this is where the program starts running
goto Loop

cblock 0x20
d1
d2
d3
endc
bsf STATUS, RP0 ;select bank 1
movlw b'01110110' ;set osc to 8mhz
movwf OSCCON
movlw b'11000110' ;set up prescaler to 128 on Tmr0
movwf OPTION_REG

movlw b'00000000' ;set PortA all outputs
movwf TRISA
movlw b'11111111'
movwf TRISB ;set PortB all inputs
bcf STATUS, RP0 ;select bank 0
clrf PORTA ;clear portA
clrf PORTB

Loop
bsf PORTA,0
;set bit 0 on
call Delay
;
bcf PORTA,0
call Delay ;set bit0 off
goto Loop ;go back and do it again
Delay

;delay of 500msec at 8mhz clock
;999997 cycles
movlw 0x08
movwf d1
movlw 0x2F
movwf d2
movlw 0x03
movwf d3
Delay_0
decfsz d1, f
goto $+2
decfsz d2, f
goto $+2
decfsz d3, f
goto Delay_0
;3 cycles
goto $+1
nop

return
end
 

absf

Joined Dec 29, 2010
1,968
Rich (BB code):
LIST p=16F88 ;tell assembler what chip we are using
#include <P16F88.inc> ;include the defaults for the chip
;set up config register 

__CONFIG _CONFIG1, _CP_OFF & _CCP1_RB0 & _DEBUG_OFF & _WRT_PROTECT_OFF & _CPD_OFF & _LVP_OFF & _BODEN_OFF & _MCLR_OFF & _PWRTE_ON & _WDT_OFF & _INTRC_IO
__CONFIG _CONFIG2, _IESO_OFF & _FCMEN_OFF

org 0x0000 ;org sets the origin, 0x0000 for the 16F88,
;this is where the program starts running
goto Loop

cblock 0x20
d1
d2
d3
endc
bsf STATUS, RP0 ;select bank 1
movlw b'01110110' ;set osc to 8mhz
movwf OSCCON
movlw b'11000110' ;set up prescaler to 128 on Tmr0
movwf OPTION_REG

movlw 0x00
movwf ANSEL

movlw b'00000000' ;set PortA all outputs
movwf TRISA
movlw b'11111111'
movwf TRISB ;set PortB all inputs
bcf STATUS, RP0 ;select bank 0
clrf PORTA ;clear portA
clrf PORTB

Loop 
bsf PORTA,0
;set bit 0 on
call Delay
;
bcf PORTA,0
call Delay ;set bit0 off
goto Loop ;go back and do it again
Delay

;delay of 500msec at 8mhz clock 
;999997 cycles
movlw 0x08
movwf d1
movlw 0x2F
movwf d2
movlw 0x03
movwf d3
Delay_0
decfsz d1, f
goto $+2
decfsz d2, f
goto $+2
decfsz d3, f
goto Delay_0
;3 cycles
goto $+1
nop

return
end
Port A is default to analog when pic is started up. Just add the 2 lines in red to initialize them to digital should solve your problem.

Allen
 
Last edited:

Thread Starter

Dodgydave

Joined Jun 22, 2012
11,285
Tried the two lines movlw 0x0
movwf ANSEL

STILL NOT WORKING!
all pins are sat at 2volts

so what else is wrong?

if you have a simple prog that works on the 16f88 to flash an led can you upload it
 

Markd77

Joined Sep 7, 2009
2,806
Still not using the simulator and stopwatch?
Your goto $+2 lines make the delay much shorter than the goto $-2 that you probably intended.

<ed> My mistake, the delay code works fine. </ed>
 
Last edited:
Top