1. fatoms

    Thread Starter New Member

    Oct 25, 2009
    4
    0
    Hi,
    I have recentely accuired a PicKit2 Programmer Starter kit and am working my way thru the Demo lessome that came with it. I have done all the lessons and am now going back thru them and making changes to se if i get the result I expect.
    I have exended the code in lesson one as follows;
    cblock 0x20
    Delay1 ; Assign an address to label Delay1
    Delay2
    Display ; define a variable to hold the display
    endc
    org 0
    Start:
    bsf STATUS,RP0 ; select Register Page 1
    bcf TRISC,0 ; make IO Pin RC0 an output
    bcf TRISC,1 ; make IO Pin RC1 an output
    bcf TRISC,2 ; make IO Pin RC2 an output
    bcf TRISC,3 ; make IO Pin RC3 an output
    bcf STATUS,RP0 ; back to Register Page 0
    clrf PORTC
    bsf PORTC,0 ;turn on led DS1
    Call OndelayLoop
    bsf PORTC,1 ;turn on led DS2
    Call OndelayLoop
    bsf PORTC,2 ;turn on led DS2
    Call OndelayLoop
    bsf PORTC,3 ;turn on led DS3
    Goto Finish
    OndelayLoop:
    decfsz Delay1,f ; Waste time.
    goto OndelayLoop ; The Inner loop takes 3 instructions per loop * 256 loopss = 768 instructions
    decfsz Delay2,f ; The outer loop takes and additional 3 instructions per lap * 256 loops
    goto OndelayLoop ; (768+3) * 256 = 197376 instructions / 1M instructions per second = 0.197 sec.
    ; call it a two-tenths of a second.
    Return
    Finish:
    goto $ ; wait here
    end
    DS1 to DS4 are leds on the demo board included in the kit.
    The problem I am having is when the 'bsf PORTC,1' executes the LED that was on previously turns off (which I do not want)indicating that bsf PORTC bit 0 has been cleared. The dcs give me the impression that this instruction should only affest bit 1. I want the four LEDs to turn each in series and stay on so I end up with alll four on. I can do this by using a the display variable to hold a byte indicating conbinations of leds (eg 0x3 for dS1 & dS2) and mowing that to the prot via w. I want to see if I can do it with bsf commands.
    Am i missing something and if so can someone fill me in on what?
    Regards
    Dom
     
  2. eng1

    New Member

    Oct 25, 2009
    13
    0
    Pins RC1~4 are multiplexed with the internal ADC and comparators. If you do not disable these analog functions, pins read as '0'. When you use the BSF instruction, the entire PORT is read, the selected bit is changed and the result is then moved to the PORT. Hence, the results you are observing.
    Try clearing the ANSEL and ANSELH registers in the init section of your code. IIRC comparators should be off upon reset for the PIC16F690, you can check the datasheet or handle their initialization too, as I usually do.
     
    Last edited: Oct 25, 2009
  3. thatoneguy

    AAC Fanatic!

    Feb 19, 2009
    6,357
    718
    Many uC's use a "Read/Modify/Write" method of setting pins. When you are trying to set a port, it reads the current status, changes the bit you want, and writes it back to the port. If the pin happens to be an output, and heavily loaded (such as an LED), the "Read" part will be zero, so when you do a set_bit on a different pin, The entire bank is read, and the heavily loaded pins will be set to zero.

    It is better to decide what all the ports should be, and write the entire port byte so there isn't confusion as to what is happening.

    e.g. PORTA = 0xFF
    Rather than
    set_bit(PORTA,0)
    set_bit(PORTA,1)
    ....
    set_bit(PORTA,7)

    The above is a common, difficult to track down bug sometimes, and it sounds like you are running directly into it.

    Microchip has an App Note on this, though I forget the number. :(
     
  4. ke5nnt

    Active Member

    Mar 1, 2009
    384
    15
    On an unrelated note since you're new to assembly, you can clean up your code a little and accomplish the same thing. In your code when you're setting your ports as output via trisc, you can use only two lines of code if you write:
    MOVLW B'00000000'
    MOVWF TRISC

    This way you are defining your pins all at once using binary instead of setting them one at a time.
     
  5. fatoms

    Thread Starter New Member

    Oct 25, 2009
    4
    0
    eng1 , thatoneguy - Thanks Between your replies I was able to work out what was going on and more importantly why.:)

    ke5nnt - Thanks for the tip.

    I have changed the code to use a variable to store the LED status and am setting the bits in that then copying to the port as required. This avoids the read-modify-write trap that I fell for.

    NEW code in case anyone is interested:

    cblock 0x20
    Delay1 ; Assign an address to label Delay1
    Delay2
    Display ; define a variable to hold the diplay
    endc
    org 0
    Start:
    bsf STATUS,RP0 ; select Register Page 1
    ; One pin at a time
    bcf TRISC,0 ; make IO Pin RC0 an output
    bcf TRISC,1 ; make IO Pin RC1 an output
    bcf TRISC,2 ; make IO Pin RC2 an output
    bcf TRISC,3 ; make IO Pin RC3 an output
    ;movlw 0x0
    ;movwf TRISC ;Make all PortC Outputs
    bcf STATUS,RP0 ; back to Register Page 0

    clrf Display
    bsf Display,0
    call SetLED
    Call OndelayLoop
    bsf Display,1
    call SetLED
    Call OndelayLoop
    bsf Display,2
    call SetLED
    Call OndelayLoop
    bsf Display,3
    call SetLED
    Goto Finish
    SetLED
    movf Display,w ; Copy the display to the LEDs
    movwf PORTC
    Return
    OndelayLoop:
    decfsz Delay1,f ; Waste time.
    goto OndelayLoop ; The Inner loop takes 3 instructions per loop * 256 loopss = 768 instructions
    decfsz Delay2,f ; The outer loop takes and additional 3 instructions per lap * 256 loops
    goto OndelayLoop ; (768+3) * 256 = 197376 instructions / 1M instructions per second = 0.197 sec.
    ; call it a two-tenths of a second.
    Return
    Finish:
    goto $ ; wait here
    end
     
Loading...