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.

Delay Calculation

Status
Not open for further replies.
Hey everyone, I would like to double check something here,

Can someone please tell me how many cycles this snippet of code would take to exectue....

Code:
        MOVLW   D'123'                  ;  
        CALL    DELAY                   ;  
        (continue...)
DELAY   
        MOVWF   DELAYGPR1               ;
        DECFSZ  DELAYGPR1, W            ;
        GOTO    $-2                     ;   
        BSF     STATUS, RP0             ; 
        BSF     TRISA, 4                ; 
        BCF     STATUS, RP0             ;  
        BSF     INTCON, GIE             ; Enable Interrupts
        RETURN

I worked it out to be 500 cycles include the CALL & RETURN.
Is that about right?
 
Yes, it's 500 cycles... It took about 30 seconds to copy and paste it into a program, add the variable equate, and run it in the simulator...
 

Attachments

  • Jake.PNG
    Jake.PNG
    25.8 KB · Views: 148
Last edited:
OK Mike.. I need to know... In stead of learning by trial and error and using the help file..
Do you know of any tutorials by microchip on MPLAB, there probably are and to be honest I havn't looked yet... But if I ask first, maybe I'll be directed to it quicker. I really need to and will learn how to use it.

Anyway the reason I asked about the timing was my communication routine with the DS18B20 is still not working, and I thought it may have been my delay routine but they look ok.

Here's the code for the GET_TEMP and communiation routines based on your untested version Mike.

I have the DS18B20 data line connected to PORTA, 4 pulled high via a 4K7 resistor.

Can you see anything wrong with the routines?

Im getting 0.0 displayed, even If i load a dummy figure after the RAM has been cleared. Its like the code below is simply clearing the registers im using for the temp.

Code:
GET_TEMP
        CALL    DS18B20_RESET            ; Issue device reset command
        MOVLW   H'CC'                    ; ROM Command - Skip ROM
        CALL    DS18B20_WRITE_BYTE       ; Write to DS18B20
        MOVLW   H'44'                    ; Function Command - Convert T
        CALL    DS18B20_WRITE_BYTE       ; Write to DS18B20
        
        CALL    DS18B20_READ_BIT         ; Master can issue read time slots after the Convert T command and the DS18B20 will respond by transmitting a 0 while the temperature conversion is in progress and a 1 when the conversion is done
        BTFSS   STATUS, C                ; Is Carry flag Set, to indicate Temperature Conversion finished?
        GOTO    $-2                      ; NO, GOTO previous instruction and continue testing
        
        CALL    DS18B20_RESET            ; Issue device reset command
        MOVLW   H'CC'                    ; ROM Command - Skip ROM
        CALL    DS18B20_WRITE_BYTE       ; Write to DS18B20
        MOVLW   H'BE'                    ; Function Command - Read Scratchpad
        CALL    DS18B20_WRITE_BYTE       ; Write to DS18B20
        
        CALL    DS18B20_READ_BYTE        ; Read from DS18B20
        MOVWF   SCRATCHPAD_BYTE0         ; Move read byte to corresponding GPR
        CALL    DS18B20_READ_BYTE        ; Read from DS18B20
        MOVWF   SCRATCHPAD_BYTE1         ; Move read byte to corresponding GPR
        
        CALL    REARRANGE_RESULT         ; This sub routine is working.... tested with dummy figures, therefore problem lies with communication with the sensor
        GOTO    GET_TEMP
        
        
DS18B20_RESET  ; RESET
        BSF     STATUS, RP0             ; }
        BCF     TRISA, 4                ; } DQ LOW
        BCF     STATUS, RP0             ; }
        
        MOVLW   D'123'                  ; Move 123 to W register
        CALL    DELAY                   ; CALL Delay: 500 cycle delay including CALL/GOTO & RETURN. Send Reset Pulse
        MOVLW   D'123'                  ; Move Decimal 123 to W register
        GOTO    DELAY                   ; GOTO Delay: 500 cycle delay including CALL/GOTO & RETURN. Wait MIN 480uS for DS18B20 & return with DQ line High Z

DS18B20_WRITE_BYTE  ; WRITE BYTE
        MOVWF   SHIFT_IN_OUT            ; Store Byte to shift into DS18B20
        MOVLW   D'08'                   ; Move Decimal 8 to W
        MOVWF   COUNT                   ; Store in COUNT GPR. This is how many bit will be read
        RRF     SHIFT_IN_OUT, F         ; Rotate Right File Register SHIFT_IN_OUT to move bit out of SHIFT_IN_OUT and into Carry
        CALL    DS18B20_WRITE_BIT       ; Send bit
        DECFSZ  COUNT, F                ; Have all 8 bits been written?
        GOTO    $-3                     ; NO, GOTO here - 3 instructions to write next bit
        RETURN                          ; 

DS18B20_WRITE_BIT  ; WRITE BIT
        BCF     INTCON,GIE              ; Disable Interrupts
        BSF     STATUS, RP0             ; }
        BCF     TRISA, 4                ; } DQ LOW
        BCF     STATUS, RP0             ; }
        BTFSS   STATUS, C               ; Test Carry bit of STATUS register to determine which Logic Level to send
        GOTO    $+4                     ; Carry = 0, Skip next 3 instructions, maintain Low Logic Level for MNI 60uS
        BSF     STATUS, RP0             ; }
        BSF     TRISA, 4                ; } DQ HIGH Z (Input, Pullup resistor forces line to Logic 1, unless DS18B20 pulls it low)
        BCF     STATUS, RP0             ; }
        MOVLW   D'16'                   ; Move 16 to W register
        GOTO    DELAY                   ; GOTO Delay: 72 cycle delay including CALL/GOTO & RETURN

DS18B20_READ_BYTE  ; READ BYTE
        MOVLW   D'08'                   ; Move Decimal 8 to W
        MOVWF   COUNT                   ; Store in COUNT GPR. This is how many bit will be read
        CALL    DS18B20_READ_BIT        ; CALL DS18B20_READ_BIT and return with read bit in Carry bit of STATUS register
        RRF     SHIFT_IN_OUT, F         ; Rotate Right File Register SHIFT_IN_OUT to move bit out of Carry and into SHIFT_IN_OUT GPR
        DECFSZ  COUNT, F                ; Have all 8 bits been read?
        GOTO    $-3                     ; NO, GOTO here - 3 instructions to read next bit
        RETURN                          ; 

DS18B20_READ_BIT  ; READ BIT
        BCF     INTCON,GIE              ; Disable Interrupts
        BSF     STATUS, RP0             ; }
        BCF     TRISA, 4                ; } DQ LOW
        BCF     STATUS, RP0             ; }
        BSF     STATUS, RP0             ; }
        BSF     TRISA, 4                ; } DQ HIGH Z (Input, Pullup resistor forces line to Logic 1, unless DS18B20 pulls it low)
        BCF     STATUS, RP0             ; }
        BCF     STATUS, C               ; Clear Carry bit of STATUS register
        BTFSC   PORTA, 4                ; Output data from the DS18B20 is valid for 15µs after the falling edge that initiated the read time slot
        BSF     STATUS, C               ; DQ line Logic 1, therefore set Carry bit of STATUS register
        BSF     INTCON,GIE              ; DQ line Logic 0, leave Carry bit of STATUS register clear and Enable Interrupts
        MOVLW   D'16'                   ; Move 16 to W register
        GOTO    DELAY                   ; GOTO Delay: 72 cycle delay including CALL/GOTO & RETURN

DELAY  ; This routine is used for delays from 12 cycles to 1028 cycles (Move D'1' for 12 cycle delay or a D'0' for 1028 cycle delay)
        MOVWF   DELAYGPR1               ;   Formula for this delay shown below (includes 'MOVLW number' and 'CALL/GOTO DELAY' instructions)
        DECFSZ  DELAYGPR1, W            ;   Cycles = 8 + (Number x 4)   OR   Number = (C - 8) / 4
        GOTO    $-2                     ;   Example. If a delay of at least 480uS is required (4MHz OSC), Number = (480 - 8) / 4 = 118. Therefore MOVLW D'118' before CALLing the DELAY
        BSF     STATUS, RP0             ; Bank 1
        BSF     TRISA, 4                ; Make Pin 3 an Input, Pullup resistor forces line to logic 1, unless DS18B20 pulls it low
        BCF     STATUS, RP0             ; Bank 0
        BSF     INTCON, GIE             ; Enable Interrupts
        RETURN

The complete program is here Jake's Electronics - Syntax Highlighter Trial
 
Please tell us if this mini' tutorial is of any help; MPLAB and MPSIM (starting at page 10).

I'll try to find time to look at your code later today. Curious if you tried my 'untested' program?

Regards, Mike
 
Please tell us if this mini' tutorial is of any help; MPLAB and MPSIM (starting at page 10).
I had a quick scan and yes It will definitly help. I will have a read after work tonight.

Curious if you tried my 'untested' program?
Yes, I did. I didn't work. I cant remember what it did, if it did anything at all, but I can also re try that again if you say it works? In the other old thread I thought you said:
Jake,

Here's my (untested) version of your program if you're interested.
so I was guessing you hadn't had it working.
 
Thanks Mickster,
I normally use this one,
But I wanted a universal delay routine which I can call for different delays.
For a delay like the one in my first post I can use this formula to work out the delays. I just have to MOVe a diffent number to W before CALLing the delay...

Cycles = how many cycles the delay will be including the call and return
Number = the number to MOV to W before calling the delayroutine


Formula's:
Cycles = 8 + (Number x 4)
OR
Number = (Cycles - 8) / 4

EG. MOVLW D'100' will give a delay of 408 cycles...

Note only delays of 12 cycles to 1028 cycles are possible
 
Hi Jake,

Your delay routine analysis and your insight are very impressive. May I contribute a couple more ideas to help stimulate those synapses?

You might consider using a Macro to make your delay subsystem look and feel a little more intuitive.
Code:
        radix   dec
;
;  generate a precise 100 cycle pulse on the clock pin
;
        bsf     clockpin        ; clock pin = 1
        DelayCy 99              ; delay 99 cycles
        bcf     clockpin        ; clock pin = 0
Code:
;
;  DelayCy(8..1028 cycles) Macro
;
DelayCy macro   cycles
        movlw   (cycles-8)/4+1  ;
        call    Delay           ;
        endm
Code:
;
;  Delay subroutine (4 cycle loop with 8 cycles "overhead")
;
Delay   movwf   delaygpr1       ;
        decfsz  delaygrp1,W     ;
        goto    Delay           ;
        return                  ;
Your delay subsystem will only generate delays that are (cycles-8)/4 so the code snippet above will generate a 96 cycle delay instead of the desired 99 cycle delay. To fix that we need to account for the three (cycles-8)%4 cycles which can be done easily enough like this;
Code:
        radix   dec

delaygrp1  equ   0x20
;
;  DelayCy(8..1031 cycles) Macro
;
DelayCy macro   cycles
        movlw   (cycles-8)/4+1  ;
        call    Delay-((cycles-8)%4)
        endm

        org     0x000
;
;  simulation code
;
        DelayCy (99)            ; <- put simulator program counter here
        nop                     ; <- put simulator break point here
;
;  Delay subroutine
;
        nop                     ; (cycles-8)%4 == 3 entry point
        nop                     ; (cycles-8)%4 == 2 entry point
        nop                     ; (cycles-8)%4 == 1 entry point
Delay   movwf   delaygpr1       ; (cycles-8)%4 == 0 entry point
        decfsz  delaygrp1,W     ; four cycle loop
        goto    Delay           ;
        return                  ;
;
        end
Once you figure how to use (DelayCycles - OverheadCycles) / LoopCycles effectively and account for those troublesome (DelayCycles - OverheadCycles) % LoopCycles you'll find little use for those Delay Code Generators (LOL). In fact if you add a couple equates you can generate "cycle accurate" delays specified in "usecs" or "msecs" that will work for almost any clock (4, 8, 12, 16, or 20 MHz);
Code:
        radix   dec
;
;  DelayCy(8..1031 cycles) Macro
;
clock   equ     4               ; 4, 8, 12, 16, or 20 MHz clock
usecs   equ     clock/4         ; cycles/usec operand multiplier
msecs   equ     clock/4*1000    ; cycles/msec operand multiplier

DelayCy macro   cycles
        movlw   (cycles-8)/4+1  ;
        call    Delay-((cycles-8)%4)
        endm
Code:
;
;  generate a precise 50 usec pulse (same code works for any clock speed)
;
        bsf     clockpin        ; clock pin = 1
        DelayCy(50*usecs-1)     ; 50 usecs minus 1 cycle
        bcf     clockpin        ; clock pin = 0
Now this 1031 cycle subroutine may not be very useful for multi-millisecond delays at higher clock speeds but the method scales well and you'll find variations of it on PICLIST in the source code library that use 16-bit delay loops to produce delays up to several hundred thousand cycles (with only 11 cycles "overhead").

Cheerful regards, Mike
 
Last edited:
Thanks Mike.
I have never played with Macro's, but it's definitly another thing to add to my to do list.

I found an error with my program..
I forgot to load the read byte to the W register before returning to the main loop.
But still, my circuit does not work.
I WONT GIVE IN... lol
Code:
DS18B20_READ_BYTE  ; READ BYTE
        MOVLW   D'08'                   ; Move Decimal 8 to W
        MOVWF   COUNT                   ; Store in COUNT GPR. This is how many bit will be read
        CALL    DS18B20_READ_BIT        ; CALL DS18B20_READ_BIT and return with read bit in Carry bit of STATUS register
        RRF     SHIFT_IN_OUT, F         ; Rotate Right File Register SHIFT_IN_OUT to move bit out of Carry and into SHIFT_IN_OUT GPR
        DECFSZ  COUNT, F                ; Have all 8 bits been read?
        GOTO    $-3                     ; NO, GOTO here - 3 instructions to read next bit 
        [COLOR="red"]MOVF    SHIFT_IN_OUT, W[/COLOR]
        RETURN                          ;

What I have done is comment out all the re-arrange number routines.
All it should do now is move the first 2 bytes of the scratch pad (the temp) to port B and display them on the 2 LSB's of the 7-segment.

BUT im getting every segment of the display lit up. See pic.

So here is the code I've got now:
DS18B20 Digital Thermometer ASM
OR
DS18B20 Digital Thermometer ASM WITH colour scheme
 

Attachments

  • DSC07510.JPG
    DSC07510.JPG
    158.1 KB · Views: 169
  • scan0001.jpg
    scan0001.jpg
    153.6 KB · Views: 165
Last edited:
Status
Not open for further replies.

Latest threads

New Articles From Microcontroller Tips

Back
Top