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 ;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
我已经检查过,当我不这样做时,编译器不会进行任何库切换正在看...什么时候必须转换银行?
I'm getting confused by bank switching in PIC assembler... This works for putting a 'Q' on the usart:
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
And this works just as good:
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
I have checked that the compiler does not do any bank switching when I'm not watching... When do HAVE to switch bank?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
首先,您使用的是哪种图片设备,因为这确实会产生轻微的差异。
还有你使用的是哪个编译器。
然而,你的代码工作的原因是因为你需要对 uart 进行 tx 操作的所有操作都在存储区 0 中。你对端口 b 的写入没有执行任何操作,我猜测你想切换 trisb,而该存储区位于存储区 1 中,但是由于uart 可以控制写入端口 B 的引脚,但它本身没有任何影响。 在你的第二个例子中,你正在轮询你认为是 TXSTA 的内容,但那是在银行 0 而不是银行 1。我猜你通过轮询错误的位置而幸运,并且该位始终处于正确的状态,因此循环终止。
当我进行传输时,我更喜欢首先查看 uart 是否为空,然后等到它为空,然后发送字符。 无需等待它完成传输,除非您想使用中断来获取下一个字符。
因此,这两段代码都可以工作,因为当您执行 movwf TXREG 时,您都位于库 0 中。 其余的由硬件为您处理。
编辑:
现在我知道你是正确的部分,TXSTA 在银行 1 中。你通过我,因为你对地址的注释为 0x18,它应该是 0x98。 在第一个示例中,您正在轮询 RCSTA 位 1,这是 OERR,而不是 TXSTA。 因此,如果它正在工作,这意味着 OERR=1 这很可能是我通常在对接收进行任何操作时清除它。
First off which pic device are you using because that does make a slight difference.
Also which compiler are you using.
However the reason your code works is because everything you need to do to tx to the uart is in bank 0. Your writes to port b are doing nothing I am guessing that you want to switch the trisb and that is in bank 1 but since the uart has control of the pins writing to port B it self has no effect. In your second example you are polling what you think is TXSTA but that is in bank 0 not bank 1. I am guessing that you get lucky by polling wrong location and the bit is always in the correct state so the loop terminates.
When I do a transmit I prefer to first see if the uart is empty and wait until it is and then send the char. No need to wait for it to finish transmitting unless you want to use an interupt for example to get the next char.
So both pieces of code work because you are in bank 0 in both when you do movwf TXREG. The rest is handled in hardware for you.
Edit:
Now that I know the part you are correct in that TXSTA is in bank 1. You through me because you had a comment of the address as 0x18 and it should be 0x98. In the first example you are polling RCSTA bit 1 which is the OERR not TXSTA. So if it is working this implies that OERR=1 which is very possible I usually clear it when I do anything with the receive.
最好只使用 BANKSEL 自动进行银行切换。 它是一个特殊的汇编程序指令,告诉汇编程序切换到正确的库。 因此,如果您想访问 PORTB,只需在使用它之前使用 BANKSEL(PORTB) 即可。
PS:PORTB 位于 PIC16 系列上的 BANK0 中,而不是代码中的 BANK1 中。
It's best to just use BANKSEL to do your bank switching automatically. It is a special assembler directive the tells the assembler to switch to the correct bank. So, if you wish to access PORTB, just BANKSEL(PORTB) before using it.
PS: PORTB is in BANK0 on the PIC16 family, not BANK1 as in your code.
我也发现银行选择很难理解。
我正在启动一个使用 PIC12F1822 的项目,以实现其 I2C 功能。 研究背景就像解开一团线,每一条线都需要费一番力气才能弄清楚。 我设法拉出的线索之一是对“BANKSEL”指令的解释。
背景。 有几十个 SFR(特殊功能寄存器),可帮助设备操作,映射到较低的数据存储器。 因为数量太多,所以它们被组织成 32 个库,编号为 0 到 31,每个库有 32 个 SFR。 SFR 以(位)bbbbbffffffff 的形式按顺序编号,其中 bbbbbb 是存储体编号,fffffff 是存储体中的偏移量。 它们的值在 PIC 的 .INC 文件中定义,并且序列中存在许多间隙。 请注意,对于存储体 0 到 30 中的 SFR 偏移,只需 5 位就足够了,但对于存储体 31 来说,需要 7 位。
当访问这些 SFR 之一时,其 Bank 号必须位于 BSR 寄存器中,该寄存器由“MOVLB”汇编指令设置。 为了使这一过程变得简单,可以在每次访问 SFR 之前使用指令“BANKSEL”。 (在其他 PIC 中,STATUS 寄存器中的位保存 BANK 编号)成功测试后,可以删除任何多余的 BANKSEL。 我的困惑(到目前为止建立这个之后——文档中的信息稀疏且分散)是这个指令是如何工作的。 当然,在生成任何代码之前,它是由汇编器评估的,这是我的测试代码来检查它,使用 EQU 进行计算,并解释它(注意 locn 是“位置”,即指令的地址.):
I too found bank selection very difficult to understand.
I am starting a project using PIC12F1822s, for their I2C functionality. Researching the background is rather like untangling a skein of threads, each one needs a lot of struggling before it comes clear. One of the threads I have managed to pull out is an explanation of the "BANKSEL" directive.
Background. There are several dozen SFRs -- Special Function Registers -- that assist in the operation of the device, mapped into the lower data memory. Because there are so many they are organised into 32 Banks, numbered 0 to 31, of 32 SFRs each. The SFRs are numbered sequentially in the form (bits) bbbbbfffffff where bbbbb is the bank number and fffffff is the offset in the bank. Their values are defined in the .INC file for the PIC, and there are many gaps in the sequence. Note that for the SFR offsets in banks 0 to 30 just five bits are sufficient, but for bank 31 seven bits are necessary.
When accessing one of these SFRs its Bank number must be in the BSR register, which is set by the "MOVLB " assembler instruction. To make this easy there is a Directive "BANKSEL " that can be used before each access of an SFR. (In other PICs, bits in the STATUS register hold the bank number) After successful testing, any superfluous BANKSELs can be removed. My puzzle (after establishing this so far -- the information in the documentation is sparse and scattered) was how this directive works. It is, of course, evaluated by the assembler before any code is produced, and this is my test code to check it out, using EQU to do the calculations, and explain it (note locn is "Location" i.e the address of the instruction.):