Hi! how can i decrement the binary value 1010001011000010101? i'm using a PIc 16F877. my idea is to breack the number into 3 bytes! but if i do that is it still the same number?
hi Eric! yes this is relayed to delays! all i'm triying to do is to apply a formula! remenber in my previous thread i wanted a 1s delay and i used this formula (XX= (Td-5us)/3), wich gave me the decimal # 333333 (1010001011000010101). I do agree that there other easier way (PIClist etc....) but i need to get this right! coz i'm currently studying and my lecturer want us to implement the delay using the given formula.
hi Eric! yes this is relayed to delays! all i'm triying to do is to apply a formula! remenber in my previous thread i wanted a 1s delay and i used this formula (XX= (Td-5us)/3), wich gave me the decimal # 333333 (1010001011000010101). I do agree that there other easier way (PIClist etc....) but i need to get this right! coz i'm currently studying and my lecturer want us to implement the delay using the given formula.
A. take 1 off from d3 until 0 then when d3 = 0 (once hits 0 it will reset to 255)
B. take 1 off from d2
C. if d2 = 0 then take 1 off of d1
D. if d2 > 0 then goto A again
E. if d1 = 0 then done!
Something like that. EDIT It comes out like:
it comes out like (133* 256) + (256 * 256) = 99584 Of course this is me using approx you can fix to make 100,000 Even.
Create a delay routine with the generator, grap a pen and piece of paper then while trying to figure out what they do in the code, draw a flowchart of it... it will make sense allot quicker.
Most of you guys are working way too hard trying to generate precise delays using code produced from those delay generator apps'.
Design a delay loop subroutine with a constant overhead and a constant loop time you'll find you can easily control it to generate precise delays exactly to the cycle.
For example, the following simple 12 word subroutine uses a 4 cycle loop with a minimum 16 cycle overhead (including the calling code). Setup the 'cycle' equate to any value between 16 and 262159 and simulate it using the Stop Watch. As we setup the delay high value for TMRH and the delay low value for W, we subtract the 16 cycle subroutine 'overhead' and then divide the value by the constant loop time (4 cycles). Finally we use a variable entry point into the subroutine to account for delay%4 values of 3, 2, and 1.
Code:
radix dec
cycles equ 150
movlw high((cycles-16)/4)+1
movwf TMRH
movlw low ((cycles-16)/4)
call DelayLo-(cycles%4)
nop ; insert 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 ;
Once you've simulated this code and you've got a handle on using this constant loop time / constant overhead delay subroutine it's a simple matter to create a macro wrapper and create "usec" and "msec" constant multipliers based on the clock frequency.
Code:
clock equ 8 ; clock frequency in Mhz
usecs equ clock/4 ; cycles per microsecond multiplier
msecs equ usecs*1000 ; cycles per millisecond multiplier
DelayCy macro cycles
movlw high((cycles-16)/4)+1
movwf TMRH
movlw low ((cycles-16)/4)
call DelayLo-(cycles%4)
endm
Now you've got a precise general purpose delay subsystem. Here's an example of how you might use it;
Code:
;
; generate a 32 msec 500 Hz "new press" beep
;
BeepTask
movlw d'32' ; |B0
movwf Beep ; set beep counter to 32 msecs |B0
Beep 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 Beep ; loop (toggle Spkr pin again) |B0
I subtracted the 6 cycle loop time in the code above in order to produce an exact 500 Hz tone from the speaker no matter what clock frequency we're using. If I had simply used a 1-msec delay parameter without accounting for the loop time we would get the following tones;
The ability to produce isochronous code like that above isn't available in the code loops produced by those delay generator apps'.
There's one CAVEAT I should mention... The delay parameter upper limit when using the 'usec' and 'msec' multipliers is determined by the clock frequency as follows;
You can extend the range of the delay subsystem several different ways. One way would be to increase the loop time of the delay subroutine and modify the macro accordingly. Another way would be to use a 24 bit delay subroutine instead of a 16 bit delay subroutine but this would increase the minimum subroutine 'overhead' and your minimum delay. And yet another way to increase the range would be to modify the macro to call the delay subroutine multiple times if necessary but this will use another 4 words of memory for each addtional subroutine call. I showed the latter method in the OP's other thread but I'd like to say that once you need delays of 1 second or more, you should really be handling the delays in an interrupt service routine as a background task.
You decrement a big number by adding -1 (aka 0xFFFFFF for the 24 bit case) to it. Remember to propagate the carry after the first addition. It is trivial to make this process run in constant time.
To answer the original question, the way to decrement a big number on a pic is to use the subtract instruction,
Code:
movlw 1 ;we are going to subtract 1
subwf LowByte,F ;subtract 1 from Least Significant Byte
btfss STATUS,C ;was there a borrow
subwf MiddleByte,F ;yes, so subtract 1 from next significant byte
btfss STATUS,C ;repeat for more
subwf HighByte,F ;significant bytes
;the carry flag will now be clear if [U]ALL[/U] bytes are 0xff.
You can, of course, repeat the above for any number of bytes.
To answer the original question, the way to decrement a big number on a pic is to use the subtract instruction,
Code:
movlw 1 ;we are going to subtract 1
subwf LowByte,F ;subtract 1 from Least Significant Byte
btfss STATUS,C ;was there a borrow
subwf MiddleByte,F ;yes, so subtract 1 from next significant byte
btfss STATUS,C ;repeat for more
subwf HighByte,F ;significant bytes
;the carry flag will now be clear if [U]ALL[/U] bytes are zero.
You can, of course, repeat the above for any number of bytes.