我对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
我已经检查过编译器在我不看的时候没有进行任何银行切换......什么时候需要切换银行?
答案 0 :(得分:7)
最好只使用BANKSEL自动进行银行转换。它是一个特殊的汇编程序指令,告诉汇编程序切换到正确的存储区。因此,如果您希望在使用之前访问PORTB,只需使用BANKSEL(PORTB)。
PS:PORTB在PIC16系列的BANK0中,而不是代码中的BANK1。
答案 1 :(得分:5)
我也发现银行选择很难理解。
我正在使用PIC12F1822s开始一个项目,以实现其I2C功能。研究背景就像解开线程的束缚,每个人在明确之前都需要进行大量的挣扎。我设法撤出的其中一个主题是对“BANKSEL”指令的解释。
背景。有几十个SFR - 特殊功能寄存器 - 帮助设备操作,映射到较低的数据存储器。因为有这么多,它们被组织成32个银行,编号为0到31,每个32个SFR。 SFR以形式(位) bbbbbfffffff 顺序编号,其中 bbbbb 是存储区编号, fffffff 是存储区中的偏移。它们的值在PIC的.INC文件中定义,序列中有许多间隙。请注意,对于0到30存储区中的SFR偏移,只需要5位,但对于存储区31,则需要7位。
当访问其中一个SFR时,其Bank编号必须位于BSR寄存器中,该寄存器由“MOVLB”汇编器指令设置。为了简化这一过程,可以在每次访问SFR之前使用指令“BANKSEL”。 (在其他PIC中,STATUS寄存器中的位保存存储区编号)成功测试后,可以删除任何多余的BANKSEL。我的谜题(到目前为止建立这个 - 文档中的信息稀疏和分散)是这个指令的工作原理。当然,在生成任何代码之前,汇编程序会对其进行评估,这是我的测试代码,使用EQU进行计算并解释它(注意locn是“Location”即指令的地址。):
;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
答案 2 :(得分:3)
首先关闭哪个pic设备,因为这确实会产生细微差别。 您还在使用哪种编译器。
然而,你的代码工作的原因是因为你需要对tx执行ux的所有操作都在bank 0.你对端口b的写操作什么都没做我猜你想要切换trisb而那是在bank 1中但由于uart控制了写入端口B的引脚,因此它本身没有任何效果。在你的第二个例子中,你正在轮询你认为TXSTA,但是在银行0而不是银行1.我猜你通过轮询错误的位置而得到幸运,并且该位总是处于正确状态,因此循环终止。
当我进行传输时,我更喜欢先看看uart是否为空并等到它是,然后发送char。无需等待它完成传输,除非您想使用中断例如获取下一个字符。
因此,当您执行movRf TXREG时,两个代码都有效,因为您在两个代码中都处于存储区0中。其余部分由硬件处理。
编辑: 现在我知道你正确的部分是TXSTA在银行1.你通过我,因为你有一个地址的评论为0x18,它应该是0x98。在第一个示例中,您轮询RCSTA位1,即OERR而不是TXSTA。因此,如果它正在工作,这意味着OERR = 1这是非常可能的,当我对接收做任何事情时,我通常会清除它。