Вы находитесь на странице: 1из 19

7/3.

Пример использования модуля 10-разрядного АЦП: цифровой измеритель


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

Наконец-то начинаются "железячные дела". Это как-то ближе к жизни.


Но и от теории никуда не спрячешься, иначе "железяка отомстит" так, что мало не
покажется.
Она как собака, уважает своих (больше всего - хозяина), а на чужих лает (самый
удачный вариант) & кусает (этот вариант похуже).
А тут целый "ротвеллер": "тяпнет" так, что …
Поэтому, хочешь – не хочешь, а за колбасой в магазин сходить придется.
И не один раз. Иначе взаимности не видать.
Колбаса скормлена. Глаза потеплели и хвост завилял.
Это уже совсем другое дело.
Вашему вниманию предлагается устройство измерения уровней напряжения на
PIC16F873A, с выводом результата измерения в линейку из четырех 7-сегментных
индикаторов (динамическая индикация, общий катод):

4-й (самый старший) десятичный разряд оранизовн для обеспечения возможности


отслеживания "квантовок" от 1000 до 1023 (устройство учебное).
Вывод RA0 назначен входом активного канала АЦП (1-й канал).
К нему подключен выход делителя напряжения, Кдел. которого можно изменять
резистором R1 (верхнее плечо делителя).
На рис. 1, вход делителя подключен к плюсу источника питания ПИКа (см. красную
стрелку), но на этот вход можно подать напряжение и от внешнего источника
напряжения.
В этом случае, если Кдел. делителя напряжения соответствующим образом
откалиброван и стабилен (R1 заменен на постоянный резистор, номинал которого
предварительно расчитан, а затем "подогнанан" под замер "эталонного" напряжения),
имеет место быть вполне приличный, цифровой вольтметр, точность и диапазон
измерения которого можно задать (что-то типа модуля индикатора значения
напряжения).

1
Можно было бы использовать и ЖКИ модуль, но я ориентировался на тех людей,
которые этой "железяки" не имеют.
Прежде чем составлять программу, нужно произвести расчет.
А он, собственно говоря, уже был произведен ранее, в предыдущем подразделе.
"Привяжусь" к его итогам.
С учетом этого, Вам должен быть понятен "сермяжный смысл" номиналов резисторов
R1 и R2.
Длительность задержки, которую нужно обеспечить после выбора активного,
аналогового канала, - 20 мкс.
Так как нужен всего один канал АЦП, выбираю настройку 14-й строки (см. таблицу
подраздела 7/1), то есть, PCFG,3…0 = 1110.
Соответственно, диапазон квантования - от 0 до напряжения источника питания.
Напряжение моего блока питания регулируется, и я выставил Uпит = 5,12 вольт.
Это для того, чтобы шаг квантования был более "съедобен и удобен"
(5,12 / 1024 = 0,005 в).
При использовании делителя напряжения с Кдел. = 20, расчетная погрешность
измерения будет составлять 0,1 вольт.
Следовательно, десятичную запятую нужно выставить между последним (справа) и
предпоследним знакоместами, то есть, во втором справа 7-сегментном индикаторе
(сектор запятой находится справа от секторов символа).
Использую правое выравнивание (ADFM,7 = 1).
А теперь "вперед и с песней":

;********************************************************************************
; Analog_1.asm 4-разрядный измеритель уровней аналогового сигнала
; (учебная программа).
;--------------------------------------------------------------------------------
; Задействуется модуль АЦП.
; Для индикации показаний применена линейка из четырех 7-сегментных
; индикаторов (общий катод).
; Индикация - динамическая.
; 4-й разряд индикатора (самый старший, левый) введен для обеспечения возможности
; отслеживания состояний от 1000 до 1023.
; Запятая выставлена между 3-м и 4-м (если считать от старшего десятичного
; разряда) десятичными разрядами.
;********************************************************************************
; "Практикум по конструированию устройств на PIC контроллерах"
; (http://ikarab.narod.ru)
; Корабельников Евгений Александрович karabea@Lipetsk.ru
;********************************************************************************
; Функции выводов порта А:
; RA0 - активный входной канал АЦП,
; остальные выводы порта А не задействованы.
; Функции выводов порта В:
; RB0...RB7 - управление секторами A,B,C,D,E,F,H,G.
; Функции выводов порта С:
; RC0...RC3 - выходы дешифратора,
; остальные выводы порта C не задействованы.
; Кварц 4000 Кгц (1 м.ц.= 1 мкс.).
; Используется PIC16F873A.
;----------------------------------------------
; Объем программы: 121 слово в памяти программ.
;================================================================================
LIST p=16F873A ; Задание типа микроконтроллера.
__CONFIG 3F31H ; XT-генератор, PWRT вкл., защита выкл., сброс
; BOR запрещен, LVP выкл., DEBUG выкл.
;================================================================================
; Регистры специального назначения.
;================================================================================
IndF equ 00h ; Доступ к памяти через FSR.
PCL equ 02h ; Счетчик команд.
Status equ 03h ; Регистр Status.
FSR equ 04h ; Регистр косвенной адресации.
2
PortB equ 06h ; Регистр защелок порта B.
PortC equ 07h ; ----------"---------- C.
TrisB equ 06h ; Регистр выбора направлений работы
; выводов порта B (банк 1).
TrisC equ 07h ; ----------"---------- C (банк 1).
AdresH equ 1Eh ; Регистр старшего байта результата АЦП.
AdresL equ 1Eh ; Регистр младшего байта результата АЦП
; (банк 1).
Adcon0 equ 1Fh ; Регистр настройки модуля АЦП.
Adcon1 equ 1Fh ; Регистр настройки модуля АЦП (банк 1).
;================================================================================
; Регистры общего назачения.
;================================================================================
LED0 equ 20h ; Регистр хранения результатов преобразований
; 1-го двоично-десятичного разряда.
LED1 equ 21h ; ------- 2-го -------------------------
LED2 equ 22h ; ------- 3-го -------------------------
LED3 equ 23h ; ------- 4-го -------------------------
Index equ 24h ; Счетчик количества малых колец индикации.
Count equ 25h ; Счетчик количества больших колец индикации.
Temp equ 26h ; Регистр временного хранения данных.
Mem equ 27h ; Регистр оперативной памяти.
Temp_L equ 28h ; Регистр младшего разряда 2-байтного
; двоичного числа.
Temp_H equ 29h ; Регистр старшего разряда 2-байтного
; двоичного числа.
;================================================================================
; Определение места размещения результатов операций.
;================================================================================
W equ 0 ; Результат направить в аккумулятор.
F equ 1 ; Результат направить в регистр.
;================================================================================
; Присвоение битам названий.
;================================================================================
C equ 0 ; Флаг переноса-заема.
Z equ 2 ; Флаг нулевого результата.
RP0 equ 5 ; Бит выбора банка.
GO equ 2 ; Бит статуса модуля АЦП.
;================================================================================
org 0 ; Начать выполнение программы
; с 0-го адреса PC.
;********************************************************************************

;********************************************************************************
; НАЧАЛО ПРОГРАММЫ.
;********************************************************************************
; Подготовительные операции.
;================================================================================
; Настройка направлений работы.
;-------------------------------------------
bsf Status,RP0 ; Переход в 1-й банк.
clrf TrisB ; Все выводы порта В работают на выход.
clrf TrisC ; Все выводы порта С работают на выход.
;-------------------------------------------
; Работа с регистром Adcon1.
;-------------------------------------------
movlw b'10001110' ; Диапазон квантования напряжения от -Vss
movwf Adcon1 ; до + Vdd, AN0-аналоговый вход,
; AN1...AN4 - цифровые каналы ввода/вывода,
; правое выравнивание.
bcf Status,RP0 ; Переход в 0-й банк.
;================================================================================
; Циклическая подпрограмма измерения уровня аналогового сигнала, присутствующего
; на выводе RA0, обработки результата измерения и его вывода на индикацию.
3
;================================================================================
; Работа с регистром Adcon0.
;-------------------------------------------
SNOVA movlw b'01000001' ; Включение модуля АЦП, выбор канала AN0
movwf Adcon0 ; (RA0), источник тактового сигнала Fosc/8,
; состояние ожидания, конденсатор подключен к
; выбранному аналоговому входу и начал
; перезаряжаться.
;-------------------------------------------
; Задержка для перезаряда конденсатора.
;-------------------------------------------
movlw .6 ; Стандартный,
movwf Count ; вычитающий,
decfsz Count,F ; однобайтный
goto $-1 ; счетчик.
;-------------------------------------------
; Начало аналого-цифрового преобразования.
;-------------------------------------------
bsf Adcon0,GO ; Включение преобразования. Конденсатор
; отключается от аналогового входа на время
; преобразования.
;-----------------------------------------------
; Ожидание окончания АЦП ("плавающая" задержка).
;-----------------------------------------------
btfsc Adcon0,GO ; Ожидание окончания аналого-цифрового
goto $-1 ; преобразования.
;-------------------------------------------
; АЦП закончено. Результат - в AdresH/AdresL.
; Копирование результата в Temp_H/Temp_L.
;-------------------------------------------
bsf Status,RP0 ; Переход в 1-й банк.
movf AdresL,W ; AdresL --> W.
bcf Status,RP0 ; Переход в 0-й банк.
movwf Temp_L ; W --> Temp_L.

movf AdresH,W ; AdresH --> W.


movwf Temp_H ; W --> Temp_H.
;-------------------------------------------
; В Temp_H/Temp_L "лежит" результат АЦП.
;-------------------------------------------
; Теперь модуль АЦП можно выключить.
;-------------------------------------------
clrf Adcon0 ; Для снижения потребляемого устройством тока,
; модуль АЦП выключается до конца отработки
; текущего полного цикла программы.
;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; ГРУППА ПОДПРОГРАММ ПРЕОБРАЗОВАНИЯ 2-БАЙТНЫХ ДВОИЧНЫХ ЧИСЕЛ
; В 4-РАЗРЯДНЫЕ ДЕСЯТИЧНЫЕ ЧИСЛА.
;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; Подготовка к преобразованию.
;================================================================================
Bin2_10 bcf Status,C ; Сброс флага переноса-заема.
movlw .16 ; "Закладка" в регистр Count1 числа
movwf Count ; проходов преобразования.

clrf LED0 ; Сброс регистра LED0.


clrf LED1 ; -------"------ LED1.
;================================================================================
; Циклический сдвиг влево.
;================================================================================
Loop16 rlf Temp_L,F ; Побитная
rlf Temp_H,F ; "переправка"
rlf LED0,F ; содержимого
rlf LED1,F ; Temp_H/Temp_L
; в LED1/LED0.
decfsz Count,F ; Анализ числа проходов
4
goto adjDEC ; преобразования.
;================================================================================
; Поразрядное распределение полубайтов регистров LED1 и LED0
; по младшим полубайтам регистров LED3, LED2, LED1, LED0.
;================================================================================
swapf LED1,W ; Запись старшего полубайта LED1
andlw 0Fh ; в младший полубайт LED3.
movwf LED3 ; --------------------------------

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


andlw 0Fh ; в младший полубайт LED2.
movwf LED2 ; --------------------------------

swapf LED0,W ; Запись старшего полубайта LED0


andlw 0Fh ; в младший полубайт LED1.
movwf LED1 ; --------------------------------

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


andlw 0Fh ; в младший полубайт LED0.
movwf LED0 ; --------------------------------

goto DINAM ; Переход в ПП динамической индикации.

;================================================================================
; Запись в регистр FSR адресов регистров LED0...1 для дальнейшей косвенной
; адресации к ним в ПП adjBCD.
; Переход к обработке следующего LED - после возврата по стеку.
;================================================================================
adjDEC movlw LED0 ; Запись в регистр FSR, через регистр W,
movwf FSR ; адреса регистра LED0 с дальнейшим переходом
call adjBCD ; в ПП adjBCD (адрес следующей команды
; закладывается в стек).
;---> Возврат по стеку из ПП adjBCD.
movlw LED1 ; -----------------------------
movwf FSR ; То же самое для регистра LED1.
call adjBCD ; -----------------------------
;---> Возврат по стеку из ПП adjBCD.

goto Loop16 ; Переход в ПП Loop16, то есть, на


; следующее кольцо числовых преобразований.
;--------------------------------------------------------------------------------
; Основные операции преобразования двоичных чисел в двоично-десятичные.
;--------------------------------------------------------------------------------
adjBCD movlw 3 ; Суммирование содержимого текущего LED с
addwf 0,W ; числом 03h, с записью результата операции,
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 addwf PCL,F ; Содержимое счетчика команд PC увеличивается
5
; на величину содержимого W.
retlw b'00111111' ; ..FEDCBA = 0
retlw b'00000110' ; .....CB. = 1
retlw b'01011011' ; .G.ED.BA = 2
retlw b'01001111' ; .G..DCBA = 3
retlw b'01100110' ; .GF..CB. = 4
retlw b'01101101' ; .GF.DC.A = 5
retlw b'01111101' ; .GFEDC.A = 6
retlw b'00000111' ; .....CBA = 7
retlw b'01111111' ; .GFEDCBA = 8
retlw b'01101111' ; .GF.DCBA = 9
;================================================================================

;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; ПОДПРОГРАММА ДИНАМИЧЕСКОЙ ИНДИКАЦИИ
;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; Подготовка счетчика количества малых колец индикации
; Index к началу полного цикла динамической индикации.
;------------------------------------------------------
DINAM clrf Index ; Сброс в 0 содержимого счетчика малых колец
; индикации Index.
;--------------------------------------------------------------------------------
; Запись в регистр Count количества больших колец индикации, которые
; должны быть отработаны за один полный цикл динамической индикации.
;--------------------------------------------------------------------------------
movlw .60 ; .60 --> W.
movwf Count ; W --> Count.

CYCLE movlw b'11111111' ; Предустановка состояний выходов дешифратора


movwf PortC ; RC3...RC0
; (RC7..4 устанавливаются в 1 "за компанию").
;--------------------------------------------------------------------------------
; Подготовка к косвенной адресации: запись в регистр W адреса регистра младшего
; разряда (LED0)
;("привязка" к 7-сегментному индикатору, с активации которого начинается полный
; цикл 1-го большого кольца индикации).
;--------------------------------------------------------------------------------
movlw LED0 ; Запись в регистр W адреса регистра LED0.
addwf Index,W ; Увеличение адреса регистра LED0 на величину
; числа, записанного в регистре счетчика
; количества малых колец индикации Index,
; c сохранением результата в регистре W.
;--------------------------------------------------------------------------------
; Косвенная адресация.
;--------------------------------------------------------------------------------
movwf FSR ; Копирование содержимого регистра W
; в регистр FSR.
movf IndF,W ; Копирование содержимого регистра с адресом,
; записанным в регистре FSR, в регистр W.
call TABLE ; Условный переход в ПП TABLE.
;---> Возврат по стеку из ПП TABLE.
;--------------------------------------------------------------------------------
; Группа команд установки запятой.
;--------------------------------------------------------------------------------
movwf Temp ; Копирование содержимого регистра W
; (7-сегментные коды индицируемых двоично-
; десятичных чисел) в регистр Temp.
movlw 1 ; Задание места "дислокации" запятой
; (во 2-м знакоместе справа).
bsf Status,Z ; Поднятие флага нулевого результата Z.
subwf Index,W ; Вычитание содержимого регистра W из
; содержимого регистра Index.
btfss Status,Z ; Проверка состояния флага Z.
goto NO_DOT ; Если флаг Z опущен (результат операции
; не=0), то переход на метку NO_DOT
; (запятая не выставляется).
6
bsf Temp,7 ; Если флаг Z поднят (результат операции=0),
; то установка в единицу 7-го бита (установка
; запятой) регистра Temp.
;--------------------------------------------------------------------------------
; Группа команд вывода десятичной цифры на индикацию.
;--------------------------------------------------------------------------------
NO_DOT movf Temp,W ; Копирование содержимого регистра Temp
; (7-сегментные коды индицируемых двоично-
; десятичных чисел, плюс запятая) в регистр W
movwf PortB ; Вывод содержимого регистра W в порт В.
;================================================================================
; ДЕШИФРАТОР: программная реализация аналога 555ИД7 (для количества выходов = 4).
;================================================================================
movf Index,W ; Index --> W.
;-------------------------------------
; 4-сценарный вычисляемый переход.
;-------------------------------------
addwf PCL,F ; Содержимое счетчика команд PC увеличивается
; на величину содержимого W.
goto D_0 ; Сценарий №1.
goto D_1 ; Сценарий №2.
goto D_2 ; Сценарий №3.
bcf PortC,3 ; Сценарий №4. На выводе RC3 выставляется 0.
goto $+6 ; Завершение дешифровки.
D_0 bcf PortC,0 ; На выводе RC0 выставляется 0.
goto $+4 ; Завершение дешифровки.
D_1 bcf PortC,1 ; На выводе RC1 выставляется 0.
goto $+2 ; Завершение дешифровки.
D_2 bcf PortC,2 ; На выводе RC2 выставляется 0.
;--------------------------------------------------------------------------------
; Группа команд задержки, определяющей время нахождения одного 7-сегментного
; индикатора в активном состоянии (определяющей время прохождения малого кольца
; индикации).
;--------------------------------------------------------------------------------
movlw .67 ; Запись в регистр Temp
movwf Temp ; времязадающей константы.

decfsz Temp,F ; 1-байтный, вычитающий


goto $-1 ; счетчик (задержка).
;--------------------------------------------------------------------------------
; Увеличение на 1 содержимого счетчика количества малых колец индикации Index
; с последующей проверкой результата инкремента на равенство (или нет) числу .4.
;--------------------------------------------------------------------------------
incf Index,F ; Увеличение на 1 содержимого регистра Index
; с сохранением результата в нем же.
movlw 4 ; Запись в регистр W константы .4.
bcf Status,Z ; Сброс флага нулевого результата Z.
subwf Index,W ; Index - W = ... (результат --> W).
btfss Status,Z ; Результат операции вычитания
; равен или нет нулю?
goto CYCLE ; Если не =0 (в регистре Index - число не
; равное 4), то переход на новое малое кольцо
; индикации.
; Если =0 (в регистре Index - число равное
; 4), то программа исполняется далее.
;--------------------------------------------------------------------------------
; После того, как последовательно активизируются все 4 7-сегментных индикатора
; линейки, - подготовка к переходу на новое большое кольцо индикации.
;--------------------------------------------------------------------------------
clrf Index ; Сброс в 0 содержимого регистра Index.
;--------------------------------------------------------------------------------
; Уменьшение на 1 содержимого счетчика количества больших колец индикации Count.
;--------------------------------------------------------------------------------
decfsz Count,F ; Декремент содержимого счетчика количества
; больших колец индикации Count с сохранением
; результата в нем же.
7
goto CYCLE ; Если результат декремента не=0, то переход
; на новое большое кольцо индикации.
; Если результат декремента =0, то программа
; исполняется далее (переход на новый полный
; цикл динамической индикации).
;================================================================================
; "Точное" формирование времени полного цикла динамической индикации (если
; тебуется точно калиброванное время полного цикла динамической индикации для
; использования его в качестве измерительного интервала).
;================================================================================

; В ДАННОМ СЛУЧАЕ, ЭТОГО НЕ ТРЕБУЕТСЯ.

;--------------------------------------------------------------------------------
; Выход из ПП динамической индикации.
;--------------------------------------------------------------------------------
clrf PortB ; "Гашение" всех сегментов.
goto SNOVA ; Переход на следующий цикл программы.
;********************************************************************************
end ; Конец программы.

ASM-файл этой программы прилагается.


Красным цветом выделено то, что относится к АЦП.
Темно – синим цветом выделено то, что относится к 2/10 преобразованию.
Темно – красным цветом выделено то, что относится к динамической индикации
(фиолетовым цветом выделена группа команд дешифратора).

Работа программы.
По умолчанию, устанавливается нулевой банк.
Прерывания не использую. Значит их нужно запретить.
А они уже запрещены по умолчанию.
RA0 нужно настроить на работу "на вход".
А он, по умолчанию, работает "на вход".
Несколько команд "сэкономлено". Мелочь, а приятно.
Остается только перейти в 1-й банк и настроить на работу "на выход" выводы портов
В и С, что и имеет место быть.
Теперь можно работать с модулем АЦП.

Сначала нужно определиться с функциями выводов AN0 … AN4, а заодно и с


диапазоном квантования, и с типом выравнивания результата АЦП (регистр Adcon1):
;-------------------------------------------
; Работа с регистром Adcon1.
;-------------------------------------------
movlw b'10001110' ; Диапазон квантования напряжения от -Vss
movwf Adcon1 ; до + Vdd, AN0-аналоговый вход,
; AN1...AN4 - цифровые каналы ввода/вывода,
; правое выравнивание.
bcf Status,RP0 ; Переход в 0-й банк.

Теперь нужно поработать с содержимым управляющего регистра Adcon0: выбрать


источник тактового сигнала, сделать активным канал AN0 (вход - вывод RA0) и
включить модуль АЦП.
;-------------------------------------------
; Работа с регистром Adcon0.
;-------------------------------------------
SNOVA movlw b'01000001' ; Включение модуля АЦП, выбор канала AN0
movwf Adcon0 ; (RA0), источник тактового сигнала Fosc/8,
; состояние ожидания, конденсатор подключен к
; выбранному аналоговому входу и начал
; перезаряжаться.

8
При этом, конденсатор Hold подключается к выводу RA0.
Не смотря на то, что модуль АЦП включен, цифровое преобразование не начнется,
так как модуль АЦП находится в состоянии ожидания преобразования.
Почему?
Потому, что "таможенник шлагбаум не открывает" (вспомните про яблоки), то есть,
флаг статуса модуля АЦП (GO) опущен (GO = 0).
Это нужно сделать программно.
Почему это "опущение" нужно?
Потому, что рановато начинать АЦП, ведь для перезаряда конденсатора Hold, нужно
время, и "по программным меркам", достаточно приличное (в данном случае, 20 мкс.).

А раз это так, то:


;-------------------------------------------
; Задержка для перезаряда конденсатора.
;-------------------------------------------
movlw .6 ; Стандартный,
movwf Count ; вычитающий,
decfsz Count,F ; однобайтный
goto $-1 ; счетчик.

Это задержка на 19 мкс., плюс, 1 мкс. исполнения следующей команды (поднятие флага
статуса), получается 20 мкс. (расчетная, "рабочая" задержка Tacq).

А вот теперь, после того как конденсатор Hold гарантированно перезарядился до


уровня отслеживаемого, аналогового сигнала, можно "запускать" преобразование:
;-------------------------------------------
; Начало аналого-цифрового преобразования.
;-------------------------------------------
bsf Adcon0,GO ; Включение преобразования. Конденсатор
; отключается от аналогового входа на время
; преобразования.

А теперь остается только ждать окончания преобразования, часто проверяя (цикл


анализа - 3 м.ц.) состояние флага статуса (GO). Короче, "курим".
"Плавающая" задержка "свое дело знает" (такие "специалисты" везде "на вес золота").
;-----------------------------------------------
; Ожидание окончания АЦП ("плавающая" задержка).
;-----------------------------------------------
btfsc Adcon0,GO ; Ожидание окончания аналого-цифрового
goto $-1 ; преобразования.

"Покурили" и хватит.
После выхода рабочей точки программы из "плавающей" задержки:
- Флаг прерывания ADIF поднялся, но он, в данном случае, не нужен. Игнорируем.
- Флаг статуса опустился (преобразование закончено). Приняли к сведению.
- Результат преобразования "осел" в AdresH/AdresL.
Теперь нужно быстренько скопировать результат преобразования из регистра
AdresH/AdresL в регистр Temp_H/Temp_L.
При этом нужно учесть, что регистр AdresL "лежит" в 1-м банке.
Получилось вот что:
;-------------------------------------------
; АЦП закончено. Результат - в AdresH/AdresL.
; Копирование результата в Temp_H/Temp_L.
;-------------------------------------------
bsf Status,RP0 ; Переход в 1-й банк.
movf AdresL,W ; AdresL --> W.
bcf Status,RP0 ; Переход в 0-й банк.
movwf Temp_L ; W --> Temp_L.

movf AdresH,W ; AdresH --> W.


9
movwf Temp_H ; W --> Temp_H.

"Правовыравненный" результат АЦП "лежит" в Temp_H/Temp_L, и теперь его можно


как-то обработать.
Примечание: на форуме обсуждался такой вариант (с использованием косвенной
адресации):
movlw 9Eh ; 9Eh (адрес регистра AdresL) --> W.
movwf FSR ; W --> FSR.
movfw IndF ; IndF (содержимое AdresL) --> W.
movwf Temp_L ; W --> Temp_L.

movfw AdresH ; AdresH --> W.


movwf Temp_H ; W --> Temp_H.

Можно и так, и эдак (количество команд одинаковое).

Далее должны быть отработаны достаточно "массивные" подпрограммы 2/10


преобразования и динамической индикации.
Зачем оставлять модуль АЦП включенным?
Выключаю. Когда потребуется, включу.

;-------------------------------------------
; Теперь модуль АЦП можно выключить.
;-------------------------------------------
clrf Adcon0 ; Для снижения потребляемого устройством тока,
; модуль АЦП выключается до конца отработки
; текущего полного цикла программы.

Теперь нужно определиться с циклом программы.


Предположим, что подпрограммы 2/10 преобразования и динамической индикации
отработаны.
Куда переходить (на что "закольцовывать" полный цикл программы, начиная со 2-го
"витка")?
Я перешел на начало процедуры "настройки" Adcon0 (см. goto SNOVA).
"Разборки" с этим будут позднее.

Подпрограмма 2/10 преобразования.


Она стандартна, только "адаптирована" под преобразование 2-байтного, двоичного
числа в 4-байтное двоично – десятичное число.
Ничего "революционного" в этой ПП нет.
Имеет место быть только "воздействие на ключевые точки", которое было детально
"расписано" ранее (в "Самоучителе …"), и удаление лишнего (имеется ввиду удаление
лишнего из "матери", которая имеет разрядность выше нужной).
Вместо этой ПП, можно использовать ПП Сергея Рослика (подраздел 5/11/1
"Практикума…" программа bin2_4.asm).
Желающие могут это сделать.
После окончания 2/10 преобразования, осуществляется переход в ПП динамической
индикации.

Подпрограмма динамической индикации.


Она "обслуживает" линейку из 4-х 7-сегментных индикаторов.
За основу взята "заготовка" Dinam.asm, из которой я "выкинул" все лишнее.
Дело в том, что эта "заготовка ваялась" с учетом встроенности ПП динамической
индикации в цикл формирования калиброванного интервала времени измерения
частотомера.
В данном случае, такой интервал времени формировать не нужно, и я ее "обкарнал"
("адаптировал" под текущие нужды).
Плюс, дополнил ее группой команд, программно реализующей функцию микросхемы
дешифратора 555ИД7 (по выходам дешифратора "бегает" один-разъединственный ноль,
10
а на остальных выходах единицы), в части касающейся 4-х его выходов (а больше и
не нужно).
В данном случае, это и можно, и нужно сделать, так как "дефицита" выводов портов
нет (нет надобности в использовании внешнего дешифратора).
Я "сваял" и "прогнал через железо" три варианта такого дешифратора. Все рабочие.
Оптимальный, с моей точки зрения, вариант (с использованием вычисляемого
перехода, минимальное количество команд) "прописан" в тексте программы.
Остальные 2 варианта Вы найдете ниже директивы END.
Одно и то же устройство можно по-разному программно реализовать.
Это и хочется наглядно показать.
Принцип дешифрования такой:
В начале каждого цикла динамической индикации, на выводах RC3 … RC0
устанавливаются единицы.
Если этого не сделать, то, через короткое время, все выходы дешифратора будут
"забиты нулями" (а нужен только один "бегающий" ноль).
Сразу же после вывода, в порт В, кода текущего, десятичного числа, в зависимости от
значения числа, "лежащего" в регистре Index, происходит выбор одного из 4-х
возможных сценариев активации того или иного 7-сегментного индикатора (Index = 0
или 1, или 2, или 3), который и исполняется.
Выбор 5-го, 6-го и т.д. сценария не возможен, так как состояние Index=4 будет
"железобетонно" обнаружено, после чего содержимое регистра Index будет сброшено в
ноль.
Перед переходом на новый цикл программы (перед goto SNOVA), я, "для порядка",
погасил все сегменты (clrf PortB), но этого, в данном случае, можно и не делать, так
как интервал времени, между началом полного цикла программы и входом рабочей
точки программы в ПП динамической индикации, мал.
За такой короткий интервал времени, человеческий глаз не сможет отследить наличие
"непогашенной цифры".
Короче, что делать с этой командой, решайте сами.
Если не нужна, то "убейте" ее, и дело с концом.

Вернусь к своим "котлетам", то есть, к АЦП.


Что, в конечном итоге, получилось?
А получилась строго определенная последовательность действий типа "АЦП - 2/10
преобразование - вывод на индикацию", которая повторяется многократно.
Причем, временные соотношения и скорость всего этого "безобразия" такова, что
мерцания вообще не ощущаются глазом.
Кто скажет, что это плохо, пусть бросит в меня камень.
Теперь нужно убедиться, что что-то замеряется.
Вход делителя напряжения подключается к источнику питания ПИКа (см. линию с
красной стрелкой на рис. 1).
При "кручении-верчении" движка резистора R1, показания должны изменяться.
Есть такое. Есть.
Вращая движок резистора R1, нужно сделать так, чтобы показание линейки
7-сегментных индикаторов было "005,1" (0,02 вольта "моль съела", так как погрешность
измерения 0,1 вольт).
А теперь считаем.
Напряжение источника питания = 5,12 вольта.
Значит, в идеале, показанию "005,1" должно соответствовать напряжение на резисторе
R2, величиной 5,12 в / 20 = 0,256 вольта (это есть напряжение, приведенное к
аналоговому входу модуля АЦП).
Замеряю напряжение на резисторе R2.
Получилось "где-то в районе" 0,26 вольта.
С учетом того, что в качестве "эталона" я использовал обычный, дешевый мультимер
DT-830B (какая – никакая, а погрешность измерения имеется), и того, что точно
выставить показания нельзя (0,02 вольта "моль съела"), получается вполне "зер гут".
Проще говоря, можно считать, что сие "сооружение врет в меру", а может быть, в
смысле "вранья", оно будет даже и получше моего DT-830B (чем черт не шутит?).
11
И еще один важный момент: при условии соблюдения требований, заявленных
разработчиками, модуль АЦП имеет высокую линейность преобразования.
На практике это означает то, что откалибровав измеритель уровня, например, в
середине диапазона измерения (самый лучший вариант), и обеспечив стабильные Кдел
делителя напряжения и уровень/уровни опорного напряжения, можно быть уверенным,
что и в других точках этого диапазона замеры будут произведены с приемлемой
точностью.
Итак, "основная тяжесть с души свалилась" (братьям-разработчикам à пролетарский
привет, "рот фронт", "но пасаран" и прочее), и можно от души покрутить движок R1
туда-сюда.
Что видно?
А видны числовые значения "ужасных и таинственных" уровней квантования.
Именно они и "высвечиваются" в линейке.
Этих уровней 1023 штуки.
Поставьте движок R1 в среднее положение.
Изолированной "проволочиной" "закоротите" резистор R2.
Результат - показания "000,0".
Теперь "раскоротите" R2 и подайте на вывод RA0 напряжение питания ПИКа (5,12 в.).
Результат - показания "102,3".
Вывод: при использовании делителя напряжения с Кдел. = 20, с помощью такой
"каракатицы" (это я любя), можно замерять уровни напряжений в диапазоне от 0 до
102,3 вольт с погрешностью 0,1 вольт.
По моему, совсем не плохо.
Если нужна погрешность 0,01 вольт, то нужно применить делитель напряжения с
Кдел. = 2 и сдвинуть десятичную запятую на одно знакоместо влево.
В этом случае, диапазон измерения составит от 00,00 в до 10,23 в.
Теперь о запятой.
Если применяется линейка 7-сегментных индикаторов, предназначенная для
динамической индикации (все запятые запараллелены внутри этого "сооружения" и нет
возможности в это вмешаться) или имеет место быть "плавающая" запятая, то
применение группы команд установки запятой оправдано.
А вот если линейка 7-сегментных индикаторов собирается из "одинарных" 7-сегментных
индикаторов, и запятая не меняет своего положения, то нужный сегмент запятой
можно просто запитать от плюса источника питания (естественно, через гасящий
резистор), а на сегменты остальных запятых не обращать внимания (никуда не
подключать).
При этом, группа команд установки запятой "убивается", и вывод RB7 освобождается.
Пошли дальше.
Надеюсь, что Вы своими глазами убедились в наличии 1023-х уровней квантования, и
теперь можно "убить" десятичное знакоместо самого старшего разряда.
И в самом деле, "не шикарно ли будет", из-за 24-х "верхних" уровней квантования,
задействовать целое знакоместо (больше единицы в нем не "высветится")?
Трех десятичных знакомест вполне хватит, и потери не велики, так как верхняя
граница диапазона измерения понизится незначительно (в данном случае, с 102,3 в до
99,9 в).
Тогда получается такая программа (ASM-файл прилагается):

;********************************************************************************
; Analog_2.asm 3-разрядный измеритель уровней аналогового сигнала
;--------------------------------------------------------------------------------
; Задействуется модуль АЦП.
; Для индикации показаний применена линейка из трех 7-сегментных индикаторов
; (общий катод).
; Индикация - динамическая.
; Запятая выставлена между 2-м и 3-м (если считать от старшего десятичного
; разряда) десятичными разрядами.
;********************************************************************************
; "Практикум по конструированию устройств на PIC контроллерах"
; (http://ikarab.narod.ru)
; Корабельников Евгений Александрович karabea@Lipetsk.ru

12
;********************************************************************************
; Функции выводов порта А:
; RA0 - активный входной канал АЦП,
; остальные выводы порта А не задействованы.
; Функции выводов порта В:
; RB0...RB7 - управление секторами A,B,C,D,E,F,H,G.
; Функции выводов порта С:
; RC0...RC2 - выходы дешифратора,
; остальные выводы порта C не задействованы.
; Кварц 4000 Кгц (1 м.ц.= 1 мкс.).
; Используется PIC16F873A.
;----------------------------------------------
; Объем программы: 115 слов в памяти программ.
;================================================================================
LIST p=16F873A ; Задание типа микроконтроллера.
__CONFIG 3F31H ; XT-генератор, PWRT вкл., защита выкл., сброс
; BOR запрещен, LVP выкл., DEBUG выкл.
;================================================================================
; Регистры специального назначения.
;================================================================================
IndF equ 00h ; Доступ к памяти через FSR.
PCL equ 02h ; Счетчик команд.
Status equ 03h ; Регистр Status.
FSR equ 04h ; Регистр косвенной адресации.
PortB equ 06h ; Регистр защелок порта B.
PortC equ 07h ; ----------"---------- C.
TrisB equ 06h ; Регистр выбора направлений работы
; выводов порта В (банк 1).
TrisC equ 07h ; ----------"---------- C (банк 1).
AdresH equ 1Eh ; Регистр старшего байта результата АЦП.
AdresL equ 1Eh ; Регистр младшего байта результата АЦП
; (банк 1).
Adcon0 equ 1Fh ; Регистр настройки модуля АЦП.
Adcon1 equ 1Fh ; Регистр настройки модуля АЦП (банк 1).
;================================================================================
; Регистры общего назачения.
;================================================================================
LED0 equ 20h ; Регистр хранения результатов преобразований
; 1-го двоично-десятичного разряда.
LED1 equ 21h ; ------- 2-го -------------------------
LED2 equ 22h ; ------- 3-го -------------------------
Index equ 24h ; Счетчик количества малых колец индикации.
Count equ 25h ; Счетчик количества больших колец индикации.
Temp equ 26h ; Регистр временного хранения данных.
Mem equ 27h ; Регистр оперативной памяти.
Temp_L equ 28h ; Регистр младшего разряда 2-байтного
; двоичного числа.
Temp_H equ 29h ; Регистр старшего разряда 2-байтного
; двоичного числа.
;================================================================================
; Определение места размещения результатов операций.
;================================================================================
W equ 0 ; Результат направить в аккумулятор.
F equ 1 ; Результат направить в регистр.
;================================================================================
; Присвоение битам названий.
;================================================================================
C equ 0 ; Флаг переноса-заема.
Z equ 2 ; Флаг нулевого результата.
RP0 equ 5 ; Бит выбора банка.
GO equ 2 ; Бит статуса модуля АЦП.
;================================================================================
org 0 ; Начать выполнение программы
; с 0-го адреса PC.
;********************************************************************************

13
;********************************************************************************
; НАЧАЛО ПРОГРАММЫ.
;********************************************************************************
; Подготовительные операции.
;================================================================================
; Настройка направлений работы.
;-------------------------------------------
bsf Status,RP0 ; Переход в 1-й банк.
clrf TrisB ; Все выводы порта В работают на выход.
clrf TrisC ; Все выводы порта С работают на выход.
;-------------------------------------------
; Работа с регистром Adcon1.
;-------------------------------------------
movlw b'10001110' ; Диапазон квантования напряжения от -Vss до +
movwf Adcon1 ; Vdd, AN0-аналоговый вход, AN1...AN4-цифровые
; каналы ввода/вывода, правое выравнивание.
bcf Status,RP0 ; Переход в 0-й банк.
;================================================================================
; Циклическая подпрограмма измерения уровня аналогового сигнала, присутствующего
; на выводе RA0, обработки результата измерения и его вывода на индикацию.
;================================================================================
; Работа с регистром Adcon0.
;-------------------------------------------
SNOVA movlw b'01000001' ; Включение модуля АЦП, выбор канала AN0
movwf Adcon0 ; (RA0), источник тактового сигнала Fosc/8,
; состояние ожидания, конденсатор подключен к
; выбранному аналоговому входу и начал
; перезаряжаться.
;------------------------------------------------
; Задержка для перезаряда конденсатора.
;------------------------------------------------
movlw .6 ; Стандартный,
movwf Count ; вычитающий,
decfsz Count,F ; однобайтный
goto $-1 ; счетчик.
;-------------------------------------------
; Начало аналого-цифрового преобразования.
;-------------------------------------------
bsf Adcon0,GO ; Включение преобразования. Конденсатор
; отключается от аналогового входа на время
; преобразования.
;-------------------------------------------
; Ожидание окончания АЦП ("плавающая" задержка).
;-------------------------------------------
btfsc Adcon0,GO ; Ожидание окончания аналого-цифрового
goto $-1 ; преобразования.
;-------------------------------------------
; АЦП закончено. Результат - в AdresH/AdresL.
; Копирование результата в Temp_H/Temp_L.
;-------------------------------------------
bsf Status,RP0 ; Переход в 1-й банк.
movf AdresL,W ; AdresL --> W.
bcf Status,RP0 ; Переход в 0-й банк.
movwf Temp_L ; W --> Temp_L.

movf AdresH,W ; AdresH --> W.


movwf Temp_H ; W --> Temp_H.
;-------------------------------------------
; В Temp_H/Temp_L "лежит" результат АЦП.
;-------------------------------------------
; Теперь модуль АЦП можно выключить.
;-------------------------------------------
clrf Adcon0 ; Для снижения потребляемого устройством тока,
; модуль АЦП выключается до конца отработки
14
; текущего полного цикла программы.
;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; ГРУППА ПОДПРОГРАММ ПРЕОБРАЗОВАНИЯ 2-БАЙТНЫХ ДВОИЧНЫХ ЧИСЕЛ В 3-РАЗРЯДНЫЕ
; ДЕСЯТИЧНЫЕ ЧИСЛА (разрядность двоичного числа - 10).
;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; Подготовка к преобразованию.
;================================================================================
Bin2_10 bcf Status,C ; Сброс флага переноса-заема.
movlw .16 ; "Закладка" в регистр Count1 числа
movwf Count ; проходов преобразования.

clrf LED0 ; Сброс регистра LED0.


clrf LED1 ; -------"------ LED1.
;================================================================================
; Циклический сдвиг влево.
;================================================================================
Loop16 rlf Temp_L,F ; Побитная
rlf Temp_H,F ; "переправка"
rlf LED0,F ; содержимого
rlf LED1,F ; Temp_H/Temp_L
; в LED1/LED0.
decfsz Count,F ; Анализ числа проходов
goto adjDEC ; преобразования.
;================================================================================
; Поразрядное распределение полубайтов регистров LED1 и LED0
; по младшим полубайтам регистров LED2, LED1, LED0.
;================================================================================
movfw LED1 ; Запись младшего полубайта LED1
andlw 0Fh ; в младший полубайт LED2.
movwf LED2 ; --------------------------------

swapf LED0,W ; Запись старшего полубайта LED0


andlw 0Fh ; в младший полубайт LED1.
movwf LED1 ; --------------------------------

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


andlw 0Fh ; в младший полубайт LED0.
movwf LED0 ; --------------------------------

goto DINAM ; Переход в ПП динамической индикации.

;================================================================================
; Запись в регистр FSR адресов регистров LED0...1 для дальнейшей косвенной
; адресации к ним в ПП adjBCD.
; Переход к обработке следующего LED - после возврата по стеку.
;================================================================================
adjDEC movlw LED0 ; Запись в регистр FSR, через регистр W,
movwf FSR ; адреса регистра LED0 с дальнейшим переходом
call adjBCD ; в ПП adjBCD (адрес следующей команды
; закладывается в стек).
;---> Возврат по стеку из ПП adjBCD.
movlw LED1 ; -----------------------------
movwf FSR ; То же самое для регистра LED1.
call adjBCD ; -----------------------------
;---> Возврат по стеку из ПП adjBCD.

goto Loop16 ; Переход в ПП Loop16, то есть, на


; следующее кольцо числовых преобразований.
;--------------------------------------------------------------------------------
; Основные операции преобразования двоичных чисел в двоично-десятичные.
;--------------------------------------------------------------------------------
adjBCD movlw 3 ; Суммирование содержимого текущего LED с
addwf 0,W ; числом 03h, с записью результата операции,
movwf Mem ; через регистр W, в регистр Mem.

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


15
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 addwf PCL,F ; Содержимое счетчика команд PC увеличивается
; на величину содержимого W.
retlw b'00111111' ; ..FEDCBA = 0
retlw b'00000110' ; .....CB. = 1
retlw b'01011011' ; .G.ED.BA = 2
retlw b'01001111' ; .G..DCBA = 3
retlw b'01100110' ; .GF..CB. = 4
retlw b'01101101' ; .GF.DC.A = 5
retlw b'01111101' ; .GFEDC.A = 6
retlw b'00000111' ; .....CBA = 7
retlw b'01111111' ; .GFEDCBA = 8
retlw b'01101111' ; .GF.DCBA = 9
;================================================================================

;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; ПОДПРОГРАММА ДИНАМИЧЕСКОЙ ИНДИКАЦИИ
;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; Подготовка счетчика количества малых колец индикации
; Index к началу полного цикла динамической индикации.
;------------------------------------------------------
DINAM clrf Index ; Сброс в 0 содержимого счетчика малых колец
; индикации Index.
;--------------------------------------------------------------------------------
; Запись в регистр Count количества больших колец индикации, которые
; должны быть отработаны за один полный цикл динамической индикации.
;--------------------------------------------------------------------------------
movlw .60 ; .60 --> W.
movwf Count ; W --> Count.

CYCLE movlw b'11111111' ; Предустановка состояний выходов дешифратора


movwf PortC ; RC2...RC0 (RC7..3 устанавливаются в 1
; "за компанию").
;--------------------------------------------------------------------------------
; Подготовка к косвенной адресации: запись в регистр W адреса регистра младшего
; разряда (LED0).
; ("привязка" к 7-сегментному индикатору, с активации которого начинается полный
; цикл 1-го большого кольца индикации).
;--------------------------------------------------------------------------------
movlw LED0 ; Запись в регистр W адреса регистра LED0.
addwf Index,W ; Увеличение адреса регистра LED0 на величину
; числа, записанного в регистре счетчика
; количества малых колец индикации Index,
; c сохранением результата в регистре W.
;--------------------------------------------------------------------------------
; Косвенная адресация.
;--------------------------------------------------------------------------------
movwf FSR ; Копирование содержимого регистра W
; в регистр FSR.
movf IndF,W ; Копирование содержимого регистра с адресом,
16
; записанным в регистре FSR, в регистр W.
call TABLE ; Условный переход в ПП TABLE.
;---> Возврат по стеку из ПП TABLE.
;--------------------------------------------------------------------------------
; Группа команд установки запятой.
;--------------------------------------------------------------------------------
movwf Temp ; Копирование содержимого регистра W
; (7-сегментные коды индицируемых двоично-
; десятичных чисел) в регистр Temp.
movlw 1 ; Задание места "дислокации" запятой
; (во 2-м знакоместе справа).
bsf Status,Z ; Поднятие флага нулевого результата Z.
subwf Index,W ; Вычитание содержимого регистра W из
; содержимого регистра Index.
btfss Status,Z ; Проверка состояния флага Z.
goto NO_DOT ; Если флаг Z опущен (результат операции
; не=0), то переход на метку NO_DOT (запятая
; не выставляется).
bsf Temp,7 ; Если флаг Z поднят (результат операции=0),
; то установка в единицу 7-го бита (установка
; запятой) регистра Temp.
;--------------------------------------------------------------------------------
; Группа команд вывода десятичной цифры на индикацию.
;--------------------------------------------------------------------------------
NO_DOT movf Temp,W ; Копирование содержимого регистра Temp
; (7-сегментные коды индицируемых двоично-
; десятичных чисел, плюс запятая) в регистр W
movwf PortB ; Вывод содержимого регистра W в порт В.
;================================================================================
; ДЕШИФРАТОР: программная реализация аналога 555ИД7 (для количества выходов = 3).
;================================================================================
movf Index,W ; Index --> W.
;-------------------------------------
; 3-сценарный вычисляемый переход.
;-------------------------------------
addwf PCL,F ; Содержимое счетчика команд PC увеличивается
; на величину содержимого W.
goto D_0 ; Сценарий №1.
goto D_1 ; Сценарий №2.
bcf PortC,2 ; Сценарий №3. На выводе RC2 выставляется 0.
goto $+4 ; Завершение дешифровки.
D_0 bcf PortC,0 ; На выводе RC0 выставляется 0.
goto $+2 ; Завершение дешифровки.
D_1 bcf PortC,1 ; На выводе RC1 выставляется 0.
;--------------------------------------------------------------------------------
; Группа команд задержки, определяющей время нахождения одного 7-сегментного
; индикатора в активном состоянии (определяющей время прохождения малого кольца
; индикации).
;--------------------------------------------------------------------------------
movlw .67 ; Запись в регистр Temp
movwf Temp ; времязадающей константы.

decfsz Temp,F ; 1-байтный, вычитающий


goto $-1 ; счетчик (задержка).
;--------------------------------------------------------------------------------
; Увеличение на 1 содержимого счетчика количества малых колец индикации Index
; с последующей проверкой результата инкремента на равенство (или нет) числу .3.
;--------------------------------------------------------------------------------
incf Index,F ; Увеличение на 1 содержимого регистра Index
; с сохранением результата в нем же.
movlw 3 ; Запись в регистр W константы .3.
bcf Status,Z ; Сброс флага нулевого результата Z.
subwf Index,W ; Index - W = ... (результат --> W).
btfss Status,Z ; Результат операции вычитания равен
; или нет нулю?
goto CYCLE ; Если не =0 (в регистре Index - число не
17
; равное 3), то переход на новое малое кольцо
; индикации.
; Если =0 (в регистре Index - число равное
; 3), то программа исполняется далее.
;--------------------------------------------------------------------------------
; После того, как последовательно активизируются все 3 7-сегментных индикатора
; линейки, - подготовка к переходу на новое большое кольцо индикации.
;--------------------------------------------------------------------------------
clrf Index ; Сброс в 0 содержимого регистра Index.
;--------------------------------------------------------------------------------
; Уменьшение на 1 содержимого счетчика количества больших колец индикации Count.
;--------------------------------------------------------------------------------
decfsz Count,F ; Декремент содержимого счетчика количества
; больших колец индикации Count с сохранением
; результата в нем же.
goto CYCLE ; Если результат декремента не=0, то переход
; на новое большое кольцо индикации.
; Если результат декремента =0, то программа
; исполняется далее (переход на новый полный
; цикл динамической индикации).
;--------------------------------------------------------------------------------
; Выход из ПП динамической индикации.
;--------------------------------------------------------------------------------
clrf PortB ; "Гашение" всех сегментов.
goto SNOVA ; Переход на следующий цикл программы.
;********************************************************************************
end ; Конец программы.

"Боевая раскраска" та же, что и в программе Analog_1.asm.


Принципиальная схема под программу Analog_2.asm выглядит так.

Если лень отпаять "проволчину" от вывода RC3, то можно и не отпаивать


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

18
swapf LED1,W ; Запись старшего полубайта LED1
andlw 0Fh ; в младший полубайт LED3.
movwf LED3 ; --------------------------------

из ПП Bin2_10 удалена (зачем работать с "мертвецом"?), и в ПП динамической


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

В следующем подразделе, с целью "выпытывания военной тайны", связанной с


возможными "закольцовками" и с точностью АЦП, в программу Analog_2.asm будет
"заслан шпион".
Может быть он в ней и еще что-нибудь "разнюхает" (дай-то Бог).
Да и гашением незначащих нулей нужно озаботиться.

Примечание: работа программ Analog_1.asm и Analog_2.asm проверена в "железе".


"Мин нет". Можно смело пользоваться.

"Практикум по конструированию устройств на PIC контроллерах"      http://ikarab.narod.ru       E-mail: karabea@lipetsk.ru

19