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.

PIC Delay calculator

Status
Not open for further replies.
And both are mentioned lots of times all over these forums! :D

The PICList one was around years before the EXE file one, and is the one I've always used (as mentioned in my tutorials).
 
PICloops is very good also.

**broken link removed**

I use it and is really simple.

To be installed in your PC.
 
You could also use a generic Delay subroutine and macro "front end" system that allows you to specify delays in cycles, microseconds, or milliseconds independent of Clock frequency.

The 12 word 16 bit delay subroutine and macro "front ends" below can provide delays of 16..262159 cycles. And using the DelayCy() macro along with the msecs and usecs multipliers in the operand are especially handy for specifying delays plus or minus some number of cycles for precise isochronous timing.

Food for thought. Regards, Mike

Code:
;******************************************************************
;                                                                 *
;  DelayMS(), DelayUS(), DelayCy()    Mike McLaren, K8LH, Jun'07  *
;                                                                 *
;  a small 16-bit delay subroutine with macro "front ends" which  *
;  allow you to specify delays in msecs, usecs, or cycles.        *
;                                                                 *
;  requires the use of constant operands known at assembly time!  *
;                                                                 *
;  each delay macro call generates 4 instructions (for delays in  *
;  the ranges shown below).  longer delays up to several seconds  *
;  are possible but the macro produces 4 additional instructions  *
;  for every 262016 cycles in the delay.                          *
;                                                                 *
;     4 MHz, 1 cycles/usec, 16..262144 usecs, 1..262 msecs        *
;     8 MHz, 2 cycles/usec,  8..131072 usecs, 1..131 msecs        *
;    12 MHz, 3 cycles/usec,  6...87381 usecs, 1...87 msecs        *
;    16 MHz, 4 cycles/usec,  4...65536 usecs, 1...65 msecs        *
;    20 MHz, 5 cycles/usec,  4...52428 usecs, 1...52 msecs        *
;                                                                 *
;  here are some of the ways to generate a 1 millisecond delay;   *                                                               *
;                                                                 *
;       DelayMS(1)              ; delay 1 msec                    *
;       DelayUS(1000)           ; delay 1 msec                    *
;       DelayCy(1*msecs-2)      ; delay 1 msec minus 2 cycles     *
;       DelayCy(1000*usecs)     ; delay 1 msec                    *
;                                                                 *
;  use the DelayCy macro with the 'msecs' or 'usecs' multipliers  *
;  in the operand plus or minus some number of cycles to produce  *
;  precise clock independent isochronous timing.                  *
;                                                                 *
;******************************************************************
        radix   dec

clock   equ     8               ; user clock frequency in MHz
;
;  DelayCy() operand multipliers
;
usecs   equ     clock/4         ; cycles/microsecond multiplier
msecs   equ     usecs*1000      ; cycles/millisecond multiplier
;                                                                 *
;  DelayMS(), DelayUS(), and DelayCy() macros                     *
;                                                                 *
DelayMS macro   pDelay          ; milliseconds
        DelayCy(pDelay*msecs)   ; convert to cycles
        endm                    ;

DelayUS macro   pDelay          ; microseconds
        DelayCy(pDelay*usecs)   ; convert to cycles
        endm

DelayCy macro   pDelay          ; cycles (Tcy), minimum 16
        local   cycles
        cycles = pDelay
     while cycles > 262032
        movlw   high((262016-16)/4)+1
        movwf   TMRH
        movlw   low((262016-16)/4)
        call    DelayLo-(262016%4)
        cycles -= 262016
     endw
        movlw   high((cycles-16)/4)+1
        movwf   TMRH
        movlw   low ((cycles-16)/4)
        call    DelayLo-(cycles%4)
        endm
;                                                                 *
;  example code for simulation testing;                           *
;                                                                 *
SimTest DelayCy(20*msecs)       ; remember to set 'clock' equate
        nop                     ; put simulator break point here
;                                                                 *
;******************************************************************
;                                                                 *
;  Delay(16..262159 Tcy) subroutine   Mike McLaren, K8LH, Jun'07  *
;                                                                 *
;  12 words, 1 RAM variable, 14-bit core                          *
;                                                                 *
Delay.16
        nop                     ; entry point for delay%4 == 3    |B0
        nop                     ; entry point for delay%4 == 2    |B0
        nop                     ; entry point for delay%4 == 1    |B0
DelayLo addlw   -1              ; subtract 4 cycle loop time      |B0
        skpnc                   ; borrow?  yes, skip, else        |B0
        goto    DelayLo         ; do another loop                 |B0
        nop                     ;                                 |B0
DelayHi addlw   -1              ; subtract 4 cycle loop time      |B0
        decfsz  TMRH,F          ; done?  yes, skip, else          |B0
        goto    DelayLo         ; do another loop                 |B0
        goto    $+1             ; burn off 2 cycles               |B0
        return                  ;
;                                                                 *
;******************************************************************
Here's an isochronous timing example. The first example uses the DelayMS() macro to generate a 1 msec delay for toggling the speaker pin. It doesn't take into account the 6 instruction cycles in the loop and will generate a slightly different tone for each Clock frequency. The second example uses the DelayCy() macro and the usecs or msecs multiplier in the operand and subtracts the 6 instruction cycles in the loop. The second example generates a precise 500 Hz tone no matter what Clock frequency you're using.

Code:
;
;  key press beep
;
;  497.018 Hz --  4 MHz clock
;  498.504 Hz --  8 MHz clock
;  499.004 Hz -- 12 MHz clock
;  499.251 Hz -- 16 MHz clock
;  499.400 Hz -- 20 MHz clock
;
        bsf     Beep,5          ; do 32 msec switch press beep    |B0
DoBeep  movf    PORTA,W         ; read port A                     |B0
        xorlw   1<<Spkr         ; toggle speaker bit              |B0
        movwf   PORTA           ; toggle speaker pin              |B0
        DelayMS(1)              ; delay 1 msec for 500 Hz tone    |B0
        decfsz  Beep,F          ; done?  yes, skip, else          |B0
        goto    DoBeep          ; loop (toggle Spkr pin again)    |B0
Code:
;
;  key press beep
;
;  exact 500 Hz tone (any Clock frequency)
;
        bsf     Beep,5          ; do 32 msec switch press beep    |B0
DoBeep  movf    PORTA,W         ; read port A                     |B0
        xorlw   1<<Spkr         ; toggle speaker bit              |B0
        movwf   PORTA           ; toggle speaker pin              |B0
        DelayCy(1*msecs-6)      ; delay 1 msec minus 6 cycles     |B0
        decfsz  Beep,F          ; done?  yes, skip, else          |B0
        goto    DoBeep          ; loop (toggle Spkr pin again)    |B0
 
Last edited:
atferrari said:
PICloops is very good also.

**broken link removed**

I use it and is really simple.

To be installed in your PC.


Thanks atferrari, too bad I don't have a pc LOL.:D

Thanks Mike for the code.

For whoever wants to know, I have most of my code down(For a clock), the next step is adding up all the instruction cycles and make a delay that is 60000000 cycles minus the total code cycles.

I don't want my clock to be even a milisecond off every hour:p .
 
wmmullaney said:
Thanks atferrari, too bad I don't have a pc LOL.:D

Thanks Mike for the code.

For whoever wants to know, I have most of my code down(For a clock), the next step is adding up all the instruction cycles and make a delay that is 60000000 cycles minus the total code cycles.

I don't want my clock to be even a milisecond off every hour:p .

I fear you are going to be GREATLY disappointed, your technique isn't likely to produce an accurate clock, and is going to be difficult to write as you have to ensure that ALL possible branches during the program take EXACTLY the same time.

It's not impossible, and it has been done, but it's not the way to do it!.

The far better way is to use timer2 to generate regular interrupts (tmr2 because it has many advantages over the others), and your interrupt routine increments registers and does the clock counting.
 
alright, well it'll be accurate enough, off what, a minute a year?

Just a few more questions, first, for a clock, is it ok to leave the PIC running for days? or weeks?

Second, if the pic will run off of 3v, can I connect hight brightness blue leds directly to the pic?

What is tmr2?

I'm not very good with interrupts. Does anyone know of a good site that teaches you how to write the config word?
 
wmmullaney said:
alright, well it'll be accurate enough, off what, a minute a year?

I doubt you would get anywhere near that accuracy?.

Just a few more questions, first, for a clock, is it ok to leave the PIC running for days? or weeks?

Yes, in many applications PIC's run 24 hours a day permanently.

Second, if the pic will run off of 3v, can I connect hight brightness blue leds directly to the pic?

No, you should ALWAYS use current limiting of some kind.

What is tmr2?

One of the three timer modules in most PIC's, it's useful because you can set it easily to give accurate repeatable interrupts.

I'm not very good with interrupts. Does anyone know of a good site that teaches you how to write the config word?

I don't see what the config word has to do with interrupts?, but the datasheet shows all the options, for 16 series PIC's it's pretty simple.
 
wmmullaney said:
Thanks Nigel.

I didn't mean to run the two together.

How accurate do you think it will be?

Depends how accurately you write the code, like I said you've got to ensure that every single program branch throughout the entire program gets EXACTLY the same amount of time (this isn't easy - a LOT, LOT harder than an interrupt driven one).

Here's some code I was playing with a year or two back, runs on a 16F876 at 20MHz.
 

Attachments

  • Tmr2_4a.asm
    20.8 KB · Views: 472
I'm just going to use the code I'v got.

I read the datasheet. How do I do a config word? Is it done in hex? Can it be done in binary?

What resistor value do you suggest as a current limiting resistor for high brightness blue leds with a pic running at 5v?
 
wmmullaney said:
I'm just going to use the code I'v got.

I read the datasheet. How do I do a config word? Is it done in hex? Can it be done in binary?

Check any PIC code examples (like mine above), you can set it in hex (as I do), in binary, or (as many do) using long text strings full of AND'd from the include files.

What resistor value do you suggest as a current limiting resistor for high brightness blue leds with a pic running at 5v?

Use ohms law subtract the voltage drop of the LED from 5V to get the voltage, and decide what current you want, then apply ohms law to get the resistor.

But it depends if you're multiplexing or not?.
 
I'm not sure the voltage drop of the led, will 350 ohms be okay?

Here's my clock code, how does it look?

Code:
	;********************
	; Written by,       *
	; William Mullaney  *
	; On                *
	; January 14, 2008  *
	;                   *
	; Binary Clock      *
	; PIC16F628A        *
	;********************
	
	LIST	p=16F628A
	include "p16f628a"
	__config 0x2118
	
	HOUR equ 20h
	MIN  equ 21h
	R1   equ 22h
	R2   equ 23h
	R3   equ 24h
	
	MOVLW    07h
	MOVWF    CMCON
	BSF      STATUS,	RP0
	MOVLW    b'11111111'
	MOVWF    TRISA
	MOVWF    TRISB
	BCF      STATUS,	RP0
	
SHR BTFSS    PORTB,     08h
	GOTO     SHR
	MOVF     PORTA,     HOUR
	
SMN BTFSS    PORTA,		08h
	GOTO	 SMN
	MOVF	 PORTB,		MIN
	
CHK	BTFSC	 PORTA,		08h
	GOTO	 CHK
	
	BSF		 STATUS,	RP0
	MOVLW	 b'00000000'
	MOVWF	 TRISA
	MOVWF	 TRISB
	BCF		 STATUS,	RP0
	
CLK CALL	 DLY
	INCF	 MIN,		1
	MOVF	 MIN,		W
	BCF		 STATUS,	C
	MOVLW	 C3h
	BTFSS	 STATUS,	C
	GOTO	 PRT
	CLRF	 MIN
	INCF	 HOUR,		1
	MOVF	 HOUR,		W
	BCF		 STATUS,	C
	MOVLW	 F3h
	BTFSS	 STATUS,	C
	CLRF	 HOUR
	INCF	 HOUR,		1
	
PRT MOVF	 HOUR,		PORTA
	MOVF	 MIN,		PORTB
	GOTO	 CLK
	
DLY CBLOCK
	R1
	R2
	R3
	ENDC
	
	MOVLW	 22h
	MOVWF	 R1
	MOVLW	 CBh
	MOVWF	 R2
	MOVLW	 83h
	MOVWF	 R3
	
DY0	DECFSZ	 R1,		F
	GOTO	 $+2
	DECFSZ	 R2,		F
	GOTO	 $+2
	DECFSZ	 R3,		F
	GOTO	 DY0
	RETURN

sorry it looks bad, something with my text editor.
 
wmmullaney said:
I'm not sure the voltage drop of the led, will 350 ohms be okay?

Here's my clock code, how does it look?

Code:
	;********************
	; Written by,       *
	; William Mullaney  *
	; On                *
	; January 14, 2008  *
	;                   *
	; Binary Clock      *
	; PIC16F628A        *
	;********************
	
	LIST	p=16F628A
	include "p16f628a"
	__config 0x2118
	
	HOUR equ 20h
	MIN  equ 21h
	R1   equ 22h
	R2   equ 23h
	R3   equ 24h
	
	MOVLW    07h
	MOVWF    CMCON
	BSF      STATUS,	RP0
	MOVLW    b'11111111'
	MOVWF    TRISA
	MOVWF    TRISB
	BCF      STATUS,	RP0
	
SHR BTFSS    PORTB,     08h
	GOTO     SHR
	MOVF     PORTA,     HOUR
	
SMN BTFSS    PORTA,		08h
	GOTO	 SMN
	MOVF	 PORTB,		MIN
	
CHK	BTFSC	 PORTA,		08h
	GOTO	 CHK
	
	BSF		 STATUS,	RP0
	MOVLW	 b'00000000'
	MOVWF	 TRISA
	MOVWF	 TRISB
	BCF		 STATUS,	RP0
	
CLK CALL	 DLY
	INCF	 MIN,		1
	MOVF	 MIN,		W
	BCF		 STATUS,	C
	MOVLW	 C3h
	BTFSS	 STATUS,	C
	GOTO	 PRT
	CLRF	 MIN
	INCF	 HOUR,		1
	MOVF	 HOUR,		W
	BCF		 STATUS,	C
	MOVLW	 F3h
	BTFSS	 STATUS,	C
        GOTO PRINT
	CLRF	 HOUR
	INCF	 HOUR,		1
	
PRT MOVF	 HOUR,		PORTA
	MOVF	 MIN,		PORTB
	GOTO	 CLK
	
DLY CBLOCK
	R1
	R2
	R3
	ENDC
	
	MOVLW	 22h
	MOVWF	 R1
	MOVLW	 CBh
	MOVWF	 R2
	MOVLW	 83h
	MOVWF	 R3
	
DY0	DECFSZ	 R1,		F
	GOTO	 $+2
	DECFSZ	 R2,		F
	GOTO	 $+2
	DECFSZ	 R3,		F
	GOTO	 DY0
	RETURN

sorry it looks bad, something with my text editor.


Fixed a bug.
 
Here is a little program that will calculate the settings (prescale, postscale and PR2) for TMR2 to generate interrupts for whatever time interval you want. If it can generate settings for exactly what you want, it shows all the ways that can be achieved. If there are no settings to get exactly what you want it shows the closest values (one greater and one less than what you want).

You run it as:

TMR2 n

where n is the timer interval you want in instruction cycles.

examples:

Code:
C:>TMR2 10000
10000 Prescaler 1:16 Postscaler 1:5  PR2 124
10000 Prescaler 1:4  Postscaler 1:10 PR2 249

C:>TMR2 1234
 1233 Prescaler 1:1  Postscaler 1:9  PR2 136
 1235 Prescaler 1:1  Postscaler 1:13 PR2  94


The maximum value for n is 65536


---updated with program that doesn't require the C-runtime DLL---

Mike
 

Attachments

  • TMR2.zip
    65.5 KB · Views: 297
Last edited:
Status
Not open for further replies.

Latest threads

New Articles From Microcontroller Tips

Back
Top