Connect with us

Writing PIC port bits

Discussion in 'Electronic Design' started by Mike Young, Oct 23, 2005.

Scroll to continue with content
  1. Mike Young

    Mike Young Guest

    Going through some very early PIC code, I came across a really ugly fix I
    made and have been quietly using since. There was some flakiness writing
    output port bits individually, and so I just buffered the entire word in RAM
    and wrote the entire PORT each time. It sucks, but got the job done. Undoing
    the hack just now, writing a single bit, say RC0 = 1, resets the other pins.
    WTF? The compiler is HiTech's PICCLITE, although I don't think it matters.
    The disasssembly shows the expected "BSF 0x7, 0". Having pulled a bit of
    hair and lost a bit of sleep over this, I just stuck that little "gem" of
    hack into everything I did since. Now it's time to get rid of it.

    My expectation is that writing an output port should be routinely possible,
    and unusual "side-effects" such as I saw would be show stoppers. Anyway, I
    don't know where the fault is. It could be the compiler's IRQ state pushing,
    but that doesn't make sense. I could write the simplest test program on
    earth to set a few bits, but thought I would start by asking here.
    (Actually, this isn't the beginning. The beginning caused me to lose a
    fistful of hair and some sleep.)
  2. Undoing

    It's called using a shadow register. It's actually the best way to do

    If you diddle a single bit on a port, you can run into the dreaded RMW
    (read modify write) issue. In order to change just one bit, the PIC has
    to read the whole port value, change the bit and write the whole port
    value back. The problem lies in reading the port bits. The actual pin
    state gets read and not the port latch register. This can be a real
    problem if the pins are heavily loaded and/or the PIC is running at
    higher clock speeds. Search Google for more than you ever wanted to
    know about this stuff.
    Good luck, but I don't think you will likely succeed. Stick with using
    a shadow register to hold the pin values, it's one less thing to worry
    This is a common pitfall with PICs.
  3. Mike Young

    Mike Young Guest

    Thanks; that helps more than you know. BTW, was your closing remark about
    PICs in regard to RMW? or to hair and sleeplessness?
  4. As someone else said, this is normal and your fix is SOP. It can lead
    to all sorts of unpleasant bugs if you're not a bit careful.

    Later PICs such as the 18F series have a second port memory location
    (called LATx rather than PORTx) that reads the latch output rather
    than the current port pin levels, and thus makes RMW instructions work
    the way you would probably expect.

    Best regards,
    Spehro Pefhany
  5. 'Read, modify, write'.
    If you do a bit set/clear on a bit in the port, the port itself is
    physically 'read', the bit is toggled, and the result written back to the
    output. The problem is that if (for instance), the pins have a heavy load,
    and though driven 'high', do not reach the voltage that the input sees as
    the 'high' level, the bit concerned will be read as a '0', not a '1', and
    written back with the wrong value. This example would be in a sense an
    'overload' condition on the output concerned, but can be met on a quite
    reasonably loaded pin, if there is a some capacitance present. The actual
    'write' to the port takes place in the last clock cycle of the
    instruction, while the 'read' takes place in the first clock cycle. So if
    you perform two successive I/O operations, setting (say) bit 0, then bit
    1, on the second operation, there will only be one cycle of the processor
    clock, since bit 0 was nominally 'set', and it is common to find that the
    combination of load capacitance and gate drive limits, have not allowed
    the pin to reach the desired level in this time.
    It is inherent in the fact that there is only the port itself, and not a
    seperate output latch.
    The 18 family chips have a 'shadow register', to allow this to be avoided.
    On the older chips, doing it in software, or allowing enough time for the
    pins to correctly reach the required level, are well documented 'fixes'
    (MicroChip describes this problem comprehensively in a couple of their
    application notes).

    Best Wishes
  6. On the older chips, doing it in software, or allowing enough time for the
    Time will never be enough when the pin is loaded enough to prevent it
    from reaching the desired level. on the 12 and 14 bit cores a shadow
    register is realy the only solution.

    Wouter van Ooijen

    -- ------------------------------------
    Webshop for PICs and other electronics
    Teacher electronics and informatics
  7. Particularly for open-drain outputs. This one is an accident waiting
    to happen:

    Port pin -----[R]-----|<|---- Vcc

    Why does it work with a red LED, but not with a green one? ;-)

    Best regards,
    Spehro Pefhany
  8. It doesn't? Why not? As long as there is a reasonable value resistor,
    shouldn't the PIC be able to pull the pin all the way to ground?
  9. Sure, but the LED may not reliably pull it all the way to '1'. RMW
    will then drive a '0' to the port pin, even if the LED is "off".
  10. Works fine in that direction, but with an open-drain port pin, the
    LED+resistor (depending on LED Vf and supply voltage) may not be able
    to pull up the output pin above the "1" threshold.

    Best regards,
    Spehro Pefhany
  11. Yes, what he said.

    Best regards,
    Spehro Pefhany
  12. And the LED will not be lit. Did you intend something else? Are you using
    the LED as an input device?
  13. Doh, I get it now. I wasn't looking at that end of things. ;-)
  14. Suppose that the above port pin is open-drain, with the LED connected
    as above. Suppose the LED has been successfully turned off some time
    ago (long enough for the voltage to settle out) by a bsf instruction
    (bit set) operating on the port.

    Now suppose that we try to modify another bit of the same port.. with,
    for example, a bsf or bcf instruction (or other RMW instruction). The
    RMW instruction first reads the entire port (input levels, not latch),
    modifies only the bit in question, then writes it back to the latch.
    If the open drain *output* was not pulled up to a "1", then the R part
    of the RMW instruction reads a "0" and writes that (unmodified) back
    to the latch. The LED then turns "on", which is probably not what you

    This can be "fixed" with a resistor across the LED, but then you can
    run into a potential time issue, as I implied in the first paragraph.
    If the instruction to turn the LED off is too close (time-wise) to the
    next RMW instruction on the same port for the stray capacitance to be
    charged reliably to the "1" level then you can have the same thing

    Best regards,
    Spehro Pefhany
  15. Don Foreman

    Don Foreman Guest

    Red LED's have lower on-voltage than green ones.
  16. keith

    keith Guest

    A *little* (blue ones are higher), and that's why the statement (above):

    "Why does it work with a red LED, but not with a green one?"
  17. keith

    keith Guest

    It's always the end you're not looking at that you get kicked in! ;-)

    There's a bunch of other usefull stuff (much learned the hard way) in this
    thread too.
Ask a Question
Want to reply to this thread or ask your own question?
You'll need to choose a username for the site, which only take a couple of moments (here). After that, you can post your question and our members will help you out.
Electronics Point Logo
Continue to site
Quote of the day