I am working with PIC18f4550 micro controller . i have connected a lcd in 4 bit mode to port d<1:4> pins .So how can i send data only to the 4 bits of port d <1:4> register without affecting (port d0,d6,d7 ) bit values.

  • 2
    \$\begingroup\$ -1 for messy question. You won't tell us what PIC (does it have LAT registers, for example), clearly haven't even looked at the datasheet, and bits "<1:5>" (ususally written <5:1>) is five bits, not four. \$\endgroup\$ – Olin Lathrop Jun 11 '13 at 13:27
  • \$\begingroup\$ -1 Too confusing...please revise. \$\endgroup\$ – fuzzyhair2 Jun 11 '13 at 13:35

There are five approaches that may be used on the PIC18Fxx parts to change some set of bits in a register.

  1. Read LATx into W, mask off the proper bits and compute the proper value, then write the value back. This will update all bits cleanly, but requires that no interrupt can write any part of the register. All bits will update simultaneously.

  2. Load W with the bits that aren't of interest, ANDWF the bits onto the register, load W with the desired values of the bits of interests, and IORWF the bits into the register. All bits of interest will be cleared simultaneously, and then all such bits that should be set will be set simultaneously. Interrupts may safely affect other bits of the register, or may modify bits of interest in the same way the main-line code is doing.

  3. As above, but IORWF all the bits of interest, and then ANDWF with the a value that has all bits set except those bits of interest that should be cleared. All bits of interest will be set simultaneously, and then all bits of interest that shouldn't be set will be cleared simultaneously. Interrupts may safely affect other bits of the register, or may modify bits of interest in the same way the main-line code is doing.

  4. Load W with the value of the register, XOR W it with the values of the bits of interest, AND W with the bits of interest, and then XORWF back to the register. This will perform all updates simultaneously. Interrupts may safely affect other bits of the register, but interrupts which change any bits of interest may have weird effects, even if the changes match what the main-line is trying to do.

  5. Use a sequence of BSF/BCF instructions to modify bits as needed. This approach will affect only the proper bits; the updates won't be simultaneous, but will avoid any inappropriate edges; combining main-line and interrupt operations won't have any odd side-effects.

Approaches #1 and #4 generate perfectly clean output; only approach #4 can safely be used with interrupts. If the program were written in assembly language, approach #1 could safely interact with interrupts if code were written as something like:

UpdateBits: ;  Call from main-line to write bits 0-3
  movf   LATA,w,c
  andwf  0xF0
  iorwf  NewLowerBits
  bsf    PortAWFlag,0,c
  mowwf  LATA,c
  bcf    PortAWFlag,0,c

  movwff WREG,SAVED_W
  ...  ; Code to write bits 4-7
  movf   _LATA,w,c
  btfsc  PortAWFlag,0,c
   movf  SAVED_W,w,c
  andlw  0x0F
  iorwf  NewUpperBits
  movwf  _LATA,c
  btfsc  PortAWFlag,0,c
   movwf SAVED_W,w,c
  movff  SAVED_W,WREG

I don't know that I've ever encountered any scenarios where this approach would be better than simply disabling interrupts before updating the port bits in the main-line, but if there's interrupt code that simply cannot abide the possibility of being delayed by about six cycles while the main-line updates the port, the above approach could work.


The process is very simple:

  1. Read the datasheet.

  2. Do what it says.

After step 1, you will notice several things:

  1. The PIC has instructions that can set or clear individual bits in any register, including a port register. Look up BCF and BSF.

  2. Even without bit manipulation instruction, you can still set or clear individual bits in a byte by performing ORing and ANDing. For example, ORing with binary 00101100 will set bits 5, 3, and 2. Likewise, ANDing with 00101100 will clear bits 7, 6, 4, 1, and 0.

  3. This PIC has a LAT register for each port. That allows performing read-modify-write operations like AND, OR and bit set/clear without inadvertantly using the actual pin values as input, as apposed to the value you last tried to set the port to. In your case, it seems you want to perform your operations on the LATD register instead of the PORTD register.


The OP tagged this question with [C]. So I'm going to assume they are using the C18 compiler. I think the easiest ways to access bits in a register is to use the types that are defined in the device header file for your processor. In your case that would be "P18f4550.h".

You can write the bits individually using LATDbits.LATD1, LATDbits.LATD2, LATDbits.LATD3, LATDbits.LATD4.

To write them all at once use a mask like LATD |= (newValue & 0x1E).

Reading individual bits uses similar nomenclature (PORTDbits.RD1).


I agree with Olin. Just want to add this:

If you don't understand how to use these instructions, you can check out the documentation of programming language which you use.

  • \$\begingroup\$ Olin is talking about assembly language, and these instructions are documented in the datasheet, which he already said to read. \$\endgroup\$ – The Photon Jun 11 '13 at 21:26
  • \$\begingroup\$ I know that. But pic programming by using C language and variations is very frequent nowadays. In such situation, one does not simply read the datasheet and implement it by using high level language. He should also read the documentation of that high level language. \$\endgroup\$ – agy Jun 12 '13 at 11:53

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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