Logical And Arithmetic Operators
Here, we are going to examine how to manipulate individual bits, perform some simple arithmetic, and data tables.
In the last tutorial we introduced the Exclusive OR function. The ExOR function is known as a logical operator. In this tutorial We are going to explain the other logical operators that the PIC supports. There won’t be any example programs, but We will explain how to use the operators by using small sections of code.
The AND function simply compares two bits and produces a 1 if they are the same, and a 0 if they are different. For example, if we said 1 AND 1, the result is 1, whereas if we said 1 AND 0 the result will be 0. Of course, we can compare words as well, and all the AND function does is compare the two words bit by bit. The example below shows two 8-bit words being ANDed along with the result:
As you can see, the result will only have a 1 when two 1s coincide with each other in the two words. We can use the AND function to check the ports, for example. If we are monitoring some I/O pins which are connected to a circuit, and we need to monitor a certain condition where only some of the pins are high, then we can simply read the port, and then AND the result with the condition we are checking for, just like the example above.
The PIC gives us two flavors for AND. They are ANDLW and ANDWF. ANDLW allows us to perform an AND function with the contents of the W register, and a number that we specify. The syntax is:
ANDLW <number> where <number> is what we will AND the contents of W with. The result of the AND function will be stored back into the W register.
ANDWF allows us to perform an AND function on the W register and another register, such as a PORT. The syntax is:
ANDWF <register>,d where <register> is the register we are interested in, e.g. PORTA, and d tells the PIC where to place the result. If d=0, the result is placed in the W register, and of d=1 the result is stored in the register we specified.
The two sections of code below show an example of each AND function. The first is checking the status of the PORTA, where we need to see if the inputs are 1100. We will put the result back into the W register:
The second example will now check the contents of the W register:
We have already come across one OR function, namely the XOR. This produced a 1 if two bits are different, but not the same. There is a second OR function called IOR, which is the inclusive OR. This function will produce a 1 if either bit is a 1, but also if both bits are 1. Below is a simple truth table to demonstrate this:
A B O/P
0 0 0
0 1 1
1 0 1
1 1 1
This function does exactly what it says. It adds two numbers! If the result of adding the two numbers exceeds 8 bits, then a CARRY flag will be set. The CARRY flag is located at address 03h bit 0. If this bit is set, then the two numbers exceeded 8 bits. If it is a 0, then the result lies within 8 bits.
Again, the PIC gives us two flavors of ADD, namely ADDLW and ADDWF. As you may have guessed, this is very similar to the above function. ADDLW adds the contents of the W register to a number that we specify. The syntax is:
ADDWF will add the contents of the W register and any other register that we specify. The syntax is:
ADDWF <register>,d where <register is the register we specify and d tells the PIC where to place the result. If d=0, the result is placed in the W register, and is d=1 it placed in the register that we specified.
Now, We bet you can’t guess what this function does! Yes, you guessed it, this function subtracts one bit from another. Once again the PIC gives us two flavors: SUBLW and SUBWF. The syntax is exactly the same as for the ADD function, except of course you type SUB instead of ADD!
If we wanted to add 1 to a number in the PIC, we could just simply use the ADD function, and use the number 1. ~The problem with this is that we have to first put the number into the W register, then use ADDLW 1 command to increment it. If we wanted to add 1 to a register, it is even worse. We first have to put the number 1 into the W register, then use ADDWF <register>,1. So, for example, to add 1 to location 0C, say, we would have to have the following section of code:
There is a better way of doing this. We can use the command INCF. The syntax is:
INCF <register>,d where <register> is the register, or location, that we are interested in, and d tells the PIC where to place the result. If d=0, the result is in the W register, and if d=1, the result is placed in the register we specified. By using this single instruction we can literally half the coding. If we wanted the result put back into the W register, then using the example above, we would have had to add another command to move the contents of 0C back into the W register, and then put the 0C register back to whatever it was.
There is another increment command. It is INCFSZ. This command will increment the register that we specify, but if we the register equals 0 after the increment (which will happen when we add 1 to 127) then the PIC will skip the next instruction. The section of code below demonstrates this:
Loop incfsz 0C
Rest of program.
In the above section of code, 0C will be incremented by 1. We then have an instruction that tells the PIC to go back to our label called Loop, and increment 0C by 1 again. This carries on until 0C equals 127. This time, when we increment 0C by 1, 0C will now equal 0. Our INCFSZ instruction will then tell the PIC to skip the next instruction, which in this case is the goto statement, and so the PIC will continue with the rest of the program.
We have already covered the decrement function in previous tutorials, so we won’t repeat myself here.
The last instruction in this group will invert all of the bits in the register that we specify. The syntax is:
COMF <register>,d where <register is the register that we want to invert, and d will tell the PIC where to store the result. If d=0, the result is stored in the W register. Id d=1, the result is stored back into the register we specified. The following example shows this instruction in action:
0C = 11001100
0C = 00110011
This could be use, for example, to quickly turn the pins of a port from output to input and vice-versa.