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

私も銀行の選択が非常にわかりにくいと感じました。

I2C 機能のために、PIC12F1822 を使用してプロジェクトを開始しています。背景を調査することは、糸の束をほどくようなもので、それぞれが明らかになるまでに多くの苦労が必要です。私がなんとか引き抜いたスレッドの 1 つは、「BANKSEL」ディレクティブの説明です。

バックグラウンド。デバイスの動作を支援する数十の SFR (特殊機能レジスタ) があり、下位データ メモリにマップされます。非常に多いため、それぞれ 32 個の SFR の 0 ~ 31 の番号が付けられた 32 個のバンクに編成されています。SFR は、(ビット) bbbbbfffffffの形式で連続して番号付けされます。ここで、bbbbbはバンク番号で、ffffffffはバンク内のオフセットです。それらの値は PIC の .INC ファイルで定義されており、シーケンスには多くのギャップがあります。バンク 0 ~ 30 の SFR オフセットでは 5 ビットで十分ですが、バンク 31 では 7 ビットが必要であることに注意してください。

これらの SFR の 1 つにアクセスする場合、そのバンク番号は、「MOVLB」アセンブラ命令によって設定される BSR レジスタにある必要があります。これを簡単にするために、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

まず、使用しているPICデバイスは、わずかな違いがあるためです。また、どのコンパイラを使用していますか。

ただし、コードが機能する理由は、uartへのtxに必要なすべてがバンク0にあるためです。ポートbへの書き込みは何もしていません。trisbを切り替えたいと思いますが、それはバンク1にあります。 uartは、ポートBに書き込むピンを制御します。それ自体は効果がありません。2番目の例では、TXSTAと思われるものをポーリングしていますが、これはバンク1ではなくバンク0にあります。間違った場所をポーリングすると幸運に恵まれ、ビットは常に正しい状態にあるため、ループは終了します。

送信を行うときは、最初にUARTが空であるかどうかを確認し、空になるまで待ってからcharを送信することを好みます。たとえば次の文字を取得するために割り込みを使用する場合を除いて、送信が完了するのを待つ必要はありません。

したがって、movwf TXREGを実行すると、両方のバンク0にいるため、両方のコードが機能します。残りはハードウェアで処理されます。

編集:TXSTAがバンク1にあるという点で、あなたが正しい部分がわかったので、アドレスのコメントが0x18であり、0x98である必要があるため、私を介してください。最初の例では、TXSTAではなくOERRであるRCSTAビット1をポーリングしています。したがって、動作している場合、これはOERR = 1を意味します。これは、受信で何かを行うときに通常クリアする可能性が非常に高いことを意味します。

于 2009-05-08T15:32:32.050 に答える