Having trouble with bit rotating on the PIC16F818.

Discussion in 'Embedded Systems and Microcontrollers' started by dmarciano, Oct 19, 2007.

  1. dmarciano

    Thread Starter Member

    Oct 10, 2007
    I am writing a programming that requires LEDs to light up in sequence. As each LED lights up the previous one goes out, so there is only one LED on at any given time. Eventually there will be multiple LED lighting patterns that will a user will be able to switch between by using a switch.

    In order to get the LEDs to light up in sequence I move '2' into PORTB which will make B1 go high (2=00000010). Next a delay of .5 seconds is called. Then I rotate left PORTB into the W register. I thought rotating a byte is the same as multiplying it by two. So the W register should now hold 4 which I then move into PORTB. The should make B2 go high and B1 go low (4=00000100). I continually check the MSB and if it is set I load '2' into PORTB and start again.

    Now when I actually run the program on a test circuit each LED lights up but the previous one doesn't go out. The program is just setting each bit in PORTB and then eventually loops (00000010->00000110->00001110). I don't know what I'm doing wrong but it is definitely something with the RLF command that I don't understand. Any help would be greatly appreciated.

    B0 is not hooked up to an LED because I will be using this pin for the interrupt function which a switch will activate in order to change the pattern. I am including the full ASM code for reference.

    NOTE: All patterns haven't been written yet and the interrupt function isn't completed. Right now I'm just testing 'pattern1'. If I can't get this working then the others don't matter because the majority of the lighting effects will depend on the RLF command. In my test circuit I have nothing hooked up to B0 right now because I'm not testing the interrupt right now.

    Any help would be greatly appreciated.

    list p=16F818 ; list directive to define processor
    #include <p16F818.inc> ; processor specific variable definitions

    errorlevel -302 ; suppress message 302 from list file

    __CONFIG H'3F10'

    Pattern EQU 20H ; variable used for inidicating current pattern
    TMR0_temp EQU 21H ; variable used for saving TMR0 register
    w_temp EQU 22H ; variable used for saving W register
    status_temp EQU 23H ; variable used for saving STATUS register
    PORTB_temp EQU 24H ; variable used for saving PORTB register
    ZEROBIT EQU 2 ; Bit2 of STATUS register for Zero calculation

    RESET_VECTOR CODE 0x000 ; processor reset vector
    goto main ; go to beginning of program

    INT_VECTOR CODE 0x004 ; interrupt vector location
    goto INTERRUPT


    bsf INTCON,GIE
    movfw Pattern ; Move Pattern into W register
    sublw .10 ; Subtract 10 from W register (W-10)
    clrf Pattern ; If W-10=0 then Pattern=0
    incf Pattern ; Increase Pattern by 1
    movfw Pattern
    sublw .1
    goto pattern1
    movfw Pattern
    sublw .2
    goto pattern2

    ; Timer Subroutines *
    ; Based on 32.768 kHz timer *
    clrf TMR0
    movf TMR0,W
    sublw .32
    goto Loop1
    retlw 0

    clrf TMR0
    movf TMR0,W
    sublw .16
    goto LoopP5
    retlw 0

    clrf TMR0
    movf TMR0,W
    sublw .8
    goto LoopP25
    retlw 0
    ; Configuration of Pins *
    bsf STATUS,5
    movlw B'11111111'
    movwf TRISA
    movlw B'00000110'
    movwf ADCON1
    movlw B'00000001'
    movwf TRISB
    movlw B'00000000'
    movwf OSCCON
    movlw B'00000111'
    movwf OPTION_REG
    clrf PORTA
    movlw 00h
    movwf PORTB
    clrf PORTB
    bsf INTCON,GIE
    movlw .1
    movwf Pattern
    ; Patterns for lighting *
    movlw .2
    movwf PORTB
    call DelayP5
    btfsc PORTB,7
    goto pattern1
    rlf PORTB,w
    goto LoopP1

    movlw .2
    movwf PORTB
    call DelayP25
    btfsc PORTB,7
    goto pattern2
    rlf PORTB,w
    goto LoopP2
    END ; directive 'end of program'
  2. beenthere

    Retired Moderator

    Apr 20, 2004
    If you aren't buffering the outputs to the LED's, then that may be the casue of your problem. A LED will act like a short once enough voltage is applied to place it into conduction. I don't know how the internal circuitry of the PIC is arranged, but the excess current has probably caused the pins to latch up.

    You are much more likely to get the LED's to work predictably if you use logic level FET's as switches. Something like mw favorite - VN10LP. Use 100 ohm resistors between the PIC pin and the gate. Put the source to ground, and run the LED plus the current limiting resistor from Vcc to the drain.
  3. Papabravo


    Feb 24, 2006
    When you read the value of a port, even one configured as an output, you may be reading the state of the pin rather than the state of the output data latch. Check your datasheet and check the type of instruction you are using. As a last resort, operate on a variable in the register file, then output the latest copy of the variable from the register file each time you want to make a change.
  4. RiJoRI

    Well-Known Member

    Aug 15, 2007
    In general, rotating the value of an I/O port is NOT A Good Thing! Especially when there are inputs and outputs mixed together. Consider if you have a switch on PortB.0, and the switch is at a 0 value. Rotate the port, and that zero is now in PortB.1. Now, what if the switch was set to a 1, or worse yet, the switch was bouncing!

    I would load W from the port, AND W with b'1111 1110 to trim off all unwanted/ unneeded bits, rotate W (you may need to clear the carry if all you have is Rotate-With-Carry) and store it back into the port.