Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronic Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

Register Log in

Need to shift 16 bit numbers using pic16f877

Status
Not open for further replies.

comp_freak

Member level 1
Joined
Jan 19, 2006
Messages
40
Helped
1
Reputation
2
Reaction score
0
Trophy points
1,286
Activity points
1,687
Hi there,

I have to shift a 16 bit number either left or right shift, i got stuck because pic16f877 only provide roatation operation plus to 16 bit number sound very complicated to me .. since again there will be two bytes upper and lower and bytes will be moving from upper to lower when i do shifting in either case.. any one has done that before or know any routines???
 

kalyanram

Advanced Member level 4
Joined
Jan 3, 2005
Messages
102
Helped
13
Reputation
26
Reaction score
4
Trophy points
1,298
Activity points
1,012
Hi Comp Freak,
I haven't worked on this PIC processor but from the microchip site I was able to look into its manual. Correct me if I'm wrong in my interpretation as I just scanned through the doc for Instruction and the register size.
ASSUMPTION:
1) Now this processor has 8 bit registers and the operation to shift is basically done through a "rotate" left or right through carry.

Now here are the sequence of instructions that shoudl give you the required result.
FOR SHIFT LEFT:
1) Clear the carry bit you can do this by doing a) ADD 0,0 or a similar kind of an operation that affects the carry bit or b) use the bit-field clear.
2) Now do a rotate left the lower byte first this should give the MSB in carry and the carry bit (which is basically '0') is now in the LSB. So the lower byte of the 16 bit number is left shifted by 1. Save this result where you need it.
3) Now (don't clear the carry) load the upper byte and rotate it left by one bit. Now this will put the carry bit in LSB of upper byte (i.e in effect the MSB of lower byte has been transfered to LSB of the upper byte) and the MSB of upper byte is now in carry.
4) You can repeat this process for as many byte long number as possible.

FOR SHIFT RIGHT:
The procedure is quite similar except that use a rotate right :D and secondly start with the upper byte first.

And for more than one byte shift loop the above routine for required no.of times.
This prcedure will work if my assumption is correct.

~Kalyan.
 

    comp_freak

    points: 2
    Helpful Answer Positive Rating

albert22

Full Member level 6
Joined
Jul 20, 2004
Messages
333
Helped
68
Reputation
136
Reaction score
65
Trophy points
1,308
Activity points
5,005
kalyanram is right. That is the way to shift on PIC MCUs I heve been using that method since the pic16c84 and up to the 16f877. Due to the reduced instruction set of the PICs, sometimes it is necessary to use more instructions to accomplish what others like the Z80 might do in just one instruction.
 

jonw0224

Full Member level 4
Joined
Nov 22, 2004
Messages
211
Helped
45
Reputation
90
Reaction score
14
Trophy points
1,298
Location
USA
Activity points
2,528
I may add there are better ways to shift by 4 and greater and by 8 or greater with a PIC16Fx. I have been working on a couple of macros to insert optimized code for each shift, unfortunately, they are untested. I can share here:

Code:
;Shifts an integer left by lit bits.
;intH:  the address of the high byte of the integer.  The low byte is assumed
; to be at the next address (intH+1) so that the integer is intH:intL.
;lit:  the number of bits to shift left.  Valid values are 1 to 15.
;Affects WREG and STATUS
;------------------------------------------------------------------------------
INT_SL macro intH, lit
    local intL, cnt
    intL = intH + 1
    if lit < 9
        if lit < 6
            if lit < 4
                cnt = lit
                while cnt > 0
                    rlf intL, f
                    rlf intH, f
                    cnt--
                endw
                if lit == 1
                    bcf intL, 0
                else
                    movlw low (0xFF << lit)
                    andwf intL, f
                endif
            else
                movlw 0x0F          ;intH: p1, p2.  intL: p3, p4
                andwf intH, f       ;0, p2
                swapf intH, f       ;p2, 0
                swapf intL, f       ;p4, p3
                andwf intL, w       ;0, p3
                iorwf intH, f       ;p2, p3
                xorwf intL, f       ;p4, 0.  intH: p2, p3.  intL: p4, 0
                if lit == 5
                    rlf intL, f
                    rlf intH, f
                    bcf intL, 0
                endif
            endif
        else
            if lit < 8
                if lit < 7
                    rrf intH, f     ;move intH[0] into carry
                    rrf intL, w     ;move intH[0] to intL and intL[0] to carry
                    clrf intL       ;set lower byte to zero
                    rrf intL, f     ;make intL[0] into intL[7]
                    rrf intH, f     ;move intH[1] into carry
                    movwf intH      ;intH = intH[0]:intL[7-1]
                    rrf intH, f     ;now intH = intH[1]:intH[0]:intL[7-2]
                    rrf intL, f     ;now intL = intL[1-0]:ZEROS
                else
                    rrf intH, f     ;move intH[0] into carry
                    movf intL, w
                    movwf intH      ;intH = intL
                    rrf intH, f     ;intH = intH[0]:intL[7-1], intL[0] in carry
                    clrf intL       ;intL = zero
                    rrf intL, f     ;intL = intL[0]:zeros
                endif
            else
                movf intL, w
		movwf intH
                clrf intL
            endif
        endif
    else
        if lit < D'14'
            if lit < D'12'
                movf intL, w
		movwf intH
                clrf intL
                cnt = lit - 8
                while cnt > 0
                    rlf intH, f
                    cnt--
                endw
                if lit == 9
                    bcf intH, 0
                else
                    movlw low (0xFF << (lit - 8))
                    andwf intH, f
                endif
            else
                swapf intL, w
                if lit == D'12'
                    andlw 0xF0
                endif
                movwf intH
                if lit == D'13'
                    rlf intH, f
                    movlw 0xE0
                    andwf intH, f
                endif
                clrf intL
            endif
        else
            clrf intH
            cnt = D'16'-lit
            while cnt > 0
                rrf intL, f
                rrf intH, f
                cnt--
            endw
            clrf intL
        endif
    endif
endm

;Shifts an integer right by lit bits.
;intH:  the address of the high byte of the integer.  The low byte is assumed
; to be at the next address (intH+1) so that the integer is intH:intL.
;lit:  the number of bits to shift right.  Valid values are 1 to 15.
;Affects WREG and STATUS
;------------------------------------------------------------------------------
INT_SR macro intH, lit
    local intL, cnt
    intL = intH + 1
    if lit < 9
        if lit < 6
            if lit < 4
                cnt = lit
                while cnt > 0
                    rrf intH, f
                    rrf intL, f
                    cnt--
                endw
                if lit == 1
                    bcf intH, 7
                else
                    movlw low (0xFF >> lit)
                    andwf intH, f
                endif
            else
                movlw 0xF0          ;intH: p1, p2.  intL: p3, p4
                andwf intL, f       ;p3, 0
                swapf intL, f       ;0, p3
                swapf intH, f       ;p2,p1
                andwf intH, w       ;p2, 0
                iorwf intL, f       ;p2, p3
                xorwf intH, f       ;0, p1.  intH: 0, p1.  intL: p2, p3
                if lit == 5
                    rrf intH, f
                    rrf intL, f
                    bcf intH, 7
                endif
            endif
        else
            if lit < 8
                if lit < 7
                    rlf intL, f     ;move intL[7] into carry
                    rlf intH, w     ;move intL[7] to intH and intH[7] to carry
                    clrf intH       ;set upper byte to zero
                    rlf intH, f     ;make intH[0] into intL[7]
                    rlf intL, f     ;move intL[6] into carry
                    movwf intL      ;intL = intH[6-0]:intL[7]
                    rlf intL, f     ;now intL = intH[5-0]:intL[7-6]
                    rlf intH, f     ;now intH = zeros:intH[7-6]
                else
                    rlf intL, f     ;move intL[7] into carry
                    movf intH, w
                    movwf intL      ;intL = intH
                    rlf intL, f     ;intL = intH[6-0]:intL[7], intH[7] in carry
                    clrf intH       ;intH = zeros
                    rlf intH, f     ;intH = zeros:intH[7]
                endif
            else
                movf intH, w
		movwf intL
                clrf intH
            endif
        endif
    else
        if lit < D'14'
            if lit < D'12'
                movf intH, w
		movwf intL
                clrf intH
                cnt = lit - 8
                while cnt > 0
                    rrf intL, f
                    cnt--
                endw
                if lit == 9
                    bcf intL, 7
                else
                    movlw low (0xFF >> (lit - 8))
                    andwf intL, f
                endif
            else
                swapf intH, w
                if lit == D'12'
                    andlw 0x0F
                endif
                movwf intL
                if lit == D'13'
                    rrf intL, f
                    movlw 0x07
                    andwf intL, f
                endif
                clrf intH
            endif
        else
            clrf intL
            cnt = D'16'-lit
            while cnt > 0
                rlf intH, f
                rlf intL, f
                cnt--
            endw
            clrf intH
        endif
    endif
endm
 

    comp_freak

    points: 2
    Helpful Answer Positive Rating

comp_freak

Member level 1
Joined
Jan 19, 2006
Messages
40
Helped
1
Reputation
2
Reaction score
0
Trophy points
1,286
Activity points
1,687
gr8 help ppl.. thanx a lot to Kalyan and Albert both of you... welll i thougth using roatet operation but i was not so clear.. but thanx a lot :D
 

Status
Not open for further replies.
Toggle Sidebar

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Top