long variable time delay with 8bit PIC

Discussion in 'Embedded Systems and Microcontrollers' started by blackmamba, Jan 11, 2010.

  1. blackmamba

    Thread Starter New Member

    Dec 4, 2009
    16
    0
    Thanks you all for your help.

    Is it possible to create a function that allows me to do variable time delay of up to 8333us using just an 8bit PIC (12f683)?

    I need that much precision and I am not sure how to go about doing this. I am programming in C. Assembly implementations would also work since I can use asm.... to indicate assembly code to compiler.

    I hope it isnt too obvious:). I cant quite figure it out.
     
    Last edited: Jan 11, 2010
  2. retched

    AAC Fanatic!

    Dec 5, 2009
    5,201
    312
    you can do a "if then loop" of NOPs. What kind of clock are you running? Crystal or onboard? and what is the speed?

    You can figure the number of instructions per second then the number of instructions for your delay. I believe there is also a command: sleep(.08333) that will help. (depending on your compiler) you may need stdio.h
     
  3. SgtWookie

    Expert

    Jul 17, 2007
    22,182
    1,728
    Made using PicLoops:
    Code ( (Unknown Language)):
    1. ;PIC Time Delay = 0.00833300 s with Osc = 4000000 Hz
    2.         movlw   D'11'
    3.         movwf   CounterB
    4.         movlw   D'208'
    5.         movwf   CounterA
    6. loop        decfsz  CounterA,1
    7.         goto    loop
    8.         decfsz  CounterB,1
    9.         goto    loop
    10.         retlw   0
    Free utility download here:
    http://biltronix.com/picloops.html
     
  4. Tahmid

    Active Member

    Jul 2, 2008
    344
    25
    Hi,
    Yup you can do it, using assembly, like the code Sgt Wookie provided.
    You can also use the TMR1 module as it can count upto 65536 us. Load TMR1 with 57203 and wait for it to overflow from 0xFFFF to 0.
    You can also use TMR0 by using prescaler. If you have prescaler of 32, TMR0 will count upto 0xFF (255) from 0 and overflow to 0 every 8192 microseconds.
    Or, if you set prescaler to 64, and load 124 to TMR0, it will count from 124 to 256 and overflow to 0 every 8384 microseconds. After overflow you need to reload TMR0.
    Or simply use an assembly language delay routine:
    Code ( (Unknown Language)):
    1. ; Delay 8 333 machine cycles
    2. ; Duration of the delay 8333 microsecond
    3. ; Frequency of the pulsing oscillator 4 MHZ
    4.  
    5.             movlw       .209
    6.             movwf       Reg_1
    7.             movlw       .11
    8.             movwf       Reg_2
    9.             decfsz      Reg_1,F
    10.             goto        $-1
    11.             decfsz      Reg_2,F
    12.             goto        $-3
    13.             nop
    Code generated from software: PIC_Delay v1.7
     
  5. chat_eur

    New Member

    Dec 30, 2009
    7
    0
  6. blackmamba

    Thread Starter New Member

    Dec 4, 2009
    16
    0
    Thank you all for the help. Really appreciate it.
    However, what if the delay value is a variable determined by the program?
    Basically what I am needing is a program that can delay in int multiples of a variable number.
    So say :
    Code ( (Unknown Language)):
    1. int time_us;  //time_us is generated by the program
    2.            multiple=10;  //for total delay of (10*time_us)
    How can I use your solutions which are pretty much similar to do this?
     
    Last edited: Jan 12, 2010
  7. chat_eur

    New Member

    Dec 30, 2009
    7
    0
    [SIZE=-1]if assembly is ok for you, use something on below. Before calling delay1s routine, use
    movlw x
    instruction to multiply the overall delay with x. This will load x to the first counter. You can find this detailed on the bottom of this page : http://www.microautomate.com/PIC/pic-timing-delay-loops.php

    delay1s:
    MOVWF CNT1 ;Load counter with W
    LOOP1 ;From above example we know that part will be 195,075us
    [/SIZE][SIZE=-1].
    .[/SIZE]
     
  8. blackmamba

    Thread Starter New Member

    Dec 4, 2009
    16
    0
    /@ chat. is your solution possible if I dont know what the int time_us is before program starts running?
     
    Last edited: Jan 12, 2010
  9. blackmamba

    Thread Starter New Member

    Dec 4, 2009
    16
    0
    I found this code which is supposed to delay for a variable d us. can someone tell me if it works for them or if the logic is right. I have tried compiling it in mickroC using the asm{} tags, and it wont work. Compiler is complaining about "_count2_delay_us not being found"

    Code ( (Unknown Language)):
    1. /* delay for d microseconds on a 4Mhz clock
    2.  */
    3. void delay_us(char d) {
    4.   char count;    
    5.   char count2;
    6.  
    7.    count = d;
    8.  
    9. _dmsouter:
    10. asm movlw D'20'
    11. asm movwf _count2_delay_us
    12.  
    13. _dmsinner:
    14. asm        NOP
    15. asm        NOP
    16. asm decfsz _count2_delay_us, f
    17. asm goto $-3
    18. asm decfsz _count_delay_us,f
    19. asm goto $-7
    20. }
     
  10. THE_RB

    AAC Fanatic!

    Feb 11, 2008
    5,435
    1,305
    Your PIC 12F683 has a 16bit TMR1 and a hardware CCP (capture/compare) module.

    Read the PIC datasheet for how to use TMR1 and the CCP, it will explain exactly how to load a value in TMR1 and generate a period from that.
     
  11. chat_eur

    New Member

    Dec 30, 2009
    7
    0
    [SIZE=-1]
    [/SIZE][SIZE=-1]
    CNT1 EQU h'20' ;General register for delay
    CNT2 EQU h'21' ;General register for delay
    CNT3 EQU h'22' ;General register for delay

    ORG 0x00 ;Start vector
    GOTO main

    main:
    BSF STATUS,RP0 ;Switch BANK1
    CLRF TRISB ;Set all pins of PORTB as output
    BCF STATUS,RP0 ;Switch BANK0

    MAIN_LOOP:
    BSF PORTB,0 ;Turn on LED
    MOVLW D'10' ;WAIT FOR 10 TIMES OF DELAY ROUTINE
    CALL delay
    BCF PORTB,0 ;Turn off LED
    MOVLW D'150' ;WAIT FOR 150 TIMES OF DELAY ROUTINE
    CALL delay ;Wait one second
    GOTO MAIN_LOOP ;Repeat

    ;ACCUMULATOR (W) WILL BE MOVED TO FIRST COUNTER OF DELAY (CNT1) ROUTINE
    ;CONTENT OF THE ACCUMULATOR DOESN'T MATTER, DELAY WILL BE SIMPLY
    ;MULTIPLIED BY THIS VALUE
    ;------Delay Routine-------------
    delay:
    MOVWF CNT1
    LOOP1:
    MOVLW d'255'
    MOVWF CNT2
    LOOP2:
    MOVLW d'255'
    [/SIZE][SIZE=-1]MOVWF CNT3
    LOOP3:
    DECFSZ CNT3,F
    GOTO LOOP3
    DECFSZ CNT2,F
    GOTO LOOP2
    DECFSZ CNT1,F
    GOTO LOOP1

    RETURN

    END[/SIZE]
     
Loading...