2
\$\begingroup\$
        PORTCbits.RC13 = 1;
        PORTDbits.RD0 = 1; 
        PORTDbits.RD11 = 1;
        PORTDbits.RD9 = 1; 

The lines above will turn off an LED. One at a time, they all work, but if I use all 4, they will leave one on for some reason!

I can re-arrange them and it is a different LED. It always seems to leave on the 2nd to last entry. Why?

\$\endgroup\$
4
  • \$\begingroup\$ Okay it works when I use the latch instead of port for all of them (i.e. LATCbits.LATC13). Why is this? \$\endgroup\$
    – dansch
    Commented Oct 26, 2015 at 18:06
  • \$\begingroup\$ Are you using a breadboard, or are these LEDs pre-soldered on your microcontroller's PCB? \$\endgroup\$
    – Dr. Funk
    Commented Oct 26, 2015 at 18:33
  • \$\begingroup\$ Which port's led is left on? \$\endgroup\$
    – user86234
    Commented Oct 26, 2015 at 18:52
  • \$\begingroup\$ I can re-arrange the lines and it's always the 2nd to last. It's something to do with using PORT instead of LATCH, cuz LATCH works fine. \$\endgroup\$
    – dansch
    Commented Oct 26, 2015 at 18:56

2 Answers 2

5
\$\begingroup\$

You are running into the read-modify-write issue when writing to the port register.

Each line of C code most likely produces a bit setting instruction. Those instructions read the whole register they operate on, set the specified bit, then write the whole word back. This has a side affect on I/O ports of freezing any of the bits you're not setting at whatever state they were read at.

Let's say in one cycle you do BSF PORTB,0. That starts the output drivers going high. If in the next cycle you do BSF PORTB,1, then it will first read what the pins state of RB0 actually is, not what you set it to in the previous instruction. If the external circuit keeps the port pin from going high fast enough, it will still be 0 when read by the second instruction. Since that instruction isn't operating on that bit, it will write it back the way it found it, which is 0. Now the RB0 pin will be driven actively low again.

The best way around this is to do the bit manipulation instructions on the LAT register, if this PIC has them. If you need to do a bunch of pin settings on a port at a time, read the port, do all the settings on the local copy, then write that back to the port once. Or, leave enough time before read-modify-write operations on port registers so that the actual pin voltage has stabalized.

Some knee-jerkers are sure to say that you should always use shadow registers, but that is usually unnecessary and way more than needed. I've done well over 100 PIC projects, and I don't think I've used shadow registers to get around port R-M-W issues once. Once you understand what is going on, a little common sense goes a long way.

\$\endgroup\$
1
\$\begingroup\$

PICs have three different registers for their digital I/Os:

TRIS defines if a pin is an input or output
PORT reads the digital level from a pin
LAT writes a digital level to a pin

(I keep the names short here. You have to add a port to address the entire port or that bits identifier to address single output pins...)

I wonder that writing to PORT has any effect, but the correct way to set an output is writing to LAT.

By the way: PORT and LAT are independent. Reading LAT tells you what the logic level should be, if the pin is configured as output, while reading PORT tells you the actual status. If PORT and LAT don't give the same reading, the pin may be configured as input, or the pin may be tied to a logic level by a short circuit.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.