'P18F4420 Switch case statement in PIC assembly language
Im using a PIC18 on Mplab IDE in Assembly language where I have four LEDs. 2 LEDs tell me the status #1 and the 2 other LEDs the status #2. Finally, I have 2 more output LEDs to tell me the status of these 4 LEDs based on their status. This can be done using a switch statement to check the 4 LEDs' status and thus have the output led green or red. Each LEDs is connected to different Ports pins in the PIC18f as well the output LEDs to other pins. The final output leds will be based on the four leds status
| sat#1 Red | sat#1 Green | sat#2 Red | sat#2 Green | out Red | Out Green | |
|---|---|---|---|---|---|---|
| 1 | 0 | 0 | 0 | 0 | 0 | 0 |
| 2 | 0 | 0 | 0 | 1 | 0 | 1 |
| 3 | 0 | 0 | 1 | 0 | 1 | 0 |
| 4 | 0 | 1 | 0 | 0 | 0 | 0 |
| 5 | 1 | 0 | 0 | 0 | 0 | 0 |
| 6 | 1 | 0 | 1 | 0 | 1 | 0 |
| 7 | 0 | 1 | 0 | 1 | 0 | 1 |
| 8 | 0 | 1 | 1 | 0 | 1 | 0 |
| 9 | 1 | 0 | 0 | 1 | 1 | 0 |
Solution 1:[1]
There are several ways to implement a solution code for your problem. But we keep it as simple as possible. ATTENTION this is not a whole complete code. I just give you the function implementations and you have to merge the big picture by making use of this implementation.
First of all we are going to define an input holding register, its bits and active cases for both output red and output green. Now that we have all cases defined, in the main loop wee need to scan input statuses and hold the last status in a register called inStates or call it whatever you wish. After that, we update the output LEDs according to the table that you showed in your question.
shared UDATA_SHR ; Declare variables in shared RAM
inStates RES 1 ; Input states holder variable
; Bit definitions for inputs
OP1RED_BIT EQU 0 ; bit-0 holds value for op#1 Red
OP1GREEN_BIT EQU 1 ; bit-1 holds value for op#1 Green
OP2RED_BIT EQU 2 ; bit-2 holds value for op#2 Red
OP2GREEN_BIT EQU 3 ; bit-3 holds value for op#2 Green
; Active case definitions for out LED red
OUT_LED_RED_CASE_1 EQU (1 << OP2RED_BIT) ; case 1
OUT_LED_RED_CASE_2 EQU ( (1 << OP1RED_BIT) | (1 << OP2RED_BIT) ) ; case 2
OUT_LED_RED_CASE_3 EQU ( (1 << OP1GREEN_BIT) | (1 << OP2RED_BIT) ) ; case 3
OUT_LED_RED_CASE_4 EQU ( (1 << OP1RED_BIT) | (1 << OP2GREEN_BIT) ) ; case 4
; Active case definitions for out LED green
OUT_LED_GREEN_CASE_1 EQU (1 << OP2GREEN_BIT) ; case 1
OUT_LED_GREEN_CASE_2 EQU ( (1 << OP2GREEN_BIT) | (1 << OP1GREEN_BIT) ) ; case 2
; Maybe here there is some piece of init codes
main_loop:
; Other codes if applicable...
; Somewhere in the main loop
call readInStats ; read the input states
call setStateForOutLedRed ; set out red LED accordingly
call setStateForOutLedGreen ; set out green LED accordingly
; Other codes if applicable...
goto main_loop
; Assuming that the access bit is enabled...
readInStats:
clrf inStates
btfsc OP1RED_PORT, OP1RED_BIT
bsf inStates, 0
btfsc OP1GREEN_PORT, OP1GREEN_BIT
bsf inStates, 1
btfsc OP2RED_PORT, OP2RED_BIT
bsf inStates, 2
btfsc OP2GREEN_PORT, OP2GREEN_BIT
bsf inStates, 3
; Read complete
return
setStateForOutLedRed:
movlw OUT_LED_RED_CASE_1
xorwf inStates, w
bz doSetOutRed
movlw OUT_LED_RED_CASE_2
xorwf inStates, w
bz doSetOutRed
movlw OUT_LED_RED_CASE_3
xorwf inStates, w
bz doSetOutRed
movlw OUT_LED_RED_CASE_4
xorwf inStates, w
bz doSetOutRed
; if the flow reaches here then no cases match to set red LED
bcf OUT_LED_RED_PORT, OUT_LED_RED_BIT
return
doSetOutRed:
; One of the cases matches to set red LED
bsf OUT_LED_RED_PORT, OUT_LED_RED_BIT
return;
setStateForOutLedGreen:
movlw OUT_LED_GREEN_CASE_1
xorwf inStates, w
bz doSetOutGreen
movlw OUT_LED_GREEN_CASE_2
xorwf inStates, w
bz doSetOutGreen
; if the flow reaches here then no cases match to set green LED
bcf OUT_LED_GREEN_PORT, OUT_LED_GREEN_BIT
return
doSetOutGreen:
; One of the cases matches to set green LED
bsf OUT_LED_GREEN_PORT, OUT_LED_GREEN_BIT
return;
Update for inStates structure info
inState Register Bits
| bit7 | bit6 | bit5 | bit4 | bit3 | bit2 | bit1 | bit0 |
|---|---|---|---|---|---|---|---|
| not used | not used | not used | not used | holds OP2GREEN_BIT | holds OP2RED_BIT | holds OP2RED_BIT | holds OP1RED_BIT |
If you have a look at readInStats function we read and save the values in this order to the inState register. If you flip the order, it will be the same order as in your truth table.
I will share the active case assignments in binary format instead of shifting for you to better understand.
; Active case definitions for out LED red
OUT_LED_RED_CASE_1 EQU B'00000100' ; case 1
OUT_LED_RED_CASE_2 EQU B'00000101' ; case 2
OUT_LED_RED_CASE_3 EQU B'00000110' ; case 3
OUT_LED_RED_CASE_4 EQU B'00001001' ; case 4
; Active case definitions for out LED green
OUT_LED_GREEN_CASE_1 EQU B'00001000' ; case 1
OUT_LED_GREEN_CASE_2 EQU B'00001010' ; case 2
If you flip the low nibbles (lower 4 bits) you will see the same values as in your truth table that sets the corresponding outputs as 1. This how you can interpret a truth table as coding constant values.
Update: Fix for memory allocation in absolute mode
Just change these 2 lines of code:
shared UDATA_SHR ; Declare variables in shared RAM
inStates RES 1 ; Input states holder variable
to this line:
inStates EQU 0 ; Allocate a byte of memory in shared memory at address 0x00
Change you code and try compiling again, it must compile now without a linker problem.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 |
