Having trouble with bit rotating on the PIC16F818.

Thread Starter

dmarciano

Joined Oct 10, 2007
21
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

MAIN CODE

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



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

DelayP5
clrf TMR0
LoopP5
movf TMR0,W
sublw .16
btfss STATUS,ZEROBIT
goto LoopP5
retlw 0

DelayP25
clrf TMR0
LoopP25
movf TMR0,W
sublw .8
btfss STATUS,ZEROBIT
goto LoopP25
retlw 0
;****************************
; Configuration of Pins *
;****************************
main
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
bcf
STATUS,5
clrf PORTA
movlw 00h
movwf PORTB
clrf PORTB
bsf INTCON,GIE
bsf INTCON,INTE
movlw .1
movwf Pattern
;****************************
; Patterns for lighting *
;****************************
pattern1
movlw .2
LoopP1
movwf PORTB
call DelayP5
btfsc PORTB,7
goto pattern1
rlf PORTB,w
goto LoopP1

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

beenthere

Joined Apr 20, 2004
15,808
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.
 

Papabravo

Joined Feb 24, 2006
12,301
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.
 

RiJoRI

Joined Aug 15, 2007
536
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.

--Rich
 
Top