Переключение банков в PIC ассемблере
-
05-07-2019 - |
Вопрос
Меня смущает переключение банков в ассемблере 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
Я проверил, что компилятор не выполняет переключение банков, когда я не смотрю...Когда НУЖНО менять банк?
Решение
Прежде всего, какое графическое устройство вы используете, потому что это имеет небольшое значение.И какой компилятор вы используете.
Однако причина, по которой ваш код работает, заключается в том, что все, что вам нужно сделать для передачи на UART, находится в банке 0.Ваши записи в порт b ничего не делают. Я предполагаю, что вы хотите переключить trisb, и он находится в банке 1, но поскольку uart контролирует контакты, записывающие в порт B, это само по себе не имеет никакого эффекта.Во втором примере вы опрашиваете то, что, по вашему мнению, является TXSTA, но это находится в банке 0, а не в банке 1.Я предполагаю, что вам повезло, если вы опрашиваете неправильное местоположение, и бит всегда находится в правильном состоянии, поэтому цикл завершается.
Когда я выполняю передачу, я предпочитаю сначала проверить, пуст ли UART, и подождать, пока он не станет пустым, а затем отправить символ.Нет необходимости ждать завершения передачи, если только вы не хотите использовать прерывание, например, для получения следующего символа.
Таким образом, обе части кода работают, потому что вы находитесь в банке 0 в обоих случаях, когда выполняете movwf TXREG.Остальное обрабатывается за вас аппаратно.
Редактировать:Теперь, когда я знаю, в какой части вы правы, TXSTA находится в банке 1.Вы через меня, потому что у вас был комментарий адреса как 0x18, а он должен быть 0x98.В первом примере вы опрашиваете бит 1 RCSTA, который является OERR, а не TXSTA.Итак, если он работает, это означает, что OERR = 1, что вполне возможно. Я обычно очищаю его, когда что-то делаю с приемом.
Другие советы
Лучше всего просто использовать BANKSEL для автоматического переключения банка. Это специальная директива ассемблера, которая указывает ассемблеру переключиться на правильный банк. Поэтому, если вы хотите получить доступ к PORTB, просто BANKSEL (PORTB) перед его использованием.
PS: PORTB находится в BANK0 в семействе PIC16, а не в BANK1, как в вашем коде.
Мне тоже было очень трудно понять выбор банка.
Я начинаю проект, используя PIC12F1822 из-за их функциональности I2C.Исследование предыстории похоже на распутывание клубка нитей: каждая из них требует немало усилий, прежде чем она прояснится.Одна из тем, которую мне удалось вытащить, — это объяснение директивы «BANKSEL».
Фон.Существует несколько десятков SFR — регистров специальных функций, которые помогают в работе устройства и отображаются в нижней памяти данных.Поскольку их так много, они организованы в 32 банка, пронумерованных от 0 до 31, по 32 SFR каждый.SFR нумеруются последовательно в виде (биты) бббббфффффффф где ббббб это номер банка и ффффффф это зачет в банке.Их значения определены в файле .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