How do I set only the 4 LSB of a port byte by reading 4 bits from an arry?
I read 4 bits from an arry and want to set the according 4 output ports, without affecting the 4 other ports.
I don't want to use if then statements and PORTA.Fx
Is this possible?
Logical BIT setting
-
- Posts: 1179
- Joined: 24 Nov 2005 20:07
- Location: Colorado, USA
You apply a "bit mask" by using the bit-wise AND (&) and bit-wise OR (|) operators. Use the AND operator to clear bits, and the OR operator to set bits.
Check the help file for more info.
Or this: http://en.wikipedia.org/wiki/Bit_mask
Check the help file for more info.
Or this: http://en.wikipedia.org/wiki/Bit_mask
-
- Posts: 17
- Joined: 30 Mar 2009 21:03
-
- Posts: 1179
- Joined: 24 Nov 2005 20:07
- Location: Colorado, USA
Yes this is the idea. The best way to do what you want is to create a shadow register for manipulating the port state. This register is a normal declared variable of char size and always holds the current state of the port. Think of it as a scratch pad for writing to the port.
Example:
The PIC needs to start out with an initial state of 11101001
Now you want to clear bits 1 and 4 and leave the rest unchanged
To set bits 2 and 3
There is another way to do this kind of port manipulation, it's called the read-modify-write method (RMW).
However it has to be done carefully because it can give you back erroneous results. I don't recommend using it.
The difference between the above code and RMW is that you first "read" the port into the shadow register. The problem with this step is the PIC reads the actual logic state on the port pins, not the output latch register. If the port pins are not sufficiently pulled high or low the value read can be wrong. This is especially troublesome if for example you are driving a MOSFET transistor. The MOSFET gate is a capacitor and depending upon the previous logic state it will be either charging or discharging. So when the PIC actually reads the port, the voltage on this gate may be somewhere between a logic high or logic low. So as you can see the result can be erroneous. Sometimes it's correct other times it's not.
The RMW example:
Now you want to clear bits 1 and 4 using RMW and leave the rest unchanged
Example:
The PIC needs to start out with an initial state of 11101001
Code: Select all
char ShadowReg_B;
ShadowReg_B = 0b11111001; // load shadow register variable with port initial state
PORTB = ShadowReg_B; // write it port B
Code: Select all
ShadowReg_B = ShadowReg_B & 11110110; // apply AND bit mask
PORTB = ShadowReg_B; // port B now is 11110000
Code: Select all
ShadowReg_B = ShadowReg_B | 00000110// Apply OR bit mask
PORTB = ShadowReg_B; // port B now is 1110011
However it has to be done carefully because it can give you back erroneous results. I don't recommend using it.
The difference between the above code and RMW is that you first "read" the port into the shadow register. The problem with this step is the PIC reads the actual logic state on the port pins, not the output latch register. If the port pins are not sufficiently pulled high or low the value read can be wrong. This is especially troublesome if for example you are driving a MOSFET transistor. The MOSFET gate is a capacitor and depending upon the previous logic state it will be either charging or discharging. So when the PIC actually reads the port, the voltage on this gate may be somewhere between a logic high or logic low. So as you can see the result can be erroneous. Sometimes it's correct other times it's not.
The RMW example:
Code: Select all
char ShadowReg_B;
ShadowReg_B = 0b11111001; // load shadow register variable with port initial state
PORTB = ShadowReg_B; // write it port B
Code: Select all
ShadowReg_B = PORTB // >>> The READ step <<<
ShadowReg_B = ShadowReg_B & 11110110; // apply AND bit mask >>> the MODIFY step <<<
PORTB = ShadowReg_B; // port B now is 11110000 >>> The WRITE step <<<