Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Samouchitel

.pdf
Скачиваний:
16
Добавлен:
13.02.2015
Размер:
3.65 Mб
Скачать

(если 7 знакомест, то 3-байтное. Почему? Об этом говорилось ранее).

Вданном, "учебно-тренировочном" случае, не имеет значения, каким именно образом сформировано 4-байтное двоичное число.

Вариантов его формирования может быть множество.

Их выбор зависит от функционального предназначения разрабатываемого устройства и выбранного способа его аппаратной и программной реализации.

Количество "рабочих" знакомест линейки можно изменить.

Если требуется количество знакомест меньшее, чем 8, то в группе команд Увеличение на 1 содержимого счетчика ..., нужно заменить число .08 на число десятичных разрядов, которое требуется (.07, .06, ...).

Например, конструируется устройство с использованием 4-х знакомест. Заменяем .08 на .04.

После этого, в группе команд установки запятой, нужно заменить пятерку на тот номер знакоместа, в котором нужно выставить запятую и определиться с времязадающими константами X, Const1 и Const2.

Вэтом случае, строки с "пропиской" регистров LED4 ... LED7, из "шапки" программы, нужно удалить (не используются).

Если запятую выставлять не нужно, то все команды группы команд установки запятой и первую команду группы команд вывода десятичной цифры на индикацию (вместе с названием метки No_Dot), можно удалить.

Вэтом случае, возврат (из ПП TABLE) будет происходить на команду movwf PortB.

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

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

Дополнительно

Вобучающих целях, группа команд работы с содержимым регистра Index программы Fsr.asm (начинается с команды incf Index,F, а заканчивается командой goto CYCLE) предоставлена в том виде, в котором Вы видите ее в программе Fsr.asm.

Вней "фигурирует" восьмерка, которая "бросается в глаза". Так удобнее.

Но можно "зайти и с другого бока".

При переходе от числа 7 к числу 8, бит №3 изменяет свое состояние с 0 на 1, а во всех остальных случаях (от 0 до 7 включительно), он имеет значение 0.

Вот за это и можно "зацепиться". Получается такая компактная группа команд:

incf Index,F btfss Index,3 goto CYCLE

которой смело можно заменить соответствующую группу команд программы Fsr.asm. Это называется многовариантностью.

Люди пытливого склада ума найдут в этом много интересного.

А это картинка, поясняющая принцип динамической индикации (используется линейка из восьми 7-сегментных индикаторов с общим катодом):

241

242

16. Преобразование двоичных чисел в двоично-десятичные. Окончательное формирование текста подпрограммы динамической индикации.

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

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

Если я "выдам на гора" готовую подпрограмму, то она будет подобна "бесплатному сыру" ("расплата" наступит при первом же затруднении), а если "уйду в детали", то с непривычки, может получиться "перенапряг и отбитие почек".

То есть, необходим разумный компромисс. Так и сделаю.

А заодно, "попутно" разберемся с некоторыми "новенькими штучками" и приобретем полезные навыки.

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

Результаты измерений выводятся на индикацию в линейку из 8-ми 7-сегментных индикаторов.

По большому счету, в данном случае, неважно, что именно измеряется.

Главное - чтобы на каждом "витке" полного цикла "программы", к моменту "влёта" рабочей точки программы в ПП преобразований чисел, тем или иным способом, было бы сформировано 4-байтное двоичное число.

Сним и будет работать ПП преобразований чисел, а после этого, ПП динамической индикации.

Файл программы называется Bin2_10.asm (находится в папке "Тексты программ").

Она выглядит так:

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

;ГРУППА ПОДРПРОГРАММ ПРЕОБРАЗОВАНИЯ ДВОИЧНЫХ ЧИСЕЛ

; В ДВОИЧНО-ДЕСЯТИЧНЫЕ

; (для случая преобразования 4-байтных двоичных чисел в 8-разрядные десятичные).

;******************************************************************************** ; "ШАПКА ПРОГРАММЫ"

;******************************************************************************** ; Bin2_10.asm Универсальная группа подпрограмм преобразования 4-байтных

;

двоичных чисел в 8-разрядные десятичные числа.

;

.............................................................

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

; Определение положения регистров специального назначения.

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

Indf

equ

00h

; Регистр Indf.

Status

equ

03h

;

Регистр

Status.

FSR

equ

04h

;

Регистр

FSR.

;.............................................................

 

 

 

 

 

;.............................................................

 

 

 

 

 

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

; Определение названия и положения регистров общего назначения.

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

LED0

equ

10h

; Регистр хранения результатов преобразований

 

 

 

; 1-го двоично-десятичного разряда.

LED1

equ

11h

; -------

2-го -------------------------

LED2

equ

12h

; -------

3-го -------------------------

LED3

equ

13h

; -------

4-го -------------------------

LED4

equ

14h

; -------

5-го -------------------------

243

LED5

equ

15h

; -------

6-го -------------------------

LED6

equ

16h

; -------

7-го -------------------------

LED7

equ

17h

; -------

8-го -------------------------

Count

equ

0Dh

; Счетчик проходов.

Mem

equ

1Fh

; Регистр оперативной памяти.

TimerL

equ

1Bh

; Регистр младшего разряда 4-байтного

 

 

 

; двоичного числа.

TimerM

equ

1Ch

; Регистр среднего разряда 4-байтного

 

 

 

; двоичного числа.

TimerH

equ

1Dh

; Регистр старшего разряда 4-байтного

 

 

 

; двоичного числа.

TimerHH

equ

1Eh

; Регистр самого старшего разряда 4-байтного

 

 

 

; двоичного числа.

;.............................................................

;.............................................................

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

; Определение места размещения результатов операций.

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

W

equ

0

;

Результат

направить

в

аккумулятор.

F

equ

1

;

Результат

направить

в

регистр.

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

; Присваивание битам названий.

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

C equ 0 ; Флаг переноса-заёма.

;.............................................................

;.............................................................

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

org

0

;

Начать выполнение программы

goto

START

;

с подпрограммы START.

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

;******************************************************************************** ; РАБОЧАЯ ЧАСТЬ ПРОГРАММЫ

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

START

.....................................

 

 

 

;

.....................................

 

 

 

NEW

call

Bin2_10

;

Условный переход в ПП Bin2_10

 

 

 

;

Адрес следующей команды закладывается в стек

;

.....................................

 

 

 

; .....................................

;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

;ГРУППА ПОДПРОГРАММ 8-РАЗРЯДНОЙ ДИНАМИЧЕСКОЙ ИНДИКАЦИИ без ПП TABLE

;(то, что было рассмотрено ранее).

;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

;.... .....................................

;

.....................................

;....

.....................................

;

.....................................

;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ; ГРУППА ПОДПРОГРАММ ФОРМИРОВАНИЯ 4-БАЙТНОГО ДВОИЧНОГО ЧИСЛА.

;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

;....

.....................................

;

.....................................

;....

.....................................

;

.....................................

;

.....................................

; К этому моменту 4-байтное двоичное

число (в регистре

 

; TimerL/TimerM/TimerH/TimerHH) должно быть сформировано

для последующей

; обработки его в группе подпрограмм

преобразования 4-байтных двоичных чисел

; в 8-разрядные десятичные числа.

 

 

 

goto

NEW

;

Безусловный переход

на метку NEW

 

 

;

подпрограммы START,

то есть, начало нового

 

 

;

полного цикла "программы".

;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

244

;ГРУППА ПОДПРОГРАММ ПРЕОБРАЗОВАНИЯ 4-БАЙТНЫХ ДВОИЧНЫХ ЧИСЕЛ В 8-РАЗРЯДНЫЕ

;ДЕСЯТИЧНЫЕ ЧИСЛА.

;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

;Подготовка к преобразованию.

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

Bin2_10

bcf

Status,C

;

Сброс флага переноса-заёма.

 

movlw

.32

;

Запись в регистр Count числа проходов

 

movwf

Count

;

преобразования, равного суммарному

 

 

 

;

количеству битов многоразрядного регистра

 

 

 

;

TimerL/TimerM/TimerH/TimerHH (8*4=32).

 

clrf

LED0

;

Сброс в 0 содержимого регистра LED0.

 

clrf

LED1

;

-------"------

LED1.

 

clrf

LED2

;

-------"------

LED2.

 

clrf

LED3

;

-------"------

LED3.

 

clrf

LED4

;

-------"------

LED4.

 

clrf

LED5

;

-------"------

LED5.

 

clrf

LED6

;

-------"------

LED6.

 

clrf

LED7

;

-------"------

LED7.

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

 

 

 

 

 

; Примечание: процесс преобразования

заканчивается при уменьшении числа проходов

; преобразования, которые заложены в регистр Count (.32), до нуля.

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

; Циклический сдвиг влево.

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

Loop16

rlf

TimerL,F

; Циклический сдвиг влево 4-байтного двоичного

 

rlf

TimerM,F

; числа, записанного в группе регистров

 

rlf

TimerH,F

; TimerL/TimerM/TimerH/TimerHH, на одну

 

rlf

TimerHH,F

; позицию через бит С регистра STATUS.

 

rlf

LED0,F

; Циклический сдвиг влево 4-байтного двоичного

 

rlf

LED1,F

; числа, записанного в группе регистров

 

rlf

LED2,F

; LED0/LED1/LED2/LED3, на одну позицию через

 

rlf

LED3,F

; бит С регистра STATUS.

 

decfsz

Count,F

; Декремент (-1) содержимого регистра Count с

 

 

 

; сохранением результата в нем же.

 

goto

adjDEC

; Если результат не=0, то переход в ПП adjDEC

 

 

 

; Если результат =0, то программа

 

 

 

; исполняется далее.

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

;

Поразрядное

распределение содержимого регистров LED0...

3 (обоих

;

полубайтов)

по младшим полубайтам регистров LED0...

7.

 

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

swapf

LED3,W

; Запись старшего полубайта LED3

andlw

0Fh

; в младший полубайт LED7.

movwf

LED7

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

movfw

LED3

; Запись младшего полубайта LED3

andlw

0Fh

; в младший полубайт LED6.

movwf

LED6

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

swapf

LED2,W

; Запись старшего полубайта LED2

andlw

0Fh

; в младший полубайт LED5.

movwf

LED5

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

movfw

LED2

; Запись младшего полубайта LED2

andlw

0Fh

; в младший полубайт LED4.

movwf

LED4

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

swapf

LED1,W

; Запись старшего полубайта LED1

andlw

0Fh

; в младший полубайт LED3.

movwf

LED3

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

movfw

LED1

; Запись младшего полубайта LED1

andlw

0Fh

; в младший полубайт LED2.

movwf

LED2

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

245

swapf

LED0,W

; Запись

старшего полубайта LED0

andlw

0Fh

; в младший полубайт LED1.

 

movwf

LED1

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

 

 

movfw

LED0

; Запись

младшего полубайта LED0

andlw

0Fh

; в младший полубайт LED0.

 

movwf

LED0

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

 

 

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

 

 

 

 

; Конец распределения. В младших полубайтах

регистров LED0...

7

;установлены двоично-десятичные числа в порядке возрастания разрядности.

;Старшие полубайты = 0.

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

 

 

return

;

Переход по стеку в группу подпрограмм

 

;

8-разрядной динамической индикации.

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

; Запись в регистр FSR адресов регистров LED0...3 для дальнейшей косвенной

;адресации к ним в ПП adjBCD.

;Переход к обработке следующего LED - после возврата по стеку.

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

adjDEC

movlw

LED0

;

Запись в регистр FSR, через регистр W,

 

 

movwf

FSR

;

адреса регистра LED0 с дальнейшим переходом

 

 

call

adjBCD

;

в ПП adjBCD (адрес следующей команды

 

 

 

 

;

закладывается в стек).

;---

> Возврат по стеку из ПП adjBCD.

 

 

 

movlw

LED1

;

-----------------------------

 

 

movwf

FSR

;

То же самое для регистра LED1.

 

 

call

adjBCD

;

-----------------------------

;---

> Возврат по стеку из ПП adjBCD.

 

 

 

movlw

LED2

;

-----------------------------

 

 

movwf

FSR

;

То же самое для регистра LED2.

 

 

call

adjBCD

;

-----------------------------

;---

> Возврат по стеку из ПП adjBCD.

 

 

 

movlw

LED3

;

-----------------------------

 

 

movwf

FSR

;

То же самое для регистра LED3.

 

 

call

adjBCD

;

-----------------------------

;---

> Возврат по стеку из ПП adjBCD.

 

 

 

goto

Loop16

;

Проход всех LED (с LED0 по LED3). Переход в

 

 

 

 

;

ПП Loop16, то есть на следующее кольцо

 

 

 

 

;

числовых преобразований.

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

; Основные операции преобразования двоичных чисел в двоично-десятичные:

; операции сложения LED0...3 и констант 03h,30h с условиями по 3-му и 7-му битам.

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

adjBCD

movlw

3

; Сложить содержимое

текущего LED (LED0...3) с

 

addwf

0,W

; числом 03h, c записью результата операции,

 

movwf

Mem

; через регистр W, в

регистр Mem.

 

btfsc

Mem,3

; Анализ состояния 3-го бита регистра Mem.

 

movwf

0

; Если бит № 3 =1, то содержимое регистра Mem

 

 

 

; копируется в текущий LED.

 

movlw

30

; Если бит №3 =0, то

содержимое текущего LED

 

addwf

0,W

; складывается с константой 30h, с последующей

 

movwf

Mem

; записью результата

операции, через регистр

 

 

 

; W, в регистр Mem.

 

 

btfsc

Mem,7

; Анализ состояния 7-го бита регистра Mem.

 

movwf

0

; Если бит №7 =1, то

содержимое регистра Mem

 

 

 

; копируется в текущий LED.

 

retlw

0

; Если бит №7 =0, то

регистр W очищается и

 

 

 

; происходит возврат

по стеку в ПП adjDEC.

;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

;ГРУППА КОМАНД ПРЕОБРАЗОВАНИЯ ДВОИЧНО-ДЕСЯТИЧНОГО КОДА В КОД 7-СЕГМЕНТНОГО

;ИНДИКАТОРА (относится к группе подпрограмм динамической индикации).

;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ TABLE .....................................

;.....................................

246

; .....................................

;******************************************************************************** end ; Конец программы.

Сначала разберемся с общей "конструкцией" программы.

Вначале ее исполнения, рабочая точка программы начинает свое движение по "линейному" участку ПП START, начиная с 1-й ее команды и до команды call Bin2_10.

После исполнения команды call Bin2_10, рабочая точка программы "прыгает" на 1-ю команду ПП преобразований чисел Bin2_10, после чего она начнет исполняться.

Врезультате исполнения команды call Bin2_10, адрес команды, следующей за командой call Bin2_10, "закладывается" в стек и находится там до окончания отработки ПП Bin2_10. После окончания отработки ПП Bin2_10 (после исполнения команды return), из вершины стека "выгружается" указанный выше адрес, и после отработки всех оставшихся команд ПП START, начинается исполнение ПП динамической индикации (то, о чем говорилось в предыдущем разделе).

После отработки ПП динамической индикации, рабочая точка программы переходит в ПП формирования 4-байтного, двоичного числа.

Обращаю Ваше внимание на то, что этот переход происходит без использования команды перехода, так как работа происходит на "линейном" участке программы (просто исполняется следующая команда).

"Конструкций" подпрограмм формирования 4-байтного, двоичного числа может быть множество. Это зависит от функциональности устройства, которое обслуживает программа. Главное, чтобы в результате работы этой ПП, тем или иным способом, было сформировано 4-байтное, двоичное число.

После того как это произошло, для обеспечения перехода в ПП преобразований чисел ("закольцовки"), осуществляется безусловный переход на метку NEW, входящую в состав ПП

START.

Таким образом, мы "прошлись" по кольцу полного цикла программы.

По ходу исполнения программы, таких колец может быть "намотано" множество.

Это зависит от времени, в течение которого устройство находится во включенном состоянии. Разбираемся с возможными "непонятками".

Вопрос: "Зачем осуществлять безусловный переход на метку NEW? Если этого не делать (команда goto NEW и метка NEW отсутствуют), то из ПП формирования 4-байтного, двоичного числа, в ПП преобразований чисел, рабочая точка программы перейдет самоходом (стык находится на линейном участке программы)".

Ответ: да, таким образом рабочая точка программы войдет в ПП преобразований чисел, но выйти из нее она не сможет, так как стек будет пустой (куда переходить? "Глюк").

А пустой он будет потому, что перед исполнением ПП преобразований чисел, в него не "заложился" адрес возврата (не исполнена команда call).

Для того чтобы обеспечить эту "закладку", а заодно и вернуться "туда, куда положено", необходимо выполнить команду goto NEW (перейти на исполнение команды call Bin2_10). Разбираемся с ПП START.

С точки зрения обеспечения надежности работы устройства, полный цикл программы лучше начинать с исполнения ПП START, а не с команды, которая не входит в ее состав.

Впротивном случае, ПП START будет исполнена всего один раз (после включения питания устройства, на 1-м "витке" полного цикла программы), и в ходе дальнейшей работы программы (от 2-го "витка" и далее), ПП START будет обходиться.

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

Если предприняты меры по "борьбе с зависаниями" (например, работает сторожевой таймер), то в принципе, это не страшно, но если этих мер не предпринято или существуют сомнения, или речь идет об обеспечении максимальной надежности работы устройства, то перестраховаться не помешает.

При наличии такой перестраховки, последствия некоторых сбоев будут ликвидированы за счет приведения "поврежденного" содержимого регистров к норме.

Насколько я понимаю, в ответах на этот "скользкий вопрос", единого мнения нет. Можно, начиная со 2-го "витка" полного цикла программы, обойти ПП START. Можно не обходить.

247

Можно включить в полный цикл программы (от 2-го "витка" и далее) наиболее "ответственные", подготовительные операции ПП START (это что-то типа компромиссного варианта).

Реализацию именно такого подхода Вы и видите в тексте программы Bin2_10.asm. "Ответственные" (эта оценка субъективна) команды подготовительных операций ПП START располагаются ниже команды call Bin2_10, а команды подготовительных операций, "рангом пониже", располагаются выше ее.

Это означает то, что команды подготовительных операций, располагающиеся выше команды call Bin2_10, будут исполнены на 1-м "витке" полного цикла программы, и в дальнейшем (от 2-го "витка" и далее), они исполняться не будут.

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

В "перестраховочном" случае, нужно заменить команду goto NEW на команду goto START. Если есть такое желание, то ничто не мешает осуществить такую замену.

А теперь давайте разберемся в сути преобразований двоичных чисел в двоично-десятичные. Предположим, что группа ПП формирования 4-байтного, двоичного числа "выдала на гора" 4-байтное, двоичное число.

По определению, такое число должно быть "заложено" в 4 регистра общего назначения. Пусть они будут называться Timer...

Так как регистров 4 штуки, то нужно определиться с порядком их старшинства:

TimerHH, TimerH, TimerM, TimerL.

Ранее об этом говорилось.

Если нужно что-то подсчитать, то речь идет о многоразрядном, двоичном счетчике, которому можно поставить в соответствие, например, двоичный счетчик на 8-ми микросхемах 555ИЕ5 (каждая 555ИЕ5 работает с полубайтом, а не с байтом, и поэтому таких м/схем нужно 8 штук). Эта аналогия относится к форме представления результатов счета.

По этому показателю, аналогия полная.

То есть, в обоих случаях, 32-битное, двоичное число будет отображаться в стандартном весовом коде.

Что же касается принципов счета, то существуют весьма существенные различия, связанные с тем, что в 555ИЕ5, счет реализуется только аппаратными средствами.

Пошли дальше.

Линейка 7-сегментных индикаторов, состоящая из 8-ми знакомест, может отобразить десятичное число не более 99 999 999.

Двоичный эквивалент этого числа в стандартном весовом коде:

00000101 11110101 11100000 11111111

См. конвертор систем исчисления, который у Вас имеется (можете проверить). Вопрос: "Что такое двоично-десятичное число"?.

Ответ: двоично-десятичное число это одно из чисел числового диапазона 0 … 9 ,

представленное в двоичной форме.

Двоично-десятичное число, по определению, не может быть больше 9-ти.

Из этого следует то, что оно отображается только в младшем полубайте байта, а старший полубайт байта всегда будет равен нулю (0000хххх).

Например, десятичное число 99 999 999, в двоичном виде, может быть отражено в 4-байтном регистре, но в двоично-десятичном виде, такое число не может быть отражено в четырех регистрах.

В последнем случае, для отображения этого числа потребуется 8 регистров. Число 99 999 999, в двоично-десятичном виде, выглядит так:

00001001 00001001 00001001 00001001 00001001 00001001 00001001 00001001

Вы видите, что во всех младших полубайтах всех 8-ми регистров, "лежат" девятки, а во всех старших полубайтах, нули.

Вот зачем и нужны 8 регистров LED0...7, "прописку" которых Вы видите в "шапке" программы. Первые четыре из них (LED0...3), в ПП преобразований чисел, задействуются для хранения промежуточных и конечных результатов преобразований.

Регистры LED4...7 для этого не задействуются.

На конечной стадии работы ПП преобразований чисел, из младших и старших полубайтов

248

регистров LED0...3, в младшие полубайты регистров LED0...7 (это не ошибка, никакой ошибки нет), переписываются конечные результаты преобразований чисел.

Это и есть то, что в дальнейшем, подлежит кодировке.

При этом, в старших полубайтах LED0...7 "выставляются" нули. Это как раз то, что Вы видите в примере (для случая 99999999).

Вконечном итоге, в младших полубайтах регистров LED0...7, на все время полного цикла ПП динамической индикации, фиксируются двоично-десятичные числа, с которыми эта ПП и будет работать.

Вобщем виде, работу ПП преобразований чисел можно описать так:

После "влёта" рабочей точки программы в ПП преобразований, в предварительно назначенный счетчик "проходов" Count, записывается константа, значение которой равно суммарному количеству битов 4-байтного регистра TimerHH/TimerH/TimerM/TimerL (в нем находится 4-байтное, двоичное число, которое нужно преобразовать в двоично-десятичное). То есть, в данном случае, числовое значение этой константы, должно быть равно .32.

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

Таким образом, войдя в ПП преобразований чисел, рабочая точка программы "наматывает" 32 "витка" внутреннего цикла ПП преобразований чисел, которые, в сумме, составляют полный цикл ПП преобразований чисел.

После этого, она выходит из ПП преобразований чисел по сценарию "программа исполняется далее".

При этом, содержимое счетчика "проходов" Count равно нулю.

Что происходит, в процессе "прохождения" рабочей точкой программы, каждого из 32-х "витков" внутреннего цикла ПП преобразований чисел?

Сначала производится групповой, циклический сдвиг содержимого 8-байтного регистра

TimerL/TimerM/TimerH/TimerHH/LED0/LED1/LED2/LED3 влево (через бит С регистра STATUS).

Перед этим, (в начале исполнения полного цикла ПП преобразований чисел), в регистры LED0...7 записываются нули.

То есть, их "старое" содержимое удаляется, после чего они готовы к работе.

В результате каждого такого группового сдвига (последовательный сдвиг содержимого 8-ми регистров. 8 команд RLF), происходит перенос содержимого старшего бита регистра TimerHH в младший бит регистра LED0.

Таким образом, через 32 таких сдвига, содержимое TimerL/TimerM/TimerH/TimerHH

переместится в LED0/LED1/LED2/LED3.

Если это трудно себе представить, то вспомните про "бегущую строку" или "бегущие огни". Если просто переместить содержимое TimerL/TimerM/TimerH/TimerHH в LED0/LED1/LED2/LED3, то это ничего полезного не даст, так как конечным результатом такого перемещения будет исходное, двоичное число.

Следовательно, после очередного группового сдвига, необходимо преобразовать содержимое 4-байтного регистра LED0/LED1/LED2/LED3 таким образом, чтобы на момент завершения всех 32-х групповых сдвигов (счетчик проходов Count очищен), во всех 8-ми полубайтах 4-байтного регистра LED0/LED1/LED2/LED3, с соблюдением порядка старшинства, "осели" двоично-десятичные числа (любое из них можно отобразить в полубайте), точно отражающие значение исходного, двоичного числа.

То есть, речь идет о процедуре типа "чтение – модификация – запись.

Так как запись результатов числовых преобразований производится в те же регистры, из которых производилось чтение (LED0...3), то при модификации, должен задействоваться регистр оперативной памяти (в нашем случае - Mem), в котором будут храниться как промежуточные, так и конечные результаты преобразований чисел.

По окончании текущего цикла модификации, модифицированное число, "осевшее" в регистре Mem, копируется в текущий LED.

Предположим, что это происходит.

После того как будет "отмотано" 32 "витка" внутреннего цикла ПП преобразований чисел, во всех 8-ми полубайтах 4-байтного регистра LED0/LED1/LED2/LED3 будут "лежать" 8 двоично-десятичных чисел.

249

Остается только "раскидать" их (также с соблюдением порядка старшинства) по младшим полубайтам регистров LED0, LED1, LED2, LED3, LED4, LED5, LED6, LED7, а в их старшие полубайты, "принудительно" записать нули (см. пример двоично-десятичного представления числа 99999999).

Всё. Конец преобразования.

После этого, содержимое регистров LED0...7 можно обрабатывать в ПП динамической индикации.

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

В"шапке" программы, "прописываются" 2 регистра общего назначения: счетчик числа проходов и регистр оперативной памяти (в нашем случае, Count и Mem).

Вначале ПП преобразований чисел, в счетчик проходов, нужно записать число битов двоичного числа.

Например, если нужно отобразить символы десятичных чисел не в 8-ми, а в 4-х знакоместах (максимальное значение 9999), то речь идет о 2-байтном регистре

(например, TimerM/TimerL).

Таким образом, в счетчик числа проходов, необходимо записать константу 8х2=.16.

Вэтом случае, лишние LEDы (LED4...7) и группы команд, которые работают с их содержимым, нужно убрать.

Должны остаться только регистры LED0, LED1, LED2, LED3 и те группы команд, которые "работают" с их содержимым.

Соответственно, в ПП преобразований, вплоть до ее концовки (до процедуры распределения полубайтов), нужно использовать только регистры LED0 и LED1.

То есть, в этом случае, из текста программы Bin2_10.asm, нужно "изъять" некоторые команды.

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

Флаг переноса-заёма С опускается (бит С регистра STATUS сбрасывается в 0), в счетчик проходов Count записывается константа, числовое значение которой равно общему количеству битов 4-байтного регистра TimerL/TimerM/TimerH/TimerHH (.32), и содержимое всех LEDов сбрасывается в 0.

Подготовительные операции закончены. Далее, начинается отработка ПП Loop16.

Вее начале, происходит циклический сдвиг влево, на одну позицию (через бит С регистра STATUS), содержимого 8-разрядного регистра

TimerL/TimerM/TimerH/TimerHH/LED0/LED1/LED2/LED3 (8 команд rlf),

а потом, содержимое счетчика количества проходов (Count) декрементируется (decfsz Count,F, результат декремента сохраняется в нем же).

Так как байт-ориентированная команда decfsz является командой ветвления, то возможны два сценария работы программы.

Предположим, что результат декремента равен 0 ("отмотаны" все 32 "витка").

Вэтом случае, начнется отработка группы команд поразрядного распределения содержимого регистров LED0...3 (обеих полубайтов), по младшим полубайтам регистров LED0...7 (концовка).

Этой группе команд вполне можно было бы "присвоить статус" отдельной подпрограммы, но так как на 1-ю команду этой группы команд, переходов нет, то формально, она входит в состав ПП Loop16.

Если результат декремента содержимого регистра Count не равен 0, то осуществляется безусловный переход в ПП adjDEC.

Всостав ПП adjDEC входят 4 группы команд, в каждой из которых осуществляется условный переход в ПП adjBCD.

Возврат происходит на следующую (из этих четырех) группу команд.

Каждая из этих групп команд работает со "своим" регистром LED (с нулевого по третий), то есть, соблюдается порядок старшинства (в начале ПП adjDEC, происходит "работа" с содержимым регистра LED0, а в конце, с содержимым регистра LED3).

Предположим, что с содержимым регистра LED3 осуществлены необходимые действия и произошел возврат на команду goto Loop16.

250

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]