2

我对 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

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

4

3 回答 3

7

最好只使用 BANKSEL 自动进行银行切换。这是一个特殊的汇编器指令,告诉汇编器切换到正确的库。因此,如果您想访问 PORTB,请在使用之前使用 BANKSEL(PORTB)。

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

于 2009-05-05T12:06:49.740 回答
5

我也发现银行选择很难理解。

我正在使用 PIC12F1822 开始一个项目,因为它们具有 I2C 功能。研究背景就像解开一缕线,每一根线都需要费一番功夫才能弄清楚。我设法提取的线程之一是对“BANKSEL”指令的解释。

背景。有几十个 SFR - 特殊功能寄存器 - 协助设备操作,映射到较低的数据存储器。因为它们太多了,所以它们被组织成 32 个库,编号为 0 到 31,每个库有 32 个 SFR。SFR 以(位) bbbbbfffffff的形式顺序编号,其中bbbbb是存储库编号,ffffffff是存储库中的偏移量。它们的值在 PIC 的 .INC 文件中定义,并且序列中有许多间隙。请注意,对于 bank 0 到 30 中的 SFR 偏移,只需 5 位就足够了,但对于 bank 31,则需要 7 位。

当访问这些 SFR 之一时,其 Bank 编号必须在 BSR 寄存器中,该寄存器由“MOVLB”汇编指令设置。为方便起见,可以在每次访问 SFR 之前使用指令“BANKSEL”。(在其他 PIC 中,STATUS 寄存器中的位保存银行编号)成功测试后,可以删除任何多余的 BANKSEL。我的困惑(在建立这一点之后——文档中的信息稀疏而分散)是这个指令是如何工作的。当然,它在生成任何代码之前由汇编程序进行评估,这是我的测试代码来检查它,使用 EQU 进行计算并解释它(注意 locn 是“位置”,即指令的地址.):

        ;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       
于 2012-10-11T18:08:03.593 回答
3

首先,您使用的是哪个图片设备,因为这确实会产生细微的差别。还有你使用的是哪个编译器。

但是,您的代码工作的原因是因为您需要对 uart 进行 tx 操作的所有操作都在 bank 0 中。您对端口 b 的写入什么也没做我猜您想切换 trisb 并且在 bank 1 中但是uart 可以控制写入端口 B 的引脚,它本身没有任何作用。在您的第二个示例中,您正在轮询您认为是 TXSTA 的内容,但那是在银行 0 而不是银行 1 中。我猜您通过轮询错误的位置而幸运,并且该位始终处于正确状态,因此循环终止。

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

因此,这两条代码都有效,因为当您执行 movwf TXREG 时,您都处于银行 0 中。其余的由硬件为您处理。

编辑:现在我知道你在 TXSTA 中正确的部分在银行 1 中。你通过我是因为你有一个地址为 0x18 的注释,它应该是 0x98。在第一个示例中,您正在轮询 RCSTA 位 1,它是 OERR 而不是 TXSTA。因此,如果它正在工作,这意味着 OERR=1 很有可能,我通常在对接收进行任何操作时将其清除。

于 2009-05-08T15:32:32.050 回答