bsf PORTC,X

Thread Starter

fatoms

Joined Oct 25, 2009
4
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
 

eng1

Joined Oct 25, 2009
13
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:

thatoneguy

Joined Feb 19, 2009
6,359
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. :(
 

ke5nnt

Joined Mar 1, 2009
384
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.
 

Thread Starter

fatoms

Joined Oct 25, 2009
4
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
 
Top