2009-05-05 41 views
2

我通过银行开关在PIC汇编感到困惑切换...这适用于把一个“Q”的USART:银行在PIC汇编

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 

我已经检查过,编译器没有做任何银行切换,当我没有看...当有切换银行?

回答

3

首先关闭哪个图片设备,因为这确实会略有不同。 你还使用哪种编译器。

然而,你的代码工作的原因是因为你需要做的一切,以tx到uart是在银行0。你写入端口b没有做什么,我猜你想切换trisb,并在银行1但由于uart控制了写入端口B的引脚,所以它自己没有任何影响。在你的第二个例子中,你在轮询你认为是TXSTA,但是在银行0而不是银行1中。我猜测你通过轮询错误的位置而得到幸运,并且该位总是处于正确的状态,因此循环终止。

当我进行传输时,我更愿意先看看uart是否为空,然后等待它,然后发送字符。除非你想用Interupt来获取下一个字符,否则不需要等待它完成传输。

所以这两个代码段工作,因为你在两个当你做movwf TXREG时在银行0。其余部分由硬件处理。

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

7

最好只使用班克斯银行自动切换银行。这是一个特殊的汇编程序指令,告诉汇编程序切换到正确的库。所以,如果你想在使用PORTB之前访问PORTB,只需使用BANKSEL(PORTB)。

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

+0

感谢您对BANKSEL的建议。而且BANK1仅用于我的代码中的TXSTA。正如你所说,PORTB是BANK0。 – c0m4 2009-05-05 12:28:51

+0

看最后2行。它在清除TRISB而不是PORTB之前切换到BANK1。 – sybreon 2009-05-05 12:31:04

+0

我站好了!我已经修正并稍微修改了这个问题。这个答案虽然有效,但... – c0m4 2009-05-05 13:53:15

5

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

我正在启动一个使用PIC12F1822的项目来实现I2C功能。研究背景更像是解开一连串的线索,每个人在清楚之前都需要大量的努力。我设法解决的一个线索是对“BANKSEL”指令的解释。

背景。有几十个特殊功能寄存器 - 特殊功能寄存器 - 有助于器件的操作,映射到较低的数据存储器中。因为有这么多它们被组织成32个银行,编号0到31,每个32个SFR。 SFR按照形式(位)顺序编号(位)bbbbbfffffff其中bbbbb是银行编号和fffffff是银行的抵消额。它们的值在PIC的.INC文件中定义,并且序列中有很多空白。请注意,对于存储区0至30中的SFR偏移,只需5位就足够了,但对于存储区31,需要7位。

访问其中一个SFR时,其Bank编号必须位于由“MOVLB”汇编程序指令设置的BSR寄存器中。为了简化操作,可以在每次访问SFR之前使用指令“BANKSEL”。 (在其他PIC中,状态寄存器中的位包含存储区号)成功测试后,可以删除多余的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