Setting a bit within a byte
To set a bit to 1 use the OR operator.The OR operator is similar to the ADD operator in that it takes two arguments and produces a result.
The XCSB OR operator is the '|' (vertical bar) character
BEWARE: XCSB has both a bitwise OR operator and a logical OR operator. The logical OR operator is '||' (two vertical bar characters).
How it works
The OR operator forces a 1 in a column where a 1 exists in either the first argument or the second argument.e.g.Written in XCSB this would be
argument 1 0 0 1 0 0 1 0 0 argument 2 0 0 1 0 0 0 0 1 result 0 0 1 0 0 1 0 1 ARG1 = 0x24 ARG2 = 0x21 result = ARG1 | ARG2 // this could be written using constants as result = ARG1 | 0x21 // or as result = 0x24 | ARG2The above example shows the result of a bitwise OR operation.Setting bits within an existing variable or output PORT is achived by assigning the result back to one of the arguments
PORTA = PORTA | 0x21This is equivalent to forcing bits 0 and 5 to 1 in PORTAClearing a bit within a byte
To set a bit to 0 use the AND operator.The AND operator is similar to the ADD operator in that it takes two arguments and produces a result.
The XCSB AND operator is the '&' (ampersand) character
BEWARE: XCSB has both a bitwise AND operator and a logical AND operator. The logical AND operator is '&&' (two ampersand characters).
How it works
The AND operator forces a 0 in a column where a 0 exists in either the first argument or the second argument.e.g.Written in XCSB this would be
argument 1 0 1 0 0 1 0 0 0 argument 2 0 1 0 0 0 0 1 0 result 0 1 0 0 0 0 0 0 ARG1 = 0x48 ARG2 = 0x42 result = ARG1 & ARG2 // this could be written using constants as result = ARG1 & 0x42 // or as result = 0x48 & ARG2The above example shows the result of a bitwise AND operation.Clearing bits within an existing variable or output PORT is achived by assigning the result back to one of the arguments
PORTA = PORTA & 0x42This is equivalent to forcing all bits except bits 1 and 6 to 0 in PORTAThis turns out to be difficult to visualise. It would be much simpler if we could force all bits represented by 1 to 0;
This is actually very easy to accomplish if we use the bitwise NOT operator. The XCSB bitwise NOT operator is the '~' (tilda) character (NOTE: this operator only takes one argument, it is like placeing a minus in front of an expression to change the sign of the result)
PORTA = PORTA & ~0x42This is equivalent to forcing bits 1 and 6 to 0 in PORTA(see a more detailed explanation of AND operator)
The XCSB bitwise NOT operator has the effect of changing all ones to zeros and all zeros to ones
e.g.
argument 0 1 0 0 0 0 1 0 result 1 0 1 1 1 1 0 1 Using bit numbers instead of masks
Instead of using a bit mask such as 0x40 it is possible to use a bit number to address a bit within a byte. For any memory location (including PORTA) the bits within the location are numbered as:
7 6 5 4 3 2 1 0 To set bit 6 of PORTA to 1 we could use the XCSB statement
PORTA = PORTA | (1 << 6)XCSB is actually clever enough to realise what it meant and it will generate the single PIC instruction to perform the operationbsf PORTA,6To set bit 6 of PORTA to 0 we could use the XCSB statementPORTA = PORTA & ~(1 << 6)Again XCSB is clever enough to realise what it meant and it will generate the single PIC instruction to perform the operationbcf PORTA,6The advantage of using bit numbers over simple masks is not clear from these simple examples. The fact is that in some circumstances it is much simpler to perform calculations on bit numbers than it is on masks. Consider the situation where you need to store a PORT address and a bit within the port in a table so that you can step through the table turning PIN's on and off. If you use a mask you will also need to store the address of the port along with the mask. If you store a bit number you can code this into 3 bits (0 to 7) which leaves the remaining 5 bits available for use as a port number.for j=0 while j<64 step j+=1 do acc = tbl[j] bit_number = acc & 7 port_number = acc >> 3 PORTA[port_number] = PORTA[port_number] | (1 << bit_number) wait() doneBits and Masks
BITS HEX Bit 7 6 5 4 3 2 1 0 Expr 0 0 0 0 0 0 0 0 0x00 (0 << 0) 0 0 0 0 0 0 0 1 0x01 (1 << 0) 0 0 0 0 0 0 1 0 0x02 (1 << 1) 0 0 0 0 0 1 0 0 0x04 (1 << 2) 0 0 0 0 1 0 0 0 0x08 (1 << 3) 0 0 0 1 0 0 0 0 0x10 (1 << 4) 0 0 1 0 0 0 0 0 0x20 (1 << 5) 0 1 0 0 0 0 0 0 0x40 (1 << 6) 1 0 0 0 0 0 0 0 0x80 (1 << 7)