Как происходит переключение банков в ассемблере PIC?

Меня смущает переключение банков в ассемблере 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

Я проверил, что компилятор не переключает банки, когда я не смотрю... Когда ДОЛЖЕН переключать банки?


person c0m4    schedule 05.05.2009    source источник


Ответы (3)


Во-первых, какое графическое устройство вы используете, потому что это имеет небольшое значение. Также какой компилятор вы используете.

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

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

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

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

person Rex Logan    schedule 08.05.2009
comment
Компилятор: МПАСМ; Чип: 16F876A. Согласно мануалу, TXSTA находится в банке 1. Я отмечаю это как правильный ответ, несмотря ни на что. - person c0m4; 11.05.2009

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

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

person sybreon    schedule 05.05.2009
comment
Спасибо за отзыв о БАНКСЕЛ. А также BANK1 используется только для TXSTA в моем коде. PORTB - это BANK0, как вы говорите. - person c0m4; 05.05.2009
comment
Посмотрите на последние 2 строчки. Он переключается на BANK1 перед очисткой TRISB вместо PORTB. - person sybreon; 05.05.2009
comment
Я исправляюсь! Я исправил и немного перефразировал вопрос. Этот ответ так же действителен, хотя... - person c0m4; 05.05.2009

Я тоже нашел выбор банка очень трудным для понимания.

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

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

При доступе к одному из этих SFR его номер банка должен находиться в регистре BSR, который устанавливается ассемблерной инструкцией "MOVLB". Чтобы упростить эту задачу, существует директива "BANKSEL", которую можно использовать перед каждым доступом к SFR. (В других 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       
person Harry Weston    schedule 11.10.2012