assembly 我怎样才能通过创建一个布尔变量而不是循环遍历分支来处理这个程序呢?

oipij1gg  于 2022-12-04  发布在  其他
关注(0)|答案(1)|浏览(97)

我正在对好奇HPC板上的PIC1847q处理器进行编程。我的任务是使用板上的LED设计一个battlestar galactica cyclon遮阳板。我当前的代码实际上创建并复制了Cyclon,但我不认为逻辑对于我被“分配”的方式是正确的。我应该创建第二个变量,但我不确定如何做。我的问题是:如何使用布尔变量和布尔逻辑来代替我的方法来得到相同的结果呢?我附上了一张赋值的图片。enter image description here

;; Inputs: None
    ;; Outputs: LEDs are illuminated and extinguished
    ;; Side Effects: I/O Configured. Lights and extinguishes four LEDs.
    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
    ;; Required header items
    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
    PROCESSOR 18F47Q10
    #include <xc.inc>
    #include "EE367_PIC18F47Q10_Setup01.inc"
    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
    ;; Constants
    // Configuration values for Timer 1 control registers
    TMR1_CS_Bits EQU 00000001B // Set to TMR1CLK to FOSC/4 (Instruction Clock)
    TMR1_Con_Bits EQU 00110011B // Set to ON, RD16, SYNC-bar, 8x prescaler
    TMR1_GCon_Bits EQU 00000000B // GE = 0, Gating is disabled
    TMR1IF_Mask EQU 00000001B // TMR1IF bit is b0 or PIR4
    TMR1IF_POSN EQU 0 // Ditto
    InitialTMR1H EQU 0xe4 // Initial value for Two-byte TMR counter register
    InitialTMR1L EQU 0x00 // 0xC000 gives about 1/2 second delay

    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
    // none
    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
    ;; Allocate space for variables
    Global TMR1_Initializer

    PSECT udata_acs
    TMR1_Initializer: DS 2 // Value used to initialize TMR 1, each cycle
    
    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
    // none
    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
        ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
    ;; InitializeTimerOne: Setup configuration for TMR1 to count up
    ;; Inputs: none
    ;; Outputs: none
    ;; Side Effects: Reinitializes the TMR1 counter register,
    ;; and clears TMR1 IF flag bit
    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  
    ;; Main program
    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

    PSECT Code,class=CODE,abs
    Code:
    ORG 0x000000
    GOTO Start
    ORG 0x000020
    
    // Enter program body here
    Start:
    Call InitializeIO_Ports

    Flash01:
    //initial state
    movlw 16
    movwf LATA,a// Adds value of Wreg to LATA LED 2 4
    
   BRA LeftRotate

   RightRotate: 
    CALL InitializeTimerOne // Comment required
    CALL DelayTMR1 ;; Call DelayTMR1
    
    RRNCF LATA,a
    CALL InitializeTimerOne // Comment required
    CALL DelayTMR1 ;; Call DelayTMR1
    
     RRNCF LATA,a
    CALL InitializeTimerOne // Comment required
    CALL DelayTMR1 ;; Call DelayTMR1
    

    RRNCF LATA,a
    CALL InitializeTimerOne // Comment required
    CALL DelayTMR1 ;; Call DelayTMR1
    
    BNZ LeftRotate
    
    LeftRotate: 
   RLNCF LATA,a
   CALL InitializeTimerOne // Comment required
    CALL DelayTMR1 ;; Call DelayTMR1
    
    RLNCF LATA,a
   CALL InitializeTimerOne // Comment required
    CALL DelayTMR1 ;; Call DelayTMR1
    
    RLNCF LATA,a
   
    BNZ RightRotate

    Sleep // Halt

    InitializeTimerOne:
  
   MOVLW TMR1_GCon_Bits ;; 8 bits for the TMR1 Gating Cntl Reg
   MOVWF T1GCON,A
   MOVLW TMR1_CS_Bits ;; 8 bits for the TMR1 clock signal Cntl Reg
   MOVWF T1CLK,A
   MOVLW TMR1_Con_Bits ;; 8 bits for the TMR1 Main Cntl Reg
    MOVWF T1CON,A ;; Note: this instruction starts the timer
    MOVLW InitialTMR1L ;; Set an initial value into var TMR1_Initializer 
    MOVWF TMR1_Initializer,A ;; which is a variable used to initialize
   MOVLW InitialTMR1H ;; the TMR1 counter on each pass.
    MOVWF TMR1_Initializer,A
    RETURN
   

    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
    ;; DelayTMR1: Busy wait until timer one times out.
    ;; Will initialize TIMR1 counter register and return immediately,
    ;; if timer 1 is already expired.
    ;; Inputs: none
    ;; Outputs: none
    ;; Side Effects: Reinitializes the TMR1 counter reg and clears TMR1 IF flag bit
    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
    DelayTMR1:
    BANKSEL PIR4 ;; The flag bit is in SFR PIR4, Banked Mode required
    DelayTMR1_Repeat01:
    MOVF PIR4,W,B ;; These two steps use AND masking to detect
    ANDLW TMR1IF_Mask ;; the TMR1 IF flag bit.
    BZ DelayTMR1_Repeat01 ;; Go into busy wait until TIMR1IF is set.
    MOVFF TMR1_Initializer,TMR1H ;; Reinitialize the 16-bit TMR1 counter
    MOVFF TMR1_Initializer,TMR1L ;;
    BCF PIR4, TMR1IF_POSN,B ;; Clear the flag, ready for the next cycle
    RETURN
    
    InitializeIO_Ports:
        CLRF LATA,A // Clear Port A output bits, before activating Port A
    
    CLRF TRISA,A // Make Port A an output port
        return
        
        
    end Code
vjrehmav

vjrehmav1#

尽管这个问题有点老了,我考虑回答,希望能帮助其他有类似问题的人。OP的实现似乎可以完成任务,但并不完全符合赋值要求。例如,它既没有使用 LEDMask 变量,也没有使用bRotateLeftLED变量。代码也有许多重复调用,可以减少到最少。定时器初始化souldn'而是在进入主循环之前初始化一次计时器模块,然后每次调用delay时,我们只重新加载定时器值,使其产生相同的延迟量。让我们编写一个伪C类代码,将问题转换为PIC汇编语言。这将给予我们更容易理解问题的方面,并使其更容易在汇编中实现。根据分配,逻辑如下:

variable bRotateLeftLED
variable LEDMask

// Init timer module once
initTimer1()
// Start from right o left
LEDMask = 0x10
bRotateLeftLED = true

// Main loop
while(true) {
    if(bRotateLeftLED == true) {
        if(LEDMask & 0x80 != 1) {
            // shift the bit towards 7th bit
            LEDMask <<= 1
        }
        else {
            // Reached to the 7th bit, reverse the shifting direction
            bRotateLeftLED = false
        }
    }
    else{
        if(LEDMask & 0x10 != 1) {
            // shift the bit towards 4th bit
            LEDMask >>= 1
        }
        else {
            // Reached to the 4th bit, reverse the shifting direction
            bRotateLeftLED = true
        }
    }

    // Output the LED LEDMask through PORTA
    LATA = LEDMask
    // Delay to make the output movement visible to the human eye
    Delay
}

现在我们有了一个方面,我们可以尽最大努力将它翻译成PIC汇编。然而,我只写能完成这项工作的代码,而省略了其余的代码,因为一些init或类似的代码可能是特定于应用程序的。我还将引用汇编代码对应的psuedo代码,使其更容易理解。

; NOTE: We will interprete the false as 0 value, and the true any value other than 0.

; Initialization block
Init:
    ; Maybe other init codes...

    ; initTimer1()
    CALL    initTimer1
    ; LEDMask = 0x10
    MOVLW   0x10
    MOVWF   LEDMask
    ; bRotateLeftLED = true
    SETF    bRotateLeftLED  ; init the flag with true to start shifting towards left
    ; NOTE: Although I use byte-wise flag here for the simplicity, it's much better
    ; and memory efficient using bitwise flags instead of using the whole 8 bits
    ; to present a boolean state. Byte-wise usage is wasting other 7 bits of the byte.

; while(true): Main loop
Start:
; Following label is optional to provide better readability
DoRotateLeft:
    ; if(bRotateLeftLED == true)
    MOVF    bRotateLeftLED, W
    ANDLW   0xFF
    BNZ
    BRA     DoRotateRight
    ; if(LEDMask & 0x80 != 1)
    MOVF    LEDMask, W
    ANDLW   0x80
    BNZ      RotateLeftDone
    ; LEDMask <<= 1 - rotate left once without carry
    RLNCF   LEDMask, F
    ; end of if(LEDMask & 0x80 != 1) block
    BRA     OutputAndDelay
; end of if(LEDMask & 0x80 != 1) block
; else block of if(LEDMask & 0x80 != 1) tree
RotateLeftDone:
    ; bRotateLeftLED = false
    CLRF    bRotateLeftLED  ; Set the boolean flag to false
    BRA     OutputAndDelay
; end of if(LEDMask & 0x80 != 1) - else block
; end of if(bRotateLeftLED == true) block

; else block of if(bRotateLeftLED == true) tree
DoRotateRight:
    ; if(LEDMask & 0x10 != 1)
    MOVF    LEDMask, W
    ANDLW   0x10
    BNZ      RotateRightDone
    ; LEDMask >>= 1 - rotate right once without carry
    RRNCF   LEDMask, F
    ; end of if(LEDMask & 0x10 != 1) block
    BRA     OutputAndDelay
; end of if(LEDMask & 0x10 != 1) block
; else block of if(LEDMask & 0x10 != 1) tree
RotateRightDone:
    ; bRotateLeftLED = true
    SETF    bRotateLeftLED  ; Set the boolean flag to true
; end of if(LEDMask & 0x10 != 1) - else block
; end of if(bRotateLeftLED == true) - else block
; No need to branch to OutputAndDelay here since the program will naturally flow to there

OutputAndDelay:
    MOVFF   LEDMask, LATA
    ; Note that we do not initialize the timer1 for each call since it is done once.
    CALL    DelayT1

    BRA Start   ; end of main loop while(true) block: Loop infinitely

; Here goes Delay subroutine
DelayT1:
    ; The delay code goes here
    ; Reload the timer registers for the next delay upon the timer overflow
    MOVLW   InitialTMR1H
    MOVWF   TMR1H
    MOVLW   InitialTMR1L
    MOVWF   TMR1L
    RETURN

    ; Maybe some more codes...

    END

相关问题