$30
PART 1)
The first part is to implement a basic program to input a number from DIP switches, take its 1’s complement and display the result out to the LEDs:
C Code:
void main()
{ char InA;
char Result;
ADCON1
= 0x0f;
TRISA
= 0xff;
// make sure PORT A is input
TRISB
= 0x00;
// make sure PORT B is output
TRISC
while (1)
{
= 0xff;
// make sure PORT C is input
InA
= PORTA;
InA
= InA & 0x0F;
Result = (1’s) InA;
PORTB = Result;
Use the lab3 Part 2) as a baseline for the implementation of this part. Modify it to add the following handling:
1) Declare the two variables ‘InA’ and ‘Result’ as two memory locations. 2) Read the content of PORTA into register W
3) Mask in the lower 4-bit of W with the constant 0x0F by using the instruction
ANDLW.
4) Store the result into the variable InA (a memory location)
5) Perform the 1’s complement of the variable InA through the use of the
‘COMF’ instruction. Use the option to store back to W instead of memory (COMF InA, 0)
6) Mask in the lower 4-bit of W using ANDLW.
7) Next, use ‘MOVWF’ to output to the variable ‘Result’.
8) Finally, use ‘MOVFF’ to get the content of ‘Result’ into ‘PORTB’. 9) Branch back to the step 2) to make the operation an infinite loop
When done, use the 4 switches connected to PORTA to set a number. Observe the result being displayed on the PORTB that should show the 1’s complement of the number specified by the DIP switches.
Make sure that the connections of the DIP switches and the LEDs are implemented such a way that the MSB (most significant bit) of the number is on the leftmost side while the LSB is on the rightmost side. Also, don’t forget that when a switch is turned ON, this means logic 0 and when it is off, the logic is 1.
PART 2)
Take the implementation in Part 1) and add the following test condition between steps 8) and step 9) above;
a) If the ‘Result’ is 0, then PORT E bit 1 will be set to 1
b) Else that same bit is reset to 0.
void main()
ADCON1
= 0x0f;
TRISA
= 0xff;
// make sure PORT A is input
TRISB
= 0x00;
// make sure PORT B is output
TRISC
while (1)
{
= 0xff;
// make sure PORT C is input
InA
= PORTA;
InA
= InA & 0x0F;
Result = (1’s) InA;
PORTB = Result
if (Zero flag == 1) PORTE = 0x02; // Set PORTE bit 1 to 1
else PORTE = 0x00; // Set PORTE bit 1 to 0
In this exercise, we will add another test after the completion of the Complement operation. We need to check if the Zero (Z flag) is set through the use of the instruction BZ. If Z flag is 1, BZ will force a jump to a label where PORTE bit 1 is set to 1. If Z flag is 0, the instruction just below the BZ instruction will be executed. There clear PORTE bit 1 to be 0.
When done go back to the main loop using the ‘GOTO MAIN_LOOP’ code.
To set a bit ‘x’ of a PORTy, you will use the instruction ‘BSF PORTy,x’. To clear a bit ‘x’ of a PORTy, use ‘BCF PORTy,x’.
The example below will show a typical implementation:
BZ LABEL1
( Place instruction here to clear PORTE bit 1 to 0)
GOTO LABEL2
LABEL1:
(Place instruction here to set PORTE bit 1 to 1) LABEL2:
GOTO MAIN_LOOP
When done, implement, compile and test the code on the board. Input a number such that the result displays 0 and the Z flag LED is turned on.
PART 3)
We will now implement a new operation that will add two numbers. Copy the routine developed in part 2). Add codes to read a second input from PORTC and stored it into the variable ‘InC’. Next, perform an addition between the two inputs ‘InA’ and ‘InC’ and stored the result into ‘Result’. Also, display the result into PORTB.
void main()
{ char InA; char InC;
char Result;
ADCON1
= 0x0f;
TRISA
= 0xff;
// make sure PORT A is input
TRISB
= 0x00;
// make sure PORT B is output
TRISC
while (1)
{
= 0xff;
// make sure PORT C is input
InA
= PORTA;
InA
= InA & 0x0f;
InC
= PORTC;
InC
= InC & 0x0f;
Result = InA + InC;
PORTB = Result;
if (Zero flag == 1) Set PORTE.bit1 to 1 else Clear PORTE.bit1 to 0
Use the instruction ‘ADDWF f,0’ where f is the memory location that has the value to add to the register W.
When completed, set two numbers for inputs on the DIP switches and check the result shown on the 5 LEDs connected to PORTB. The fifth LED of PORTB will show the overflow of the result of the addition of two 4-bit numbers.
PART 4)
Replace the ADD operation on part 3) by doing the ‘AND’ operation with the instruction ‘ANDWF f,0’. Verify that the operation is implemented properly.
PART 5)
Replace the ADD operation on part 3) by doing the ‘OR’ operation with the instruction ‘ORWF f,0’. Verify that the operation is implemented properly.
PART 6)
One last routine is to take a 4-bit input number and convert into a BCD number which is the decimal equivalent of the input number.
To do the conversion, the input number is checked against the value 0x09. If it is greater than 9, then add a constant 0x06 to it. If it is less than 9, then no addition of the constant is needed. For example:
a) If input = 0x08, then output = 0x08 (no change)
b) If input = 0x0b, then output = 0x0b + 0x06 = 0x11. 0x0b has the decimal equivalent of 11. This will the number 11 which is the decimal equivalent of
0x0b
c) If input = 0x0d, then output = 0x0d + 0x06 = 0x13 because 0x0d is 13 in decimal.
To implement the operation, here are some steps:
a) Read the input into the variable ‘InA’
b) Load a constant 0x09 into W
c) Use the instruction CPFSGT (see reference) to compare the value in ‘InA’ against the W register (that contains 0x09). If ‘‘InA’is greater than 0x09, the next instruction below this instruction is executed. Otherwise, the next instruction is skipped:
CPFSLT InA, 1
(go here if greater or =)
(go here if less)
PART 7)
Take the basic code of each of the five functions implemented above and group them into five different sets of code. Call each group by the name of the function it performs like:
SUBROUTINE_COMP:
SUBROUTINE_ADD:
SUBROUTINE_AND: SUBROUTINE_OR:
SUBROUTINE_BCD:
At the end of each group where the instruction ‘GOTO MAIN_LOOP’ is called, replace that line by the line ‘RETURN’.
Here is a typical implementation:
SUBROUTINE_ COMP:
(code from the COMP implementation)
RETURN
SUBROUTINE_ ADD:
(code from the ADD implementation)
RETURN
Next, start at the beginning of the program with a basic loop that will constantly check three new switches connected to PORTD bits 2 and 0. These three switches will select what function to execute as follows:
PORT D Action
Bit_2 Bit_1 Bit_0
0 0 0 1’s complement
0 0 1 ADD operation
0 1 0 AND operation
0 1 1 OR operation
1 x x BCD conversion
Use the ‘BTFSC’ instructions to do the decoding of the five tasks to jump to. Once the differentiation is done, we will have five different labels, each for each task. At each task, first use the BCF and BSF to set the three bits 5-7 of the PORTD to show what routine is being executed. For example, task ‘001’ is for the ‘ADD’ function. The LEDs connected to PORTD bits 4-6 should also show the value ‘001’. Next, use the ‘CALL’ instruction to call the respective subroutine that was created for each task. It will force the execution of the appropriate routine for that task. After the ‘CALL’ was executed, a GOTO
MAIN_LOOP instruction should be called in order to go back to the main loop. Here is a typical implementation:
MAIN_LOOP:
BTFSC
PORTD, 2
; test bit 2 of PORT D
GOTO
PORTD1xx
; if fall here then bit is set to 1
GOTO
PORTD1xx:
PORTD0xx
; if fall here then bit is set to 0
GOTO
TASK_BCD
; if fall here, bit 2 of PORTD is set
; to 1, go to place to execute
; BCD operatio
; if fall here, bit 2 of PORTD is set
; to 0, now we have to check bit 1
BTFSC
PORTD, 1
; test bit 1 of PORTD
GOTO
PORTD01x
; if fall here then bit 1 is set to 1
GOTO
PORTD01x:
PORTD00x
; if fall here then bit 0 is set to 1
BTFSC
PORTD, 0
; test bit 0 of PORTD
GOTO
…
GOTO
PORTD00x:
…
BTFSC
PORTD, 0
; test bit 0 of PORTD
GOTO
…
GOTO
TASK_COMP:
BCF PORTD, 7
BCF PORTD, 6
BSF PORTD, 5
CALL SUBROUTINE_COMP
GOTO MAIN_LOOP
TASK_ADD:
BCF PORTD, 7
BSF PORTD, 6
BCF PORTD, 5
CALL SUBROUTINE_ADD
GOTO MAIN_LOOP
Note: PORTD has a mixture of inputs and outputs. The first three bits are used as inputs to read in the operation to be executed. The three bits 5-7 are setup as outputs to show what function is being executed. Make sure that the TRISD register is setup properly in order to reflect this condition.
Once this part is completed, demonstrate using the three switches on PORT D bits 0 through 2 to select an arithmetic/logical operation, then select the inputs and check that the outputs are correct. Also, verify that the Z Flag LED does reflect the proper result.