Connect with us

18F4420 Switch case statement in assembly language(asm)

Discussion in 'Microcontrollers, Programming and IoT' started by cat5244, Jul 24, 2021.

Thread Status:
Not open for further replies.
Scroll to continue with content
  1. cat5244

    cat5244

    5
    0
    Jul 24, 2021
    0
    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 a third single LED Output to tell me the status of these 4 LEDs based on their status. For example, below there's picture of the truth table I would like to implement.

    I need help please, writing a algorithm fucntion in assembly lanaguge. I was thinking of using like a switch statament to check the 4 LEDS stauts and thus drive the OUTPUT third led either green or red.

    The 4 leds are connected to diffrent Ports pins in the PIC and and the output LED to another pins. I just having trouble of 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 fucntion. Any help will be wlecome. Thank you

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

    Attached Files:

  2. DBingaman

    DBingaman

    108
    28
    Jun 27, 2021
    The last time I wrote anything in assembly language was back in the late 1990's for '486 processor running DOS. Is there a reason you don't want to write it in C? Microchip provides free C compilers. In addition your code can be ported to another processor if needed when written in C. The C compilers are very efficient and it sure beats trying to learn a specific processor instruction set when there are millions of processors out there. You don't have to use the Harmony Libraries. I hate them myself. I prefer to read and write directly to registers myself. For that you only need include <xc.h> it is a conditional that will give you register names and bit fields that match the parts datasheet exactly making life a lot easier. You can also post your code here so others can look at it if you are having trouble. Most people are pretty much now at least going up to a low level language like C.
     
  3. cat5244

    cat5244

    5
    0
    Jul 24, 2021
    The original project was written in assembly, and not in C. I'm trying to add a function to implement the table shown below. However, my code below is not working and I get errors. I think is not possible to read the value of the op1_red, op2_green from the port pins, by the way, I'm doing it, because for instance op1_red and the other 3 inputs will be changing. I need help I just would like to implement the table below and drive the pins l_out_green and l_out_red off or on based on the four input bits.
    [​IMG]
    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
     

    Attached Files:

  4. shumifan50

    shumifan50

    578
    57
    Jan 16, 2014
  5. DBingaman

    DBingaman

    108
    28
    Jun 27, 2021
    movlw op1_red ; Put the value of op1_red it on the working register

    Are you sure this is doing what you think it is? According to the datasheet this takes a literal (in this case an 8bit constant) and moves it to the working register. It does not appear to take the contents of what op1_red is pointing to and move it to the working register.

    MOVLW -> Move a literal (constant value) to the Working Register

    In other words move the value of 'op1_red' which is a literal that points to the op1_red register, not the contents of the register which I think is your intention.

    I think you may want MOVF which takes the contents of the register pointed to 'op1_red' I am thinking is the address of register A and moves it to the working register.

    In other words I think you want this:
    MOVF op1_red,W
    Which takes the address pointed to 'op1_red' and moves the contents to the working register.

    I also noticed this device supports 12bit addressing and 8 bit addressing. When using 8 bit addressing you must make sure you are in the correct bank (16 banks in all).


    I tried to upload the datasheet for this part, but it is to large for this forum.

    Datasheet location:
    https://ww1.microchip.com/downloads/en/DeviceDoc/39631E.pdf
     
    Last edited: Jul 26, 2021
  6. shumifan50

    shumifan50

    578
    57
    Jan 16, 2014
    @DBingaman: I did not create the content of that link and did not check it. I would not do it like that myself. I would:
    Code:
    [/B]
    [B]
    segment CODE
    lab1:
        jmp s1
        jmp s2
        jmp s3
    etc
    Segment DATA
    
    Then use that status as an offset
    ....
    if ( status <0 ) || status > 2) jmp to statusError
    PC = lab1 + (status * size of the jump instruction)
    
    

    If I remember you cannot code the jmp like that so you have to set the program counter:
    PC = lab1 + (status * size of the jump instruction)
    You also have to set your segment to the code segment before declaring lab1 and reset it to your data segment after.

    As I say, age is catching up with me and I cannot remember the exact details - I last coded for the Microchip MCs 15 years ago.
    The above is DEFINITELY syntactically INCORRECT and merely indicative of how to do it.
    I also vaguely remember that lab1 has to be in the first page of memory, so at the top of the code.
     
    Last edited: Jul 26, 2021
    DBingaman likes this.
  7. DBingaman

    DBingaman

    108
    28
    Jun 27, 2021
    I have a lot of questions about the constants: op1_red,op2_green,I_out_red, etc. In order to read the assembly code and verify it does anything requires the definition of those constants. I am fairly certain though the first instruction is not what you want. That just copies a literal 8bit value that is part of the instruction to the working register.
     
  8. DBingaman

    DBingaman

    108
    28
    Jun 27, 2021
    Y
    Yea, I agree with you on that. I would probably implement it as a look up table. Being it is just a giant logic table. You would have nothing more than the op's being bits in say a byte. With the first combination being zero, pointing to a byte in memory where each byte then represents the state of the LED's. You could implement this with nothing but a table in memory where each relative memory address is another combination of op's and that data at that point is the state of the LED's. So the assembly could be something like, load the state of the ops into the bits of a register (address pointer), add that (the offset) to the base address of the register table. Then take the contents of that address, it would have the state of each LED defined in it's bits. Then set them appropriately. But a vector jump table like you stated could also do that.
     
    shumifan50 likes this.
  9. cat5244

    cat5244

    5
    0
    Jul 24, 2021
    Thank you guys for helping me, I really appreciated it. This means a lot. I've been trying to implement a table in memory but I having trouble with it. I don't have a lot of experience with assembly so I was reading I can use UDATA_SHR and RES 1 to unbanked objects that are uninitialised, declare variables that are allocated in RAM that is shared across all RAM banks, But I get some errors when building the project.Directive only allowed when generating an object file
    RES directive cannot reserve odd number of bytes in PIC18 absolute mode. This the code i have right now. I just need to crate the table and use it to compare the states. Is there's a way to create a table similar to what i have below but not using DATA_SHR and RES 1. I really need help. Thank you
    Here the code :


    1. #define op2_red LATA,0
    2. #define op2_green LATA,1

    3. #define op1_green LATB,3
    4. #define op1_red LATB,1

    5. #define led_out_red LATC,2
    6. #define led_out_green LATC,0


    7. ; Setup PORT A
    8. movlw 0x00; 0000000
    9. movwf TRISA

    10. ; Setup PORT C
    11. movlw 0xF5; 11110101
    12. movwf TRISC

    13. ; Setup PORT C
    14. movlw 0xFA; 11111010
    15. movwf TRISC



    16. led_register UDATA_SHR ; unbanked objects that are uninitialised, declare variables that are allocated in RAM that is shared across all RAM banks
    17. states RES 1 ; general purpose buffer

    18. op1_red_bit equ 0; hold the vlaue for op2_red on bit - 0
    19. op1_green_bit equ 1; hold the vlaue for op1_green on bit - 1
    20. op2__red_bit equ 2; hold the vlaue for op1_red on bit - 2
    21. op2_green_bit equ 3; hold the vlaue for op2_green on bit - 3

    22. ; led_out_red; lower bits op2_green, op2_red, op1_green, op1_red
    23. led_out_red_case1 equ(1 << op2_red_bit); case 1 0000 0100
    24. led_out_red_case2 equ((1 << op1_red_bit) | (1 << op2_red_bit)); case 2 0000 0101
    25. led_out_red_case3 equ((1 << op1_green_bit) | (1 << op2_red_bit)); case 3 0000 0110
    26. led_out_red_case4 equ((1 << op2_red_bit) | (1 << op2_green_bit)); case 4 0000 1001

    27. ; led_out_green
    28. led_out_green_case1 equ(1 << op2_green_bit); case 1 0000 1001
    29. led_out_green_case2 equ((1 << op2_green_bit) | (1 << op2_green_bit)); case 2 0000 1001



    30. ; These functions will be inside the main


    31. ; this will read the status of the output op pins and save the value in the register
    32. read_states:
    33. clrf states
    34. btfsc op1_red, op1_led_red ; if bit 0 of op1_red = 0 skip otherwise do next line
    35. bsf states, 0 ; set bit 0 in the states bit high
    36. btfsc op1_green, op1_green_bit
    37. bsf states, 1
    38. btfsc op2_red, op2_red_bit
    39. bsf states, 2
    40. btfsc op2_green, op2_green_bit
    41. bsf states, 3

    42. red_states:
    43. movlw led_out_red_case1; move the contents of case 1 into Wreg
    44. xorwf states, w; Xor the contnets of Wreg with the contencts of statesand keep
    45. bz led_red_out; if zero branch, if not move to next line
    46. movlw led_out_red_case2
    47. xorwf states, w
    48. bz led_red_out
    49. movlw led_out_red_case3
    50. xorwf states, w
    51. bz led_red_out
    52. movlw led_out_red_case4
    53. xorwf states, w
    54. bz led_red_out
    55. ; if it reaches here then no cases match
    56. bcf lt_red, light_tower_red_bit ;set led_out_red port pin low for red

    57. led_red_out:
    58. ; One of the cases matches to set red LED
    59. bsf led_out_red, led_out_red_bit ;set port pin high for the Led_out_Red

    60. green_states:
    61. movlw led_out_green_case1
    62. xorwf states, w
    63. bz light_tower_green
    64. movlw led_out_green_case1
    65. xorwf states, w
    66. bz light_tower_green
    67. ; if it reaches here then no cases match
    68. bcf lt_green, light_tower_green_bit

    69. led_green_out:
    70. ; One of the cases matches to set green LED ; set led_out_red port pin low
    71. bsf led_out_green, light_tower_green_bit ; set port pin high for the Led_out_green
     
  10. cat5244

    cat5244

    5
    0
    Jul 24, 2021
    I just want to find another way of maybe not using UDATA_SH, I manged to add a linker and that got rid of the errors but now I have a new one that
    Section 'led_register' length=0x00000001
    Errors : 1

    Link step failed.
     
  11. cat5244

    cat5244

    5
    0
    Jul 24, 2021
    I have the project as relocatable
     
  12. DBingaman

    DBingaman

    108
    28
    Jun 27, 2021
    I would recommend not using the #defines at the top:
    1. #define op2_red LATA,0
    These make the assembly code harder to read. Just use LATA,0 etc. where needed and add appropriate comments. This is making it difficult for me to follow the code to help you.
     
  13. Harald Kapp

    Harald Kapp Moderator Moderator

    11,653
    2,695
    Nov 17, 2011
    Why?
    Threads are usually not deleted. Unless there is a specific reason, that is.
     
  14. Harald Kapp

    Harald Kapp Moderator Moderator

    11,653
    2,695
    Nov 17, 2011
    @cat5244 : without a good reason your post will not be deleted.
     
Ask a Question
Want to reply to this thread or ask your own question?
You'll need to choose a username for the site, which only take a couple of moments (here). After that, you can post your question and our members will help you out.
Thread Status:
Not open for further replies.
Electronics Point Logo
Continue to site
Quote of the day

-