简体   繁体   中英

P18F4420 Switch case statement in assembly language(asm)

I currently working on a project using PIC18f4420 on Mplab IDE in Assembly language where I have four LEDs. 2 LEDs tell me the status of operation#1 and the 2 other LEDs the status of another operation#2. Finally, I have 2 more output LEDs to tell me the status of these 4 LEDs based on their status. For example, below there's a picture of the truth table I would like to implement.

I need help please, writing an algorithm function in assembly language. I was thinking of using a switch statement to check the 4 LEDs' status and thus drive the OUTPUT LEDs either green or red.

The 4 LEDs are connected to different Ports pins in the PIC and the output LEDs to another pin. I just having trouble with how to write the code in assembly for the PIC18f4420 on Mplab V8. I don't have a clear idea of how to create this function. Any help will be welcome. Thank you

The final output LED will be based on the 4 LED'S colors status RED/GREEN/OFF.

So far this is what I got:

Leds_out ; function name 
 ; LED OUT Green = op2_green & ~op1_red
   movlw     op1_red      ; Put the value of op1_red it on the working register 
   movwf     0x39, f, a   ; save it on the file register at this location
   comf      0x39, f, a   ;  complement op1_red of the value on the file register and keep vlaue on the same location on the file register 
   movlw     op2_green    ;  move op2_green value into the working register 
   andwf     0x39, w, a   ;  AND the complement of op1_red in the file register with the vlaue bit of op2_green on the working register and keep value on the Wreg 
   movwf     0x40, f, a   ; move the contents of the Wreg into the file register at this location 
   movff     0x40, l_out_green, a  ; finally move content from file register 0x40 to the l_out_green

;LED Out red = op1red | op2red
                
   movlw     op1_red      ; put op1_red on the wokring register 
   movwf     0x41, f, a   ; move contents of the Wreg to file register 0x41
   movlw     op2_red      ;  Then move op2_red on the working register 
   iorwf     0x41, f, a   ;  OR the contents of the working register with what is in the file register 0x41 which is the bit value of op1_red, and keep OR value in the same location on the file register 
   
   movff     0x41, l_out_red, a ; Finally move the value bit in the location 0x41 into the port bit l_out_red 
OP#1 Red OP#1 Green OP#2 Red OP#2 Green LED Out RED LED 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

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM