Continue to Site

Welcome to our site!

Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

  • Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

Newbie Pickit 2 question

Status
Not open for further replies.

daddywags

New Member
Hello,

I recently purchased a copy of Microchip's Pickit 2 programmer, with a low pin count demo board to play around with. The board comes with a PIC16F690 chip, 4 LEDs, a pushbutton, and a pot. I'm using Microchip's MPLAB development environment.

The Demo Board comes with several tutorials. The first one is called, "Hello World." It involves using Assembly language to light up a single LED, attached to one of the IO pins.

The Four LEDs are connected to pins RC0-RC3.

Here's the code that turns on LED RC0:

#include <p16F690.inc>
__config (_INTRC_OSC_NOCLKOUT & _WDT_OFF & _PWRTE_OFF & _MCLRE_OFF & _CP_OFF & _BOR_OFF & _IESO_OFF & _FCMEN_OFF)
org 0
Start:
bsf STATUS,RP0 ; select Register Page 1
bcf TRISC,0 ; make IO Pin C0 an output
bcf STATUS,RP0 ; back to Register Page 0
bsf PORTC,0 ; turn on LED C0 (DS1)
goto $ ; wait here
end


I've done this, and it seems to work just fine.

My question is, how would I go about turning on 2 or more LEDs? The intuitive way seems to be to use the following code:

Start:
bsf STATUS,RP0 ; select Register Page 1
bcf TRISC,0 ; make IO Pin C0 an output
bcf TRISC,1 ; should this make pin C1 an output?
bcf STATUS,RP0 ; back to Register Page 0
bsf PORTC,0 ; turn on LED C0 (DS1)
bsf PORTC,1 ; shouldn't this turn on LED C1?
goto $ ; wait here
end


I've tried this, and many other combinations, but no luck. Any thoughts?
 
The default value of the TRISC register after a "power on reset" or "brown out reset" is b'11111111' (all inputs). You want to set both the RC0 and RC1 pins as outputs. Try to think of a '1' bit in TRISC as an Input and a '0' bit as an Output

Mike

<added>

Almost forgot.... Welcome to the Forum... Have fun!!!
 
Last edited:
Hey there,
Thanks for the welcome and the quick response!

That makes sense. I've been operating under the impression that by adding the line, bcf TRISC,1 I would be able to set pin RC1 as an output, as well.

Is that not the way to do it?


Start:
bsf STATUS,RP0 ; select Register Page 1
bcf TRISC,0 ; make IO Pin C0 an output


bcf TRISC,1 ; Doesn't this turn pin RC1 into an output?


bcf STATUS,RP0 ; back to Register Page 0
bsf PORTC,0 ; turn on LED C0 (DS1)
bsf PORTC,1 ; shouldn't this turn on LED C1?
goto $ ; wait here
end
 
Hi,

Welcome.

What happens if you do,
Code:
Start:
		bsf	STATUS,RP0	; select Register Page 1
		bcf	TRISC,0		; make IO Pin C0 an output
		bcf	TRISC,1		; should this make pin C1 an output?
		bcf	STATUS,RP0	; back to Register Page 0
		movlw	b'00000011'	
		movwf	PORTC
		goto	$		; wait here
		end

If this fixes it then it is probably because the port is in analogue mode. To set the port to all digital you need to clear ANSEL and ANSELH (both in bank 2).

I'm also a little confused by the example code you have posted, it has both the internal clock selected and master clear turned off. This can cause problems with some chips. Is this the example supplied by Microchip?

Mike.
 
Last edited:
Just had a look at the circuit diagram for that board and just thought I would ask, do you have JP2 on?

edit, removed reply to deleted post.

Mike.
 
Last edited:
That fixed it! LEDs 1 and 2 are now glowing brightly! I also tried it with LEDs 0-3, (with a hex value of 0xFF) and all of them are glowing! This is just about the prettiest thing I've seen all day.

Could you tell me a little bit more about this "analogue mode," and why the method I tried didn't work? I looked at the writeup for the ANSEL and ANSELH registers in the 16F690 user manual, but it's difficult to decipher: This is the first time I've done any programming ever, so please bear with me.

Hi,

Welcome.

What happens if you do,
Code:
Start:
		bsf	STATUS,RP0	; select Register Page 1
		bcf	TRISC,0		; make IO Pin C0 an output
		bcf	TRISC,1		; should this make pin C1 an output?
		bcf	STATUS,RP0	; back to Register Page 0
		movlw	b'00000011'	
		movwf	PORTC
		goto	$		; wait here
		end

If this fixes it then it is probably because the port is in analogue mode. To set the port to all digital you need to clear ANSEL and ANSELH (both in bank 2).

I'm also a little confused by the example code you have posted, it has both the internal clock selected and master clear turned off. This can cause problems with some chips. Is this the example supplied by Microchip?

Mike.
 
Some of the pins on the 690 are configured as analogue pins at reset. Analogue pins always read as zero and so when a bsf instruction is used it reads the other bits as zero and so the second bsf will reset the first one. (bsf reads the port (or other register), modifies the value and writes it back to the port)

To turn off the analogue part of the ports you would clear the ANSEL(H) registers and so you code would become,
Code:
Start:
		bsf	STATUS,RP2	;bank 2
		clrf	ANSEL		;turn of analogue pins
		clrf	ANSELH		;and some more
		bcf	STATUS,RP2	;back to bank 0
		bsf	STATUS,RP0	; select Register Page 1
		bcf	TRISC,0		; make IO Pin C0 an output
		bcf	TRISC,1		; should this make pin C1 an output?
		bcf	STATUS,RP0	; back to Register Page 0
		bsf	PORTC,0		; turn on LED C0 (DS1)
		bsf	PORTC,1		; turn on LED C1
		goto	$		; wait here
		end

Mike.
 
Last edited:
I don't think that the analog mode makes any difference when the pins are being used as outputs. Analog mode only disables the input buffers.

I think that the problem here could be the read-modidy-write effect on the ports.

The simple rule when manipulating ports is to never modify bits on a port in subsequent instructions.

so
Code:
	bsf	PORTC,0		; turn on LED C0 (DS1)
	bsf	PORTC,1		; turn on LED C1

is wrong.

You can use

Code:
	movlw	b'00000011'	
	iorwf	PORTC

like you did or
Code:
	bsf	PORTC,0		; turn on LED C0 (DS1)
	nop
	bsf	PORTC,1		; turn on LED C1


The reason is a little technical, and you don't need to understand it if you stick to the rule of not setting bits on subsequent instructions:-

On PICs, instructions that change registers, including the ports, work by reading the register value from the memory, modifying the value in the Arithmetic Logic Unit, and writing the value back into the memory.

There is no way that the PIC can change individual bits in the memory, so instuctions like bsf 0x20, 0 are executed by reading register 0x20, setting bit 0 and writing the whole lot back into register 0x20. In normal registers that aren't ports that doesn't make any difference.

However, with ports, if you execute bsf PORTC, 0 the value is written back to the port in the last quarter of the instruction. If the next instruction is bsf PORTC, 1, that will read the port again in the first quarter of the next instruction, only a very short time after the 1 was written.

Any capacitance or load on the pin will slow the rise of the voltage on PORTC, 0 pin. If that pin is read a very short time later, the voltage will still read as 0. Even though it is rising, it will not have got to a level that reads as a 1. The second instruction (bsf PORTC, 1) will read PORTC, 0 as a 0, so that is what will be written back at the end of the second instruction.
 
like you did or
Code:
	bsf	PORTC,0		; turn on LED C0 (DS1)
	nop
	bsf	PORTC,1		; turn on LED C1

Good advice but unfortunately, in this case, this will not work. The pins are configured as analogue and therefore always read back as a zero. No delay will fix this problem, the second bsf will always clear the first.

Mike.
 
Last edited:
Good advice but unfortunately, in this case, this will not work. The pins are configured as analogue and therefore always read back as a zero. No delay will fix this problem, the second bsf will always clear the first.

Mike.

Good point. You should set all the pins to digital, and to output, or you can just write using

Code:
	movlw	b'00000011'	
	movwf	PORTC
 
Hey there,
Thank you all for your help! I wouldn't have gotten anywhere on this without your advice, and I really appreciate it.

Now, to proceed with the rest of the lessons... =)
 
i tested this..

I tried this out.. in fact you do have to pull it out of analog mode to make it work.. also there is no STATUS,RP2 (for any new people...)

to go to "bank 2" and get PORTC out of analog mode you want to change to code to reflect..

bsf STATUS, RP1 ;bank 2
clrf ANSEL
clrf ANSELH
bcf STATUS,RP1 ;bank 0
...

Thanks for the tips guys, I found this posting helpful.
 
I think you have one you don't need I always did it like the data sheet said
Code:
    BCF STATUS,RP0          ;Bank 0
    BCF STATUS,RP1          ;
    CLRF PORTC                ;Init PORTC
    BSF STATUS,RP1          ;Bank 2
    CLRF ANSEL                ;digital I/O
    BSF STATUS,RP0         ;Bank 1
   MOVLW b'00000000    ;Set PortC all to output
   MOVWF TRISC              ;writes to trisC
   BCF STATUS,RP0          ;Bank 0
   MOVLW b'11111111    ; sets all pins on PortC high
   MOVWF PORTC             ; wirte  to PortC
Code:
   BCF STATUS,RP0          ;Bank 0
   MOVLW b'11111111    ; sets all pins on PortC high
   MOVWF PORTC             ; wirte  to PortC
   ;; Or  use BSF for setting just the pin you need 
   BSF PORTC,1
   BSF PORTC,2        ;which ever way dos what you need
clrf ANSELH
you don't need that one
 
Last edited:
Status
Not open for further replies.

New Articles From Microcontroller Tips

Back
Top