44947

Динамическая индикация

Реферат

Информатика, кибернетика и программирование

Для краткости эти регистры обозначим под названиями LED с соответствующей нумерацией. Например если результат измерения подсчета нужно вывести на индикацию как 4 разрядное десятичное число то двоичный результат измерения “прогоняется†через двоично-десятичное преобразование о нем позднее в итоге которого результат измерения помещается в младшие полубайты 4х регистров LED от LED0 до LED3.0 MHz ; DtL equ 0Ch DtH equ 0Dh D_H equ 0Eh D_L equ 0Fh Step equ 1Bh Led0 equ 1Ch Led1...

Русский

2013-11-14

59.87 KB

21 чел.

Динамическая индикация

В большинстве случаев подпрограмма вычисляемого перехода, подобная подпрограмме TABLE, вызывается (call  TABLE) из циклических подпрограмм обработки содержимого неких регистров общего назначения, содержащих в себе данные, предназначенные для вывода на индикацию. Для краткости, эти регистры обозначим под названиями LED с соответствующей нумерацией. Например, если результат измерения (подсчета) нужно вывести на индикацию как 4-разрядное десятичное число, то двоичный результат измерения “прогоняется” через двоично-десятичное преобразование (о нем, позднее), в итоге которого результат измерения помещается в младшие полубайты 4-х регистров LED (от LED0 до LED3). Далее, содержимое этих регистров, с соблюдением порядка старшинства, поочередно копируется в регистр W и подвергается кодовому преобразованию (call  TABLE) и выводится на индикацию в виде символов. Что касается последнего, то “технология” вывода на индикацию проста: результат кодового преобразования из регистра W копируется в регистр того порта, к выводам которого подключены выводы секторов 7-сегментного индикатора.

В общем виде разберемся с таким понятием как динамическая индикация. Для определенности предположим, что в одном полном цикле индикации результаты кодового преобразования последовательно выводятся на индикацию, начиная с младшего десятичного разряда линейки 7-сегментных индикаторов. По окончании последовательного вывода результатов кодового преобразования во все 4 знакоместа линейки происходит переход (по кольцу) на вывод символа в младшее знакоместо линейки. После этого, все опять повторяется снова и снова.

Описанный случай является типичным примером “двойной закольцовки”: один “виток” большого кольца индикации равен 4-м “виткам” малого кольца индикации, “дислоцирующегося” внутри большого кольца индикации. Если речь идет о фиксированном количестве “витков” (4), то количество “витков” малого кольца индикации нужно “поставить на счетчик”. Количество “витков” большого кольца индикации тоже нужно “поставить на счетчик”, ведь нельзя же допустить, чтобы рабочая точка программы все время находилась в подпрограмме вывода данных на индикацию. В противном случае, “не будут делаться другие, важные дела”, например, замеры (или вычисления), для которых и нужна индикация.

Итак, должно быть “отмотано” фиксированное количество “витков” большого кольца индикации, после чего рабочая точка программы должна покинуть подпрограмму вывода данных на индикацию и “сделать другие, важные дела”. После того, как “она их сделает”, и в результате этого в наличии будет иметься то, что нужно вывести на индикацию, снова начинается отработка подпрограммы вывода данных на индикацию. Все повторяется снова. Ну и так далее. В интервале времени каждой такой “отлучки” 7-сегментные индикаторы “гасятся” вплоть до начала следующей отработки подпрограммы вывода данных на индикацию. Это и является причиной так называемых “мерцаний”, являющихся недостатком динамической индикации.

В отдельно взятом 7-сегментном индикаторе символ индицируется (“высвечивается”) в течение интервала времени формирования одного “витка” малого кольца индикации, в интервале которого он активен. В начале следующего “витка” малого кольца индикации этот 7-сегментный индикатор переводится из активного в пассивное состояние (“гасится”), а следующий по разрядности 7-сегментный индикатор активируется. Ну и так далее, до окончания активации последнего 7-сегментного индикатора линейки. Таким образом, речь идет о последовательном поразрядном выводе результатов измерения (счета) на индикацию.

“Привязка” конкретных десятичных разрядов результата измерения (счета) к конкретным знакоместам линейки 7-сегментных индикаторов, осуществляется путем последовательной (в порядке старшинства) “запитки” 7-сегментных индикаторов, входящих в состав линейки. В зависимости от того, какие именно 7-сегментные индикаторы применены (с общим катодом или с общим анодом), эта “запитка” осуществляется либо коммутацией точки соединения общих выводов сегментов на плюс источника питания, либо ее коммутацией на корпус. Остальные выводы сегментов объединяются в группы (по принципу одноименности секторов) и в пределах этих групп “параллелятся”. Получается 8 выводов, которые и подключаются к выводам порта, который задействован для управления линейкой. Сказанное относится к тому случаю, если линейка создается из отдельных, 7-сегментных индикаторов. Если речь идет о промышленных вариантах такой линейки (например, АЛС318), то ничего “параллелить” не нужно, так как это уже сделано разработчиками.

Динамическая индикация организуется тогда, когда линейка состоит из нескольких  7-сегментных индикаторов (знакомест), и выводов используемого микроконтроллера не хватает для индикации информации статическим способом.

Рассмотрим случай организации динамической индикации для линейки 7-сегментных индикаторов, состоящей из 4-х знакомест. Рассматриваемая подпрограмма динамической индикации достаточно универсальна, т.е. она может быть “врезана/встроена” в другие программы. Разрядность можно будет уменьшить (просто) или увеличить (сложнее). По ходу дела, разберемся с косвенной адресацией, который в нашем случае используется для записи константы в регистр.  

В качестве примера используем микроконтроллер PIC16F84A, структурные возможности которого вполне хватают для управления четырьмя 7-сегментными индикаторами. PIC16F84A имеет 2 порта. Порт В, имеющий 8 выводов, “в полном составе” выделяется под управление сегментами 7-сегментных индикаторов (включая и запятую), а функция последовательной активации знакомест передается в порт А, имеющего 5 выводов. Таким образом, 8 выводов соответствующих запараллеленных секторов индикаторов подключаются к 8-ми выводам порта В, а 4 вывода общих катодов индикаторов подключаются к 4-м выводам порта A.

Предметом дальнейшего рассмотрения является программа, в которой результаты счета выводятся на индикацию в линейку из четырех 7-сегментных индикаторов с общим катодом. В данном случае неважно, что именно измеряется. Главное – чтобы на каждом “витке” полного цикла “программы”, к моменту “влёта” рабочей точки программы в подпрограмму преобразований чисел, тем или иным способом, было бы сформировано 4-байтное двоичное число. С ним и будет работать подпрограмма преобразований чисел, а после этого – подпрограмма динамической индикации.

Подпрограмма преобразования двоичных чисел в (далее, для краткости, просто “подпрограмма преобразований чисел”) входит в состав рассматриваемой далее программы, реализующую некое контролирующее устройство, и в которой подпрограмма преобразований чисел работает в комплексе с подпрограммой динамической индикации, а обе они, в свою очередь, “органически вписаны” в программу. Изучение структуры подпрограммы преобразования двоичных чисел в двоично-десятичные коды и освоение характера организации работы (хотя бы, на уровне общих понятий) абсолютно необходимы, так как если нужно визуально отобразить числа в десятичном виде, то без этой подпрограммы просто не обойтись.

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

; Dynamic Display

;===========================

; Microcontroller PIC16F84A

; Clock Frequency 4.0 MHz

;*****************************

DataL  equ  0Ch

DataH equ  0Dh

D_H  equ  0Eh

D_L  equ  0Fh

Step  equ  1Bh

Led0  equ  1Ch

Led1  equ  1Dh

Led2  equ  1Eh

Led3  equ  1Fh

Index  equ  10h

Count  equ  11h

Temp  equ  12h

Mem  equ  13h

TempL equ  14h

TempH equ  15h

;*****************************

org  0

 goto  START

;*****************************

Start   bsf  Status,RP0

 movlw .16

 movwf TrisA

 movlw .00

 movwf TrisB

 bcf  Status,RP0

;===========================

 clrf  DataL

 clrf  DataH

;===========================

Data  movf  DataH,W

 addlw  EСh

 btfss  Status,C

 goto  Incr

;===========================

Decr  decf  Step,F

 movf  Led3,W

 sublw  .9

 btfss  Status,Z

 goto  Cont

 movf  Led2,W

 sublw  .9

 btfss  Status,Z

 goto  Cont

;--------------------------------------------

S_7  movlw .7

 movwf Step

;--------------------------------------------

 movf  Led1,W

 addlw  F8h

 btfss  Status,C

 goto  Cont

 goto  S_1

;===========================

Incr  incf  Step,F

 movf  DataH,F

 btfss  Status,Z

 goto  Cont

 movf  DataL,W

 addlw  F5h

 btfsc  Status,C

 goto  Cont

;--------------------------------------------

S_1  movlw 1

 movwf Step

;===========================

Cont  clrwdt

 movfw Step

 addwf  DataL,F

 btfsc  Status,C

 incf  DataH,F

 movf  DataL,W

 movwf D_L

 movf  DataH,W

 movwf D_H

 call  BinDec

 incfsz  Temp,F

 goto  Data

 call  Clr

 goto  Start

;*****************************

;*****************************

BinDec bcf  Status,C

 movlw .16

 movwf Count

 clrf  Led0

 clrf  Led1

 clrf  Led2

 clrf  Led3

;===========================

Loop8 clrwdt

 rlf   D_L,F

 rlf   D_H,F

 rlf   Led0,F

 rlf   Led1,F

 decfsz Count,F

 goto  adjDEC

;--------------------------------------------

 swapf  Led1,W

 andlw  0Fh

 movwf Led3

;--------------------------------------------

  movfw Led1

 andlw  0Fh

 movwf Led2

;--------------------------------------------

 swapf  Led0,W

 andlw  0Fh

 movwf Led1

;--------------------------------------------

 movfw Led0

 andlw  0Fh

 movwf Led0

 goto  Disp

;===========================

adjDEC movlw Led0

 movwf FSR

 call  adjBCD

;--------------------------------------------

 movlw LED1

 movwf FSR

 call  adjBCD

;--------------------------------------------

 goto  Loop8

;===========================

adjBCD movlw 3

 addwf  0,W

 movwf Mem

 btfsc  Mem,3

 movwf 0

;--------------------------------------------

 movlw 30h

 addwf  0,W

 movwf Mem

 btfsc  Mem,7

 movwf 0

;--------------------------------------------

 retlw  0

;*****************************

Disp  clrwdt

 movlw .3

 movwf Index

 movf  Led3,F

 btfss  Status,Z

 goto  IndexS

;--------------------------------------------

 decf  Index,F

 movf  Led2,F

 btfss  Status,Z

 goto  IndexS

;--------------------------------------------

 decf  Index,F

 movf  Led1,F

 btfss  Status,Z

 goto  IndexS

;--------------------------------------------

 decf  Index,F

;===========================

IndexS clrf  PortA

 movf  Index,W

 addwf  PCL,F

 goto  Disp0

 goto  Disp1

 goto  Disp2

;===========================

Disp3  clrf  PortA

 movf  Led3,W

 call  Table

 movwf PortB

 movlw .8

 movwf PortA

;--------------------------------------------

Disp2  clrf  PortA

 movf  Led2,W

 call  Table

 movwf PortB

 movlw .4

 movwf PortA

;--------------------------------------------

Disp1  clrf  PortA

 movf  Led1,W

 call  Table

 movwf PortB

 movlw .2

 movwf PortA

;--------------------------------------------

Disp0  clrf  PortA

 movf  Led0,W

 call  Table

 movwf PortB

 movlw .1

 movwf PortA

;*****************************

Aud  movf  Led3,W

 sublw  .9

 btfss  Status,Z

 return

 movf  Led2,W

 sublw  .9

 btfss  Status,Z

 return

 movf  Led1,W

 sublw  .9

 btfss  Status,Z

 return

 movf  Led0,W

 sublw  .9

 btfss  Status,Z

 return

 movlw FFh

 movwf Temp

 return

;*****************************

Clr  movlw .3

 movwf Index

 movlw .10

 movwf Led0

 movwf Led1

 movwf Led2

 movwf Led3

 call  IndexS

;--------------------------------------------

 movlw .255

 movwf Temp

Del_0  decfsz Temp,F

 goto  Del_0

;--------------------------------------------

 movlw .3

 movwf Index

 movlw .11

 movwf Led0

 movwf Led1

 movwf Led2

 movwf Led3

 call  IndexS

;--------------------------------------------

 movlw .255

 movwf Temp

Del_1  decfsz Temp,F

 goto  Del_1

;--------------------------------------------

 return

;*****************************

Table  addwf  PCL,F

;--------------------------------------------

 retlw  b'00111111'

 retlw  b'00000110'

 retlw  b'01011011'

 retlw  b'01001111'

 retlw  b'01100110'

 retlw  b'01101101'

 retlw  b'01111101'

 retlw  b'00000111'

 retlw  b'01111111'

 retlw  b'01101111'

;--------------------------------------------

 retlw  b'10001000'

 retlw  b'00000000'

;*****************************

 end

Сначала разберемся с общей “конструкцией” программы. В начале ее исполнения, рабочая точка программы начинает свое движение по “линейному” участку программы, начиная с 1-й ее команды и до команды вызова подпрограммы BinDec. В начальном участке программы размещена подпрограмма Data, последовательно формирующая двухбайтные данные (в диапазоне от 0 до 270Fh) с определенным шагом, предназначенные для отображения на четырех 7-сегментных индикаторах в виде десятичных чисел (от 0 до 9999). Характер изменения значений шага итерации формируемых данных обеспечивает наглядность наблюдения за результатами индикации отображаемых данных.

После исполнения команды call BinDec, рабочая точка программы “прыгает” на 1-ю команду подпрограммы преобразований чисел BinDec, после чего она начнет исполняться. В результате исполнения команды call BinDec адрес команды, следующей за этой командой, “закладывается” в стек и находится там до окончания отработки подпрограммы BinDec. После окончания отработки подпрограммы BinDec (после исполнения команды return) из вершины стека “выгружается” указанный выше адрес и после отработки всех оставшихся команд подпрограммы Start вызывается подпрограмма динамической индикации Disp и начинается ее исполнение.

Преобразование двоичных двухбайтных чисел, переданных  из подпрограммы Start, в двоично-десятичные коды выполняется в начале подпрограммы BinDec и далее осуществляется их отображение на четырех 7-сегментных индикаторах (в подпрограмме Disp). После этого в подпрограмме Aud осуществляется проверка возможности продолжения формирования следующих данных, т.е. достижение предельного значения формируемых чисел. Результат проверки поступает в основную программу в виде значения содержимого регистра Temp. Значение 0 соответствует возможности (и необходимости) продолжения формирования последовательности чисел и рабочая точка программы переходит к метке Data для формирования (выборки) новых значений отображаемых чисел. Значение FFh сообщает о достижении предела формируемых (270Fh) и, соответственно, отображаемых чисел (9999). В последнем случае выполняются подпрограмма Clr, наглядно демонстрирующая о завершении одного цикла индикации сформированных данных и перехода к следующему циклу.

А теперь давайте разберемся в сути преобразований двоичных чисел в двоично-десятичные коды. Предположим, что группа подпрограммы формирования двухбайтного двоичного числа выдала очередное число. По определению, такое число должно быть “заложено” в 2 регистра общего назначения. Они в программе определены под названиями DataH и DataL.

Линейка 7-сегментных индикаторов, состоящая из 4-х знакомест, может отобразить десятичное число не более 9999. Двоичный эквивалент этого числа в стандартном весовом коде: 10 0111 0000 1111 (в шестнадцатеричной записи – 270Fh).

Двоично-десятичное число, по определению, не может быть больше 9. Из этого следует то, что оно отображается только в младшем полубайте байта, а старший полубайт байта всегда будет равен нулю (0000хххх). Например, десятичное число 9999 в двоичном виде может быть отражено в 2-байтном регистре, но в двоично-десятичном виде такое число не может быть отражено в двух регистрах. В последнем случае для отображения этого числа потребуется 4 регистра. Итак, число 9999 в двоично-десятичном виде выглядит так: 00001001 00001001 00001001 00001001, т.е. во всех младших полубайтах всех 4-х регистров, “лежат” девятки, а во всех старших полубайтах – нули. Вот зачем и нужны 4 регистра Led0...3, “прописанные” в "заголовке" программы. Первые два из них (Led0 и Led1) в подпрограмме преобразований чисел задействуются для хранения промежуточных и конечных результатов преобразований.

На конечной стадии работы подпрограммы преобразований чисел из младших и старших полубайтов регистров Led0 и Led1 в младшие полубайты регистров Led0 и Led3 переписываются конечные результаты преобразований чисел. Это и есть то, что в дальнейшем, подлежит кодировке. При этом, в старших полубайтах Led0...3 “выставляются” нули. Это как раз то, что Вы видите в примере (для случая 9999). В конечном итоге, в младших полубайтах регистров Led0...3, на все время полного цикла подпрограммы динамической индикации, фиксируются двоично-десятичные числа, с которыми эта подпрограмма и будет работать. 

В общем виде опишем работу подпрограммы преобразований чисел. После “влёта” рабочей точки программы в подпрограмму преобразований (BinDec), в предварительно назначенный счетчик “проходов” Count записывается константа, значение которой равно суммарному количеству битов 2-байтного регистра D_H/D_L (в нем находится 2-байтное двоичное число, которое нужно преобразовать в двоично-десятичное), т.е.  числовое значение этой константы должно быть равно .16. На каждом из 16-ти “витков” внутреннего цикла подпрограммы преобразований чисел, содержимое счетчика “проходов” Count декрементируется, и если результат декремента не равен 0, то происходит переход рабочей точки программы на следующий “виток” внутреннего цикла подпрограммы преобразований чисел. Таким образом, войдя в подпрограмму преобразований чисел, рабочая точка программы “наматывает” 16 “витков” внутреннего цикла подпрограммы преобразований чисел, которые, в сумме, составляют полный цикл подпрограммы преобразований чисел.

Поясним события, происходящие в процессе “прохождения” рабочей точкой программы каждого из 16-ти “витков” внутреннего цикла подпрограммы преобразований чисел. Сначала производится групповой, циклический сдвиг содержимого 4-байтного регистра Led1/Led0/D_H/D_L влево (через бит С регистра Status). Перед этим (в начале исполнения полного цикла подпрограммы преобразований чисел) в регистры Led0...3 записываются нули, т.е. их “старое” содержимое удаляется, после чего они готовы к работе. В результате каждого такого группового сдвига (последовательный сдвиг содержимого 4-х регистров. 4 команды rlf) происходит перенос содержимого старшего бита регистра D_H в младший бит регистра Led0. Таким образом, через 16 таких сдвигов, содержимое D_H/D_L переместится в Led1/Led0 (по принципу “бегущей строки”).

Следовательно, после очередного группового сдвига, т.е. на момент завершения всех 16-ти групповых сдвигов (счетчик проходов Count очищен), во всех 8-ми полубайтах 4-байтного регистра Led0/Led1/Led2/Led3, с соблюдением порядка старшинства, “осядут” двоично-десятичные числа, точно отражающие значение исходного двоичного числа. Ясно, что здесь речь идет о процедуре типа “чтение – модификация – запись”. Так как запись результатов числовых преобразований производится в те же регистры, из которых производилось чтение (Led0...3), то при модификации должен задействоваться регистр оперативной памяти (в нашем случае – Mem), в котором будут храниться как промежуточные, так и конечные результаты преобразований чисел. По окончании текущего цикла модификации, модифицированное число, “осевшее” в регистре Mem, копируется в текущий Led. После того, как будет “отмотано” 16 “витков” внутреннего цикла подпрограммы преобразований чисел, во всех 8-ми полубайтах 4-байтного регистра Led0/Led1/Led2/Led3 будут “лежать” 4 двоично-десятичных числа. Остается только “раскидать” их (также с соблюдением порядка старшинства) по младшим полубайтам регистров Led0, Led1, Led2, Led3, а в их старшие полубайты, “принудительно” записать нули (см. пример двоично-десятичного представления числа 9999). После выполненного преобразования (расстановки) содержимое регистров Led0...3 можно обрабатывать в подпрограмме динамической индикации. 

Разберемся со стратегией работы подпрограммы преобразований чисел (BinDec). Подпрограмма BinDec начинается с подготовительных операций. Флаг переноса-заема С опускается (бит С регистра Status сбрасывается в 0), в счетчик проходов Count записывается константа, числовое значение которой равно общему количеству битов 2-байтного регистра D_L/D_H (.16), и содержимое всех регистов Led сбрасывается в 0. Подготовительные операции закончены. Далее, начинается отработка подпрограммы Loop8. В ее начале происходит циклический сдвиг влево, на одну позицию (через бит С регистра Status), содержимого 4-разрядного регистра D_L/D_H/Led0/Led1 (4 команды rlf), а потом содержимое счетчика количества проходов (Count) декрементируется (decfsz Count,F) с сохранением результата декремента в нем же). Так как байт-ориентированная команда decfsz является командой ветвления, то возможны два сценария работы программы. Предположим, что результат декремента равен 0 (“отмотаны” все 16 “витков”). В этом случае, начнется отработка группы команд поразрядного распределения содержимого регистров Led0 и Led1 (обеих полубайтов) по младшим полубайтам регистров Led0...3. Если результат декремента содержимого регистра Count не равен 0, то осуществляется безусловный переход в подпрограмму adjDEC.

В состав подпрограммы adjDEC входят 2 группы команд, в каждой из которых осуществляется условный переход в подпрограмму adjBCD. Возврат происходит на следующую (из этих двух) группу команд. Каждая из этих групп команд работает со “своим” регистром Led, т.е. соблюдается порядок старшинства (в начале подпрограммы adjDEC, происходит “работа” с содержимым регистра Led0, а затем – с содержимым регистра Led1). Предположим, что с содержимым регистра Led1 осуществлены необходимые действия и произошел возврат на команду goto Loop8. После исполнения этой команды, начнется “отмотка нового витка” внутреннего цикла подпрограммы BinDec (напоминаю, что таких “витков” – 16). На каждом таком “витке”, происходит сдвиг содержимого 4-байтного регистра D_L/D_H/Led0/Led1, по направлению от D_L к Led1, т.е. 2-байтный регистр Led0/Led1 будет последовательно заполняться результатами числовых преобразований. Итак, подпрограмма adjDEC никаких числовых преобразований не осуществляет, а исполняет функцию “администратора”, т.е. определяет порядок обработки содержимого регистров Led0 и Led1. 

В состав каждой из этих 2-х групп команд входят две команды процедуры “разорванной”, косвенной адресации. Слово “разорванной” означает то, что в подпрограмме adjDEC осуществляется только запись в регистр FSR адреса регистра, с содержимым которого будут производиться действия, а сами эти действия производятся в другой подпрограмме (в подпрограмме adjBCD).

После исполнения команды movlw Led... (0, 1), в регистр W записывается адрес текущего регистра Led. После исполнения команды movwf FSR, этот адрес, из регистра W, копируется в регистр FSR. Далее, осуществляется условный переход в подпрограмму adjBCD (call adjBCD). После того, как подпрограмма adjBCD будет отработана, т.е. будет исполнена команда retlw 0, содержимое регистра W сбрасывается в 0 и происходит возврат на команду записи в регистр W адреса следующего регистра Led. Проще говоря, начинается обработка содержимого следующего регистра Led. И так будет происходить до тех пор, пока не будет обработано содержимое регистра Led1. После этого, осуществляется безусловный переход в подпрограмму Loop8, т.е. на новый “виток” внутреннего цикла подпрограммы BinDec.

А теперь обратим внимание на стек. Ранее рассматривались случаи, когда в стек “закладывался” только один адрес возврата. В данном случае адрес возврата на 1-ю, после команды call BinDec, команду программы, будет “лежать” в стеке вплоть до окончания отработки подпрограммы BinDec, но только преимущественно (основную часть времени) не в вершине стека (в 1-й его строке), а во 2-й строке, так как после исполнения команд call adjBCD, вершину стека поочередно будут занимать соответствующие адреса возвратов. Таким образом, если на момент исполнения текущей команды call, в стеке уже находится адрес (адреса) возврата, “заложенный” в него ранее, то в таблице стека (всего в этой таблице 8 строк), он (они) сместится на одну позицию вниз, а в вершину стека запишется адрес возврата, соответствующий текущей (последней) команде call. После освобождения вершины стека, все “имеющиеся в наличии”, активные адреса возвратов, синхронно сместятся вверх на одну позицию (строку), после чего, в вершине стека будет “лежать” адрес возврата, ранее “дислоцировавшийся” во 2-й строке.

Итак, после записи, в регистр FSR, адреса текущего LEDа (в подпрограмме adjDEC), происходит условный переход в подпрограмму adjBCD. Подпрограмма adjBCD является как бы “основной кухней” преобразования чисел. Она обрабатывает результаты групповых, циклических сдвигов, находящиеся в регистрах Led0 и Led1. В начале подпрограммы adjBCD, с помощью команды movlw 3, в регистр W записывается константа 03h (00000011), которая далее, с помощью команды addwf 0,W, суммируется с содержимым текущего регистра LED. Этой командой завершается ранее начатая процедура косвенной адресации.

Обращение к регистру INDF в подпрограмме происходит не непосредственно, а через его адрес (косвенно). В данном случае, происходит обращение к числу 0, т.е. к адресу регистра. В области оперативной памяти, по адресу 00h, “дислоцируется” регистр INDF. Следовательно, обращение происходит именно к нему. А если происходит обращение к регистру INDF (прямое или косвенное, без разницы), то по определению, происходит обращение к содержимому того регистра, адрес которого записан в регистре FSR. В регистре FSR, “лежит” адрес текущего регистра LED, следовательно, произойдет суммирование содержимого текущего регистра LED c ранее записанной, в регистр W, константой 03h. Результат суммирования сохранится в регистре W. Затем, результат суммирования, из регистра W, копируется в регистр оперативной памяти Mem, после чего, состояние бита №3 анализируется (btfsc Mem,3). Если в этом бите 1, то исполняется команда movwf 0, в которой также происходит обращение не к названию регистра INDF, а к адресу регистра INDF (00h), т.е.  происходит обращение к содержимому текущего регистра LED. Таким образом, команда movwf 0 копирует содержимое регистра W, в текущий регистр LED. А так как в регистре W находится то же самое, что и в регистре Mem, то фактически, происходит копирование содержимого регистра Mem, в текущий регистр LED. Если бит №3 регистра Mem равен 0, то процедура суммирования повторится снова, но только в регистр W будет записана не константа 03h, а константа 30h (00110000), и будет произведен анализ состояния не бита №3, а бита №7 регистра Mem. Если бит №7 регистра Mem будет равен 0, то произойдет возврат в подпрограмму adjDEC, после чего произойдет смена текущего регистра LED, следующий переход в подпрограмму adjBCD, ее отработка, возврат в подпрограмму adjDEC и т.д. До тех пор, пока не будет закончена обработка содержимого регистра LED1. Далее, исполняется команда goto Loop8, после чего начинается “отмотка” следующего витка/кольца подпрограммы BinDec. И так  16 раз.

После того, как содержимое счетчика количества проходов Count станет равным 0, начнется отработка группы команд поразрядного распределения содержимого регистров Led0 и Led1 по младшим полубайтам регистров Led0...3. На момент начала ее отработки, в 4-х полубайтах регистров Led0 и Led1, в порядке старшинства, будут “лежать” результаты преобразований, в виде четырех 4-битных, двоично-десятичных чисел.

Распределение начинается со старшего полубайта регистра Led1 (он “уходит” в младший полубайт регистра Led3. В его старший полубайт записывается 0) и далее, по-порядку (в сторону уменьшения разрядности) и аналогично. В данном случае (4 знакоместа) в наличии должно быть 4 групп команд распределения. Причем, при распределении каждого полубайта, должна гарантированно обеспечиваться запись нуля в старший полубайт регистра-получателя. Эти 4 группы команд, по сути, выполняют одну и ту же “работу”, но разными способами:  

  1. 4 группы команд, работающие с младшими полубайтами регистров Led0 и Led1, – одним способом;
  2. и 4 группы команд, работающие со старшими полубайтами регистров Led0 и Led1, – другим.

Это обусловлено положением полубайта в байте. Если полубайт старший, то необходимо задействовать команду смены местами старшего и младшего полубайтов (swapf), а если полубайт младший, то этого не требуется. Рассмотрим работу первой из этих групп команд. Распределение начинается со старшего полубайта регистра Led1. С помощью команды swapf Led1,W, старший и младший полубайты регистра Led1 меняются местами. Результат этой операции сохраняется в регистре W. С помощью команды andlw 0Fh, выполняется логическая операция побитного И содержимого регистра W и константы 0Fh (.15 или 00001111) т.е. выполняется побитное И содержимого регистра Led1 (с учетом смены местами его полубайтов) и константы 0Fh, с сохранением результата этой операции в регистре W. В результате этого, старший полубайт “встает на место” младшего, и в старшем полубайте устанавливается 0. По логике операции И, результат побитного И с нулем, всегда есть ноль, а результат побитного И с единицей, повторяет состояние второго “участника” этой логической операции. Таким образом (movwf Led3), в младший полубайт регистра Led3 записывается старший полубайт регистра Led1 и в старшем полубайте регистра Led3 устанавливается 0. Следующая группа команд работает с младшим полубайтом регистра Led1. В этом случае, менять местами полубайты регистра Led1 не нужно. Первая команда (movfw Led1) копирует содержимое регистра Led1 в регистр W. Работа второй команды (andlw 0Fh) описана выше.

Работа третьей команды (movwf Led0) описана выше, разница только в том, что содержимое регистра W копируется не в регистр Led3, а в регистр Led1. Таким образом (movwf Led0), в младший полубайт регистра Led0, записывается младший полубайт регистра Led1, и в старшем полубайте регистра Led0 устанавливается 0. Другая пара групп команд распределения полубайтов работают аналогично.

При распределении полубайтов в регистры Led0 и Led1, содержимое их ранее распределенных полубайтов во внимание не берется (они уже распределены), и с ними можно проводить описанные выше операции, не опасаясь “уничтожить нужный” полубайт. На конечной стадии распределения, младший полубайт регистра Led0 копируется в него же.

Рассмотренная подпрограмма динамической индикации BinDec достаточно универсальна, т.е. она может быть “врезана/встроена” в другие программы, с соответствующим изменением разрядности.

Работу программы можно проверить на симуляторе, для чего следует установить скорость моделирования (Rate) на Extremely Fast и запустить его. При такой проверке можно заметить, что шаг выборки (точнее, формирования) индицируемых чисел не остается постоянным, а изменяется. Эти изменения, осуществляемые в подпрограммах Incr или Decr, можно наблюдать в регистре Step, прописанном по адресу 01Bh. Характер этих изменений, осуществляемых в рассматриваемой программе, подобран таким образом, чтобы быстрее “пройти” весь диапазон отображаемых (формируемых) чисел (от 0 до .9999) и в то же время “успевать” заметить результаты переносов от разряда к разряду, происходящие при добавлении к предыдущему числу текущего шага (Step).


 

А также другие работы, которые могут Вас заинтересовать

70859. Этика отношений преподавателя и студента 98.5 KB
  Этические кодексы поведения запрещает преподавателю узурпировать свою власть над студентом особенно в форме эксплуатации или насилия в различных видах: сексуальном расовом религиозном интеллектуальном принуждать студентов делать то что не является предметом изучения его дисциплины.
70860. Обучение студентов и школьников навыкам изучения правовых наук 104.5 KB
  Творческие работы как элемент мотивации студентов к изучению правовых наук. Обучение студентов и школьников работе с текстом книгой Учебный текст как модель представления научных знаний это обобщенное содержание учебного процесса. Студентов следует учить как работать с текстом.
70861. Основные требования к преподавателю общественных дисциплин 89 KB
  Педагоги используют различные способы мотивирования студентов к учебе. Первый использует собственный авторитет свою личность для того чтобы привлечь студентов а затем пытается перенести интерес студентов от себя к предмету.
70862. Дискуссия как эффективный метод проведения семинарского занятия по правоведческим наукам 120 KB
  Дискуссии и диалоги их преимущества и недостатки. Роль преподавателя в проведении дискуссии. Приемы и методы проведения дискуссии. Дискуссии и диалоги их преимущества и недостатки.
70863. Демократический идеал и методика преподавания общественно- правовых дисциплин 57 KB
  По содержанию гуманитарное образование можно определить как учебно-воспитательный процесс преподавания и усвоения широкого круга гуманитарных дисциплин исторических философских политологических социологических экономических культурологических филологических...
70864. Использование семинаров и школьных уроков в преподавании правовых дисциплин 116.5 KB
  Помогает расширить закрепить и обогатить знания студентов по отдельным темам курса активизировать работу студентов привить им вкус к публичным выступлениям. Иные авторы подчеркивают что неформальная структура семинара дает возможность большему числу...