Adventures in PIC programming

Recently, I got a PICKit2 programmer from Microchip, for a project. I haven’t started, I’ve just been learning my way around the chip, using the included lessons. They’re somwhat lacking though, so from time to time I’ll post some (possibly useful) information on here.

Just so we’re on the same page, I’m using the second type of PICKit2 that Microchip sells, the DV164120.

Now, on to the possibly useful part. The first lesson is to turn on a single light, and the 4th lesson is to make those lights rotate around and chase each other. It took me a while to figure out exactly what was going on, so let’s go dive into lesson 1.

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

This is relatively simple, so let’s try and set two LEDs on at a time. First, let’s make all of PORTC to be output. That code is given in Lesson 3. Plus, let’s set the second bit on PORTC to set the second light on.

Start:
bsf STATUS,RP0 ; select Register Page 1
clrf TRISC ;from lesson 3, set all of TRISC to output

bcf STATUS,RP0 ; back to Register Page 0
bsf PORTC,0 ; turn on LED C0 (DS1)
bsf PORTC,1

goto $ ; wait here
end

However, this doesn’t work! You’ll notice that only LED C1 turns on. Huh. That’s interesting, because we definitely set two bits, bits 0 and 1 to turn on DS1 and DS0.

Well, so what would happen if we were to, say give the bsf command a hex value that had both bits 0 and 1 set, like 0x03? Well, as it turns out, that will actually turn on DS4. What?!

The key here is that bsf is setting the [i]bit[/i] value. Basically, you give it a variable and you set the actual bit in that region. However, you can also load in a value to that region, which is what the rotate lesson does. Now, let’s look at the datasheet for the PIC, and look at the PORTC:

Notice how this is only 7 bits. These bits control which outputs are on at a time. We’re only concerned with the first 4 bits, because we only have 4 lights plugged into the PIC. Now let’s look at the relevant code for the rotate that sets what light to put on:

 bcf STATUS,C ; ensure the carry bit is clear
rrf Display,f
btfsc STATUS,C ; Did the bit rotate into the carry?
bsf Display,3 ; yes, put it into bit 3.

Basically, what this does is it clears the carry bit, which is in the STATUS register. Now, we rotate the Display variable to the right, after moving it into f. Let’s step through this from the starting point, where Display has the value of 0x8(note that the Microchip code has this as 0x08, however only one byte is relevant and needed, since PORTC is only 8 bits(1 byte) wide). The next part shows only the last 4 bits of the byte, as those are the only relevant bits for this example.

1000 ;display at beginning
0100 ;rotate display to right, in C this would be Display >> 1
;is there anything in the carry bit? no, don't put anything in bit 3
0100 ;display next loop
0010 ;display after rotate
;is there anything in the carry bit? no, don't put anything in bit 3
0010 ;display next loop
0001 ;display after rotate
;is there anything in the carry bit? no, don't put anything in bit 3
0001 ;display next loop
0000 ;display after rotate
;is there anything in the carry bit? yes, set bit 3
1000 ;display at end. repeat

Now back to our original question, which was how to set multiple lights to be on? Well, we need to do basically the same thing that we did for the rotate. We make a variable, and then we load the [i]variable[/i] with the hex value of what two lights we want on.

cblock 0x20
Display
endc

org 0
Start:
bsf STATUS,RP0 ; select Register Page 1
clrf TRISC ;set all IO pins C to output

bcf STATUS,RP0 ; back to Register Page 0
movlw 0xA ;1010 binary. Lights DS2 and DS4
movwf Display
movf Display,w
movwf PORTC
goto $ ; wait here
end

Simple once you understand it.

Leave a Reply

Your email address will not be published.