【问题标题】:P18F4420 Switch case statement in PIC assembly languageP18F4420 汇编语言 (asm) 中的 switch case 语句
【发布时间】:2021-10-01 00:15:44
【问题描述】:

我目前正在以汇编语言在 Mplab IDE 上使用 PIC18f4420 进行一个项目,其中我有四个 LED。 2 个 LED 告诉我操作#1 的状态,另外 2 个 LED 告诉我另一个操作#2 的状态。最后,我还有 2 个输出 LED 可以根据它们的状态告诉我这 4 个 LED 的状态。例如,下面有一张我要实现的真值表的图片。

我需要帮助,用汇编语言编写一个算法函数。我正在考虑使用 switch 语句来检查 4 个 LED 的状态,从而将 OUTPUT LED 驱动为绿色或红色。

4 个 LED 连接到 PIC 中的不同端口引脚,输出 LED 连接到另一个引脚。我只是不知道如何在 Mplab V8 上为 PIC18f4420 编写汇编代码。我不清楚如何创建此功能。欢迎任何帮助。谢谢

最终输出 LED 将基于 4 个 LED 的颜色状态 RED/GREEN/OFF。

到目前为止,这是我得到的:

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

【问题讨论】:

  • 您不需要在代码中进行分支:如果您可以有效地将 4 个输入位转换为一个 4 位整数,则可以只使用数据查找表。或者,如果两个输出位都可以计算为 4 个输入的布尔函数,那么这也很好。例如LED OUT Green = op2green & ~op1red 似乎适用于您在真值表中显示的 10 行; IDK 如果其他 6 种可能的状态中的任何一种都可能是该表达式的问题,如果它们可能的话。 (我假设第 4 列应该是 OP#2 Green,而不是另一个 OP#1 Green?)
  • 我也认为outred = op1red | op2red 适用于第一个输出行。
  • 哦,是的,看起来它需要一个& ~out2green(再次假设这是第 4 个输入列,因为图像仍然有重复的标签。另外,不要发布文本图片。堆栈溢出有表格格式markdown:New Feature: Table Support,或者使用代码块。)
  • 将文本(尤其是代码)复制/粘贴为文本,而不是图像。 (另外,看起来你使用了add 而不是and,除非这是有意使用 add 的 xor + 进位操作。)
  • 不要发布你的代码图片。

标签: c assembly microcontroller microchip mplab


【解决方案1】:

有多种方法可以针对您的问题实施解决方案代码。 但我们尽可能简单。 注意这不是一个完整的代码。我只是给你函数实现,你必须通过使用这个实现来合并全局。

首先,我们要定义一个输入保持寄存器,它的位和输出红色和输出绿色的活动情况。现在我们已经定义了所有情况,在主循环中,我们需要扫描输入状态并将最后一个状态保存在名为inStates 的寄存器中,或者随意调用它。之后,我们会根据您在问题中显示的表格更新输出 LED。

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;
    

inStates 结构信息更新

inState 寄存器位

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

如果您查看readInStats 函数,我们会按此顺序读取值并将其保存到 inState 寄存器中。如果您颠倒顺序,它将与您的真值表中的顺序相同。 我将分享二进制格式的活动案例分配,而不是为了让您更好地理解。

; 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

如果您翻转低半字节(低 4 位),您将看到与将相应输出设置为 1 的真值表中相同的值。这就是您可以将真值表解释为编码常量值的方式。

更新:修复绝对模式下的内存分配

只需更改这两行代码:

shared      UDATA_SHR   ; Declare variables in shared RAM
inStates    RES     1   ; Input states holder variable

到这一行:

inStates    EQU     0 ; Allocate a byte of memory in shared memory at address 0x00

更改您的代码并再次尝试编译,它现在必须编译而不会出现链接器问题。

【讨论】:

  • 感谢您的回复。我会试一试。我只是对保持寄存器及其位感到困惑,因为 op1 red、op1green、op2red、op2green 是作为输出的端口引脚,它们会改变状态。所以我只想找到一种简单的方法来检查他们的状态。在我上面的代码中,我试图将状态值 0 或 1 带入 WERG
  • 还使用文件寄存器进行一些位操作 AND/OR ,从而将 ledout 设置为绿色或红色。我将尝试了解您的功能实现以合并全局
  • 放轻松,试试看。我使用了一个保持寄存器,因为状态 LED 可能位于不同端口的不同引脚上。这样,我会逐一收集每个引脚的状态,并将它们的状态保存在一个保持寄存器中,以便检查我之前定义的 case 值。不要犹豫,问任何让你困惑的事情。我想让你明白。
  • 至于输入的位定义,以及输出 LED 的活动案例定义。如果可能的话,你能告诉我表格中的条件在代码中的样子吗?非常感谢您的帮助
  • 不,不会。它将保存一个常量值,即二进制的0b00000101,对应于真值表的第 6 行。在第 6 行,当 opred1 和 opred2 都为 1 时,outred 将为 1。由于我将 opred1 保存在 bit0 中,opred2 保存在 bit2 中,它看起来是二进制形式0b00000101。现在有意义吗?
猜你喜欢
  • 2013-09-24
  • 1970-01-01
  • 1970-01-01
  • 2021-06-13
  • 2021-07-24
  • 1970-01-01
  • 1970-01-01
  • 2011-08-15
  • 1970-01-01
相关资源
最近更新 更多