Переключение банков в ассемблере ПИК - PullRequest
2 голосов
/ 05 мая 2009

Меня смущает переключение банков в ассемблере PIC ... Это работает для того, чтобы поставить 'Q' на 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

И это работает так же хорошо:

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 ]

7 голосов
/ 05 мая 2009

Лучше всего просто использовать BANKSEL для автоматического переключения вашего банка. Это специальная директива ассемблера, которая указывает ассемблеру переключиться на правильный банк. Итак, если вы хотите получить доступ к PORTB, просто BANKSEL (PORTB) перед его использованием.

PS: PORTB находится в BANK0 семейства PIC16, а не BANK1, как в вашем коде.

5 голосов
/ 11 октября 2012

Мне тоже очень трудно понять выбор банка.

Я начинаю проект с использованием PIC12F1822s для их функциональности I2C. Исследовать фон - это все равно, что распутывать моток нитей, каждый из которых нуждается в большом количестве усилий, прежде чем станет ясным. Одна из тем, которую мне удалось вытащить, - это объяснение директивы BANKSEL.

Фон. Существует несколько десятков SFR - регистров специальных функций, которые помогают в работе устройства и отображаются в нижней памяти данных. Поскольку их так много, они организованы в 32 банка, пронумерованных от 0 до 31, по 32 SFR в каждом. SFR нумеруются последовательно в виде (биты) bbbbbfffffff , где bbbbb - номер банка, а fffffff - смещение в банке. Их значения определены в файле .INC для PIC, и в последовательности много пробелов. Обратите внимание, что для смещений SFR в банках от 0 до 30 достаточно только пяти битов, но для банка 31 необходимо семь битов.

При обращении к одному из этих SFR его номер банка должен быть в регистре BSR, который устанавливается инструкцией ассемблера "MOVLB". Для этого существует директива «BANKSEL», которую можно использовать перед каждым доступом к SFR. (В других 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       
3 голосов
/ 08 мая 2009

Прежде всего, какое устройство Pic вы используете, потому что это немного меняет дело. Также какой компилятор вы используете.

Однако причина того, что ваш код работает, заключается в том, что все, что вам нужно сделать для передачи по каналу uart, находится в банке 0. Ваши записи в порт b ничего не делают. Я предполагаю, что вы хотите переключить trisb, а это в банк 1 но поскольку уарт имеет контроль над выводом, записывающим в порт B, он сам по себе не имеет никакого эффекта. Во втором примере вы опрашиваете то, что вы считаете TXSTA, но оно находится в банке 0, а не в банке 1. Я предполагаю, что вам повезло, если вы опрашиваете неправильное местоположение, и бит всегда находится в правильном состоянии, поэтому цикл завершается.

Когда я делаю передачу, я предпочитаю сначала посмотреть, пуст ли уарт, дождаться его и затем отправить символ. Не нужно ждать окончания передачи, если только вы не хотите использовать прерывание, например, чтобы получить следующий символ.

Таким образом, оба фрагмента кода работают, потому что вы находитесь в банке 0 в обоих случаях, когда выполняете movwf TXREG. Все остальное обрабатывается аппаратно для вас.

Edit: Теперь, когда я знаю, что вы правы в том, что TXSTA находится в банке 1. Вы через меня, потому что у вас был комментарий по адресу 0x18, и он должен быть 0x98. В первом примере вы опрашиваете бит 1 RCSTA, который является OERR, а не TXSTA. Так что, если это работает, это означает, что OERR = 1, что очень возможно, я обычно очищаю его, когда делаю что-нибудь с получателем.

...