Assembly 如何在PIC汇编程序中进行银行切换?

Assembly 如何在PIC汇编程序中进行银行切换?,assembly,switch-statement,pic,bank,Assembly,Switch Statement,Pic,Bank,我被PIC汇编程序中的银行切换弄糊涂了。。。这有助于在usart上添加“Q”: bsf PORTB,1 ;Set Transmit DIR (PORTB (0x6) not mirrored in other banks) movlw 'Q' ;'Q' to work reg movwf TXREG ;work reg to TXREG (TXREG (0x19) not mirrored in other banks) clrwdt

我被PIC汇编程序中的银行切换弄糊涂了。。。这有助于在usart上添加“Q”:

bsf PORTB,1         ;Set Transmit DIR (PORTB (0x6) not mirrored in other banks)
movlw 'Q'           ;'Q' to work reg
movwf TXREG         ;work reg to TXREG (TXREG (0x19) not mirrored in other banks)
clrwdt              ;Clear watchdog
btfss TXSTA,TRMT    ;Wait until 'Q' is shifted (TXSTA is 0x18, not mirrored)
goto $-2
bcf PORTB,1         ;Set Recive DIR
这同样有效:

BCF 0x3, 0x5        ;Switch to bank 0
BCF 0x3, 0x6
bsf PORTB,1         ;Set Transmit DIR
movlw 'Q'           ;'Q' to work reg
movwf TXREG         ;work reg to TXREG 
BSF 0x3, 0x5        ;Switch to bank 1
clrwdt              ;Clear watchdog
btfss TXSTA,TRMT    ;Wait until 'Q' is shifted
goto $-2
BCF 0x3, 0x5        ;Switch to bank 0
bcf PORTB,1         ;Set Recive DIR

我已经检查过编译器在我不看的时候没有做任何银行切换。。。您什么时候必须切换银行?

最好只使用BANKSEL自动切换银行。它是一个特殊的汇编指令,告诉汇编程序切换到正确的库。因此,如果您希望访问PORTB,在使用它之前只需BANKSEL(PORTB)


PS:PORTB位于PIC16系列的BANK0中,而不是代码中的BANK1中。

首先,您使用的是哪种pic设备,因为这会产生轻微的差异。 另外,您正在使用哪个编译器

然而,代码正常工作的原因是,发送到uart所需的所有操作都在组0中。您对端口b的写入没有任何作用,我猜您希望切换trisb,而trisb位于气缸组1中,但由于uart可以控制端口b的引脚写入,因此它本身没有任何效果。在第二个示例中,您正在轮询您认为是TXSTA的对象,但该对象位于组0中,而不是组1中。我猜,如果轮询错误的位置,并且位始终处于正确的状态,那么循环将终止,那么您就幸运了

当我进行传输时,我更喜欢先查看uart是否为空,然后等待它为空,然后发送字符。不需要等待它完成传输,除非您想使用中断来获取下一个字符

所以这两段代码都可以工作,因为当您执行movwf TXREG时,这两段代码都在组0中。其余部分由硬件为您处理

编辑:
现在我知道了你所说的TXTA在气缸组1中的部分是正确的。你通过我,因为你有一个地址为0x18的注释,它应该是0x98。在第一个示例中,您正在轮询RCSTA位1,它是OERR而不是TXSTA。因此,如果它工作,这意味着OERR=1,这是很可能的,我通常在处理接收时清除它。

我也发现银行选择非常难以理解

我正在使用PIC12F1822s启动一个项目,以实现其I2C功能。研究背景就像解开一捆线,每一根线都需要努力才能弄清楚。我设法引出的一条线索是对“BANKSEL”指令的解释

背景。有几十个SFR——特殊功能寄存器——协助设备运行,映射到较低的数据存储器中。因为银行数量如此之多,它们被组织成32家银行,编号从0到31,每个银行有32家SFR。SFR以(位)bbbbb fffffff的形式顺序编号,其中bbbbb是组编号,fffffff是组中的偏移量。它们的值在PIC的.INC文件中定义,序列中有许多间隙。请注意,对于组0到30中的SFR偏移量,仅5位就足够了,但对于组31,7位是必需的

当访问其中一个SFR时,其银行编号必须在BSR寄存器中,该寄存器由“MOVLB”汇编指令设置。为了简化此操作,有一个指令“BANKSEL”,可在每次访问SFR之前使用。(在其他PIC中,状态寄存器中的位保留银行编号)成功测试后,可以删除任何多余的银行编号。我的困惑(在建立到目前为止——文档中的信息是稀疏和分散的)是这个指令是如何工作的。当然,在生成任何代码之前,汇编程序都会对它进行评估,这是我的测试代码,用于检查它,使用EQU进行计算,并解释它(注意locn是“Location”,即指令的地址):

;BANKSEL是一个指令,它与
;       movlb(&0XF0)>>7
;例如,TRISA在P12F1822.INC中定义为:
;-----银行1------------------
TRISA EQU H'008C'
汇编程序:
Locn结果值行原始代码行内容“;”是注释
~~~~   ~~~~~~~~~~~~~~~     ~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
00047 ; BANKSEL指令等效性的测试
000000 8C 00048 selbank equ TRISA
000000 80 00049 selbnk1 eq selbank&0XF80;提取银行编号。。
00000001 00050 selbnk2 eq selbnk1>>7。。把它移到右边
0000000 c 00051 selbnk3 equal TRISA&0XF80>>7
[运算符优先级:>>(位右移)高于&(按位与)]
0000000 c 00052 selbnk4 eq TRISA&(0XF80>>7);违约
0000000 1 00053 selbnk5 equ(TRISA&0XF80)>>7;必要时`
. . .
006C 0021 00100 movlb 1;应与下一行相同
006D 0021 00101班克塞尔TRISA

感谢您提供有关BANKSEL的提示。而且在我的代码中,BANK1只用于TXSTA。正如你所说,PORTB是BANK0。请看最后两行。在清除TRISB而不是PORTB之前,它会切换到BANK1。我站在更正位置!我已对这个问题稍作修改和重新措辞。这个答案同样有效…编译器:MPASM;芯片:16F876A。根据手册,TXSTA位于气缸组1中。不管怎样,我都会把这个标记为正确答案。
        ;BANKSEL is a directive that does the equivalent of 
        ;       movlb  (<SFRname> & 0XF0) >> 7

        ;For example TRISA is defined in P12F1822.INC as:

        ;-----Bank1------------------
        TRISA            EQU  H'008C' 

   Assembler:
   Locn   Resulting value     Line  Original code line content ";" is a comment
   ~~~~   ~~~~~~~~~~~~~~~     ~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
                              00047 ; Test of equivalent of BANKSEL directive          
          0000008C            00048 selbank equ TRISA
          00000080            00049 selbnk1 equ selbank & 0XF80 ; Extract bank no. ..
          00000001            00050 selbnk2 equ selbnk1 >> 7 ; .. move it to the right
          0000000C            00051 selbnk3 equ TRISA & 0XF80 >> 7 
        [ Operator precedence: >> (bit shift right) higher than & (bitwise AND) ]
          0000000C            00052 selbnk4 equ TRISA & (0XF80 >> 7) ; default
          00000001            00053 selbnk5 equ (TRISA & 0XF80) >> 7 ; as needed`
                     . . .
   006C   0021                00100 movlb  1           ; Should be same as next line
   006D   0021                00101 banksel TRISA