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.
There are five approaches that may be used on the PIC18Fxx parts to change some set of bits in a register.
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.
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.
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.
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.
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 Interrupt: 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 retfie
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:
- Read the datasheet.
- Do what it says.
After step 1, you will notice several things:
- The PIC has instructions that can set or clear individual bits in any register, including a port register. Look up BCF and BSF.
- 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.
- 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).