Косвенная адресация очень удобная штука, когда необходимо оперировать с большим количеством регистров, о ней я упоминал еще в первой статье, здесь же покажу, как можно применить данный вид адресации.
Для работы с косвенной адресацией используется регистр специального назначения FSR и физически не реализованный регистр INDF. Принцип работы простой, в регистр FSR записываем адрес какого-либо регистра, пусть это будет регистр с названием temp (то есть адресу этого регистра присвоено название temp с помощью директивы equ), после чего содержимое регистра temp “условно” оказывается в регистре INDF. Теперь все операции, проделанные над регистром INDF, будут выполнены и для регистра temp, на самом же деле обращение к регистру INDF вызовет действие непосредственно с регистром temp, поэтому я и употребил термин “условно”.
Рассмотрим следующую задачу: необходимо получить 10 байт данных от какого-либо устройства по интерфейсу SPI (тут возможен не только SPI, например I2C, UART и т.д.) и разместить их в памяти данных (ОЗУ). В “шапке” программы необходимо присвоить название одному регистру, начиная с которого будут располагаться остальные регистры, в них будет происходить запись принятых байтов, пусть это будет регистр с названием data. Понадобиться еще один регистр (назовем его shet), который будет выступать в качестве счетчика принятых байтов. Код программы представлен ниже:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;"Шапка" программы, здесь адресам регистров присваиваются названия shet equ 20h ;регистр счетчика принятых байтов data equ 21h ;первый регистр для хранения принятых данных ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;Основная программа org 0000h ;начать выполнение программы с адреса 0000h goto Start ;переход на метку Start Start ................. ;здесь происходит первоначальная настройка ................. ;регистров специального назначения ................. movlw .10 ;запись числа 10 в регистр shet, для счета movwf shet ;принятых данных movlw data ;запись адреса регистра data в регистр FSR movwf FSR ; s1 call spi ;вызов подпрограммы получения данных movwf INDF ;запись полученного байта из W в регистр INDF incf FSR,F ;инкремент регистра FSR decfsz shet,F ;декремент с условием регистра shet goto s1 ;регистр shet не равен нулю: переход на метку s1 ;регистр shet равен нулю: дальнейшее ................. ;исполнение основной программы ................. ; ................. ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; spi ................. ;подпрограмма получения данных по интерфейсу ................. ;spi, полученный байт загружается в аккумулятор ................. ;при выходе из подпрограммы return ;выход из подпрограммы ; |
Первым делом записываем число 10 в регистр shet, чтобы вести отчет принятых байтов, далее записываем адрес первого регистра (регистр data по адресу 0х21, который будет использоваться для хранения принятых данных) в регистр FSR. Вызываем подпрограмму spi для получения одного байта данных, при этом байт записывается в аккумулятор при выходе из подпрограммы. По возвращении из подпрограммы записываем принятый байт в регистр INDF, на самом деле этот байт записывается в регистр data, расположенный по адресу 0х21 в памяти данных. Теперь производим инкремент регистра FSR, тем самым подготавливая следующий регистр памяти данных для записи очередного принятого байта. После инкремента в регистре FSR будет лежать число 0х22, то есть это адрес следующего регистра в памяти данных после регистра data. Далее декрементируем регистр shet, если он не равен нулю, переходим на метку s1, получаем новый байт и записываем в регистр INDF, только теперь этот байт запишется в регистр с адресом 0х22. Тем самым после выполнения кода (когда регистр shet обнулится), все 10 принятых байт запишутся в регистры расположенные последовательно по адресам 0х21 – 0х2A.
Конечно, можно поступить просто и прямолинейно, присвоить названия всем 10-ти регистрам, и написать линейный код: вызов подпрограммы spi, далее запись полученного байта в первый регистр, очередной вызов подпрограммы с записью в следующий регистр, и так 10 раз подряд. В итоге получим код размером в 20 строчек (слов памяти программ). Но это будет неоптимизированный код, занимающий много места в памяти программ, а если нам надо принять 20, 40, 60 байт?
Косвенную адресацию можно использовать не только для приема данных, но и в других целях, например выполнение однотипных операций с большим количеством регистров ОЗУ, в частности для реализации динамической индикации и т.д., короче это очень полезная вещь.
При использовании косвенной адресации следует помнить о банках памяти.
Но тут все проще, нежели при непосредственной адресации. Банк указывается одним битом IRP регистра STATUS, если этот бит сброшен, можно обращаться к регистрам расположенным сразу в двух банках, в 0-ом и 1-ом, если бит установлен, обращение идет к регистрам 2-го и 3-го банка.
А не подскажете какую нибудь программу для Pic 12f675 с использованием косвенной адресации,или же где уже имеются написанные программы составленные в MPLAB IDE! А то дали курсовой проект, а данную тему даже не рассматривали
так сходу ничего посоветовать не могу, надо посмотреть, тип микроконтроллера здесь не имеет значения, косвенная адресация одинакова во всем семействе PIC12, PIC16, используются одни и те же регистры. А зачем вам программа, что вы с ней будете делать?
подскажите пожалуйста как использовать косвеггую адресацию на этом примере)
Использовать косвенную адресацию. В регистры h’20’ – h’2 F’ занести константу h’0 F’. [h’2 F’] отобразить в Portb.
Относительная адресация позволяет при меньшей длине адресного кода команды обеспечить доступ к любой ячейке памяти. Для этого число разрядов в базовом регистре выбирают таким, чтобы можно было адресовать любую ячейку оперативной памяти, а адресный код команды используют для представления лишь сравнительно короткого «смещения». Смещение определяет положение операнда относительно начала массива, задаваемого базовым адресом.
Подсажите, как напримере продолжить эту операциюРис.2 Прямая/косвенная адресация в PIC16F877
Пример 1 Косвенная адресация
BCF STATUS, IRP ; Установить банк 0,1
MOVLW 0x20 ; Указать первый регистр в ОЗУ
MOVWF FSR
NEXT:
CLRF INDF ; Очистить регистр
INCF FSR,F ; Увеличить адрес
BTFSS FSR,4 ; Завершить?
GOTO NEXT ; Нет, продолжить очистку
CONTINUE:
; Да
Не понял, что именно вы хотите узнать? в вашем примере выполняется очистка 16 регистров ОЗУ, начиная с адреса 0x20 (32).
Про косвенную, что уходит и приходит )))) в цифрах