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

7/8. Генератор импульсов длительностью от 1 мкс. до 999 мкс.

(разрешение
1 мкс.), с индикацией точного, числового значения длительности импульса в
линейке из трех 7-сегментных индикаторов (для случаев правого и левого
выравнивания результата АЦП). "Адаптация" ПП Bin2_10 под левое
выравнивание результата АЦП.

Усложняю усторойство предыдущего подраздела: ввожу в него дополнительную


функцию вывода на индикацию точного, числового значения длительности импульса.

Теперь можно "отказаться от услуг" осциллографа, да и контрольного светодиода тоже.


На схеме я их выделил светло – серым цветом.
Это означает то, что, в данном случае, их применение не обязательно.
Сразу обращаю Ваше внимание на то, что в результате этой доработки, "быстрое"
устройство предыдущего подраздела "превратилось" в "медленное".
Проще говоря, от момента времени начала "верчения" движка переменного резистора и
до момента смены показаний индикатора, пройдет несколько десятков миллисекунд.
Если не знать о только что сказанном, то можно подумать, что смена показаний
производится сразу же после начала "верчения" движка переменного резистора, так как
визуально "засечь" такую инерционность весьма затруднительно.
Это все-равно что визуально "засечь" один кадр видеосъемки, произведенной со
скоростью 24 кадра в секунду.
Так что, в данном случае, это вполне приемлемо.
Чем определяется величина этой инерционности?
Ее величина определяется суммарным временем отработки всего того, что связано с
динамической индикацией (включая и ПП Bin2_10, и процедуру гашения незначащих
нулей).
Естественно, что это затягивает время исполнения полного цикла программы.
В течение интервала времени этой "затяжки", модуль CCP будет формировать
серию импульсов одинаковой длительности.
Какой именно длительности?
Той, числовое значение которой "лежит", в буфере модуля CCP, на момент начала
исполнения ПП Bin2_10.
Если, в течение интервала времени отработки этой группы подпрограмм (а проще
говоря, "врезки"), произойдет изменение положения движка переменного резистора, то,
1
после этого, длительность импульсов не изменится вплоть до момента "загрузки", в
буфер модуля CCP, "нового", числового значения длительности импульса.
А это произойдет только на следующем "витке" полного цикла программы (то есть,
после отработки всех, указанных выше, процедур).
Вот Вам и инерционность смены показаний, которая возникает за счет увеличения
(затягивания) времени исполнения полного цикла программы.
При этом (и не смотря на это), модуль CCP, как "свою копну молотил" (в части
касающейся формирования периодов), так и будет ее "молотить", вплоть до
выключения питания: 1000 мкс. (в данном случае) и "не шага в сторону".
Эта "строгость" определяется управляющими, фиксированными (в данном случае)
настройками модуля CCP, произведенными в начале 1-го "витка" полного цикла
программы (начиная со 2-го "витка" и далее, они обходятся).
Что касается длительности импульса, то модуль CCP, работающий в режиме ШИМ,
совсем о ней не "задумывается".
Он просто "тупо" сравнивает содержимое TMR2 c тем, что "лежит" в буфере.
Если это "то" не будет меняться, то модуль CCP, "с тупостью железяки", выдаст
серию одинаковых по длительности (она зависит от содержимого буфера) импульсов, и
"будь здоров".
А если это "то" будет меняться, например, в каждом периоде, то модуль CCP, точно
таким же образом, сформирует серию "разнокалиберных" импульсов.
Ему это "что в лоб, что по лбу" - все едино.
Вот такая, в сущности, достаточно простая логика работы.
После "запуска в работу" этой "тупой железяки" (это я любя), конструктору нужно
только позаботиться о порядке заполнения буфера (с расчетной скоростью) тем, что
ему нужно.
Если с этими "делами" у него все в порядке, то будет ему и счастье и улыбка до
ушей, а если не в порядке, то будет ему и "голый зад", и "фингал под глазом".
Первого хотят все. Второго не хочет никто.
Тогда почему так много несчастных (в той или иной форме)?
Ответ на этот вопрос индивидуален, могуч, "стержнеподобен" и выходит далеко за
рамки технического аспекта.
Вернусь к своим "котлетам".
Так как имеется 2 типа выравнивания результата АЦП, то я составил 2
соответствующие программы.
В "железе", они работают одинаково, и поэтому можно использовать любую из них.
Разница, естественно, есть, но она "окопалась в программном секторе".
Начну с правого выравнивания.

;********************************************************************************
; Schim_7.asm Регулятор скважности
; (вариант с правым выравниванием результата АЦП)
;--------------------------------------------------------------------------------
; Задействуется модуль АЦП и модуль ССP, работающий в режиме ШИМ.
; Скважность регулируется переменным резистором.
; Числовое значение длительности импульса (в мкс., запятой нет) выводится на
; индикацию в линейку из 3-х 7-сегментных индикаторов.
; Незначащие нули гасятся в двух десятичных разрядах (кроме младшего).
; Индикация - динамическая.
; Диапазон изменения длительности импульса от 1мкс. до 999мкс. с разрешающей
; способностью 1 мкс.
; Импульсная последовательность, длительность импульсов которой индицируется,
; выводится на RC2.
;********************************************************************************
; "Практикум по конструированию устройств на PIC контроллерах"
; (http://ikarab.narod.ru)
; Корабельников Евгений Александрович karabea@lipetsk.ru
;********************************************************************************
; Функции выводов порта А:
; RA0 - активный входной канал АЦП,
; остальные выводы порта А не задействованы.
; Функции выводов порта В:

2
; RB0...RB7 - управление секторами A,B,C,D,E,F,H,G.
; Функции выводов порта С:
; RC2 - выход модуля CCP (выход ШИМ),
; RC0, RC1, RC3 - выходы дешифратора,
; остальные выводы порта C не задействованы.
; Кварц 4000 Кгц (1 м.ц.= 1 мкс.).
; Опорное напряжение -> Uпит. ПИКа.
; Частота импульсов -> 1000 Гц.
; Используется PIC16F873A.
;----------------------------------------------
; Объем программы: 181 слово в памяти программ.
;================================================================================
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).
;-------------------------------------
; Регистры, обеспечивающие ШИМ.
;-------------------------------------
PIR1 equ 0Ch ; Регистр флагов прерываний
; от периферийных модулей.
T2CON equ 12h ; Регистр управления модулем таймера TMR2.
CCP1CON equ 17h ; Регистр управления модулем CCP.
CCPR1L equ 15h ; Регистр младшего байта CCP.
PR2 equ 12h ; Регистр периода (банк 1).
;================================================================================
; Регистры общего назачения.
;================================================================================
LED0 equ 20h ; Регистр хранения результатов преобразований
; 1-го двоично-десятичного разряда.
LED1 equ 21h ; ------- 2-го -------------------------
LED2 equ 22h ; ------- 3-го -------------------------
Index equ 23h ; Счетчик количества малых колец индикации.
Temp equ 24h ; Регистр временного хранения данных.
Mem equ 25h ; Регистр оперативной памяти.
Count equ 26h ; Регистр счетчика.
Temp_L equ 27h ; Регистр младшего разряда 2-байтного
; двоичного числа.
Temp_H equ 28h ; Регистр старшего разряда 2-байтного
; двоичного числа.
;================================================================================
; Определение места размещения результатов операций.
;================================================================================
W equ 0 ; Результат направить в аккумулятор.
F equ 1 ; Результат направить в регистр.
;================================================================================
; Присвоение битам названий.
3
;================================================================================
C equ 0 ; Флаг переноса-заема.
Z equ 2 ; Флаг нулевого результата.
RP0 equ 5 ; Бит выбора банка.
GO equ 2 ; Бит статуса модуля АЦП.
TMR2IF equ 1 ; Флаг прерывания по переполнению TMR2.
;================================================================================
org 0 ; Начать выполнение программы
; с 0-го адреса PC.
;********************************************************************************

;********************************************************************************
; НАЧАЛО ПРОГРАММЫ.
;********************************************************************************
; Подготовительные операции.
;================================================================================
; Перевод в пассивное состояние всех выходов дешифратора
; (для исключения "мелькания" при включении питания).
;-------------------------------------------------------
bsf PortC,0 ; Предустановка состояний
bsf PortC,1 ; выходов дешифратора
bsf PortC,3 ; RC0, RC1, RC3.
;-------------------------------------------
; Задание длительности периода сигнала ШИМ
; и настройка направлений работы.
;-------------------------------------------
bsf Status,RP0 ; Переход в 1-й банк.
clrf TrisC ; Все выводы порта С работают на выход.
clrf TrisB ; Все выводы порта В работают на выход.
movlw .249 ; Задание длительности
movwf PR2 ; периода (.249).
;-------------------------------------------
; Работа с регистром Adcon1.
;-------------------------------------------
movlw b'10001110' ; Диапазон квантования напряжения от -Vss до +
movwf Adcon1 ; Vdd, AN0-аналоговый вход, AN1...AN4-цифровые
; каналы ввода/вывода, правое выравнивание.
bcf Status,RP0 ; Переход в 0-й банк.
;------------------------------------------
; Настройка модуля CCP.
;------------------------------------------
movlw b'00001111' ; Включение
movwf CCP1CON ; режима ШИМ.
;------------------------------------------
; Настройка модуля TMR2.
;------------------------------------------
movlw b'00000101' ; TMR2 включен, Кдел.предделителя = 4,
movwf T2CON ; Кдел.выходного делителя = 1.

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

4
; Задержка для перезаряда конденсатора.
;------------------------------------------------
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 ; Для снижения потребляемого устройством тока,
; модуль АЦП выключается до конца отработки
; текущего полного цикла программы.
;--------------------------------------------------------------------------------
; Блокировка результата измерения с числовым значением от .1000 и более.
; Примечание: разложение числа 1000 (00000011 11101000) = 256 х 3 + 232
;--------------------------------------------------------------------------------
movlw 3 ; Проверка байта Temp_H на "залегание в нем"
subwf Temp_H,W ; числа 3 (0000 0011).
btfss Status,Z ; Если это число 3, то переход на проверку
goto CCP ; байта Temp_L, а если нет, то переход
; в ПП CCP.
movlw .232 ; Проверка байта Temp_L на "залегание в нем"
subwf Temp_L,W ; числа 232 (1110 1000).
btfss Status,C ; Если это число меньше или равно 232 (С=1),
goto CCP ; то переход в ПП CCP.
clrf Temp_H ; Если это число больше 232 (С=0), то
movlw b'00000001' ; результат замера сбрасывается в .1,
movwf Temp_L ; которая и выводится на индикацию.
;----------------------------------------------------------
; Задержка 0,2 секунды (для обеспечения "мигания"
; символа "1" в младшем разряде, при показаниях более 999).
;----------------------------------------------------------
movlw .186 ;
movwf LED0 ;
movlw .4 ;
movwf LED1 ;
movlw .2 ;
movwf Count ;

decfsz LED0,F ; Стандартный,


goto $-1 ; вычитающий,
decfsz LED1,F ; 3-байтный
5
goto $-3 ; счетчик.
decfsz Count,F ;
goto $-5 ;

;********************************************************************************
; Далее производится перевод результата "оцифровки" в длительность импульса
; (задействуется модуль CCP, работающий в режиме ШИМ).
;********************************************************************************
; "Загрузка" результата АЦП, из Temp_H/Temp_L, в CCPR1L/CCP1CON,5,4.
;================================================================================
; Определение момента начала "загрузки" в CCPR1L/CCP1CON,5,4.
;------------------------------------------------------------
CCP bcf PIR1,TMR2IF ; Сброс флага прерывания по переполнению TMR2.

btfss PIR1,TMR2IF ; Проверка состояния флага


goto $-1 ; прерывания по переполнению TMR2.
;------------------------------------------------------------
; Сохранение содержимого Temp_L в Temp (для ПП Bin2_10).
;------------------------------------------------------------
movf Temp_L,W ; Temp_L --> Temp.
movwf Temp ;
;------------------------------------------------------------
; "Загрузка" Temp_L,1,0 в CCP1CON,5,4 (1-->5, 0-->4).
;------------------------------------------------------------
btfsc Temp_L,1 ;
goto $+3 ; Бит №1 регистра Temp_L
bcf CCP1CON,5 ; копируется в бит №5
goto $+2 ; регистра CCP1CON.
bsf CCP1CON,5 ;

btfsc Temp_L,0 ;
goto $+3 ; Бит №0 регистра Temp_L
bcf CCP1CON,4 ; копируется в бит №4
goto $+2 ; регистра CCP1CON.
bsf CCP1CON,4 ;
;------------------------------------------------------------
; "Загрузка" Temp_L,7...2 в CCPR1L,5...0.
;------------------------------------------------------------
rrf Temp_L,F ; Содержимое Temp_L сдвигается
rrf Temp_L,F ; вправо на 2 бита.

movf Temp_L,W ; Содержимое Temp_L


movwf CCPR1L ; "загружается" в CCPR1L.
;------------------------------------------------------------
; "Загрузка" Temp_H,1,0 в CCPR1L,7,6.
;------------------------------------------------------------
btfsc Temp_H,1 ;
goto $+3 ; Бит №1 регистра Temp
bcf CCPR1L,7 ; копируется в бит №7
goto $+2 ; регистра CCP1CON.
bsf CCPR1L,7 ;

btfsc Temp_H,0 ;
goto $+3 ; Бит №0 регистра Temp
bcf CCPR1L,6 ; копируется в бит №6
goto $+2 ; регистра CCP1CON.
bsf CCPR1L,6 ;

bcf PIR1,TMR2IF ; Сброс флага прерывания по переполнению TMR2.

;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; ГРУППА ПОДПРОГРАММ ПРЕОБРАЗОВАНИЯ 2-БАЙТНЫХ ДВОИЧНЫХ ЧИСЕЛ В 3-РАЗРЯДНЫЕ
; ДЕСЯТИЧНЫЕ ЧИСЛА (разрядность двоичного числа - 10).
;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; Подготовка к преобразованию.
;================================================================================
6
Bin2_10 bcf Status,C ; Сброс флага переноса-заема.
movlw .16 ; "Закладка" в регистр Count числа
movwf Count ; проходов преобразования.

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


clrf LED1 ; -------"------ LED1.
;================================================================================
; Циклический сдвиг влево.
;================================================================================
Loop16 rlf Temp,F ; Побитная
rlf Temp_H,F ; "переправка"
rlf LED0,F ; содержимого
rlf LED1,F ; Temp_H/Temp
; в 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 GASH ; Переход в ПП гашения незначащих нулей.

;================================================================================
; Запись в регистр 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.
7
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
retlw 0 ; ........ = гашение всех сегментов.
;================================================================================
; Подпрограмма гашения незначащих нулей (в LED0, ноль не гасится).
;================================================================================
GASH movf LED2,W ; Если содержимое LED2=0, то в него
movlw .10 ; записывается число.10
btfss Status,Z ; (сценарий гашения всех сегментов).
goto DINAM ; Если оно не=0, то рабочая точка программы
movwf LED2 ; "улетает" в ПП динамической индикации.

movf LED1,W ;
movlw .10 ; То же самое,
btfss Status,Z ; только для
goto DINAM ; LED1.
movwf LED1 ;

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

CYCLE bsf PortC,0 ; Предустановка состояний


bsf PortC,1 ; выходов дешифратора
bsf PortC,3 ; RC0, RC1, RC3.
;--------------------------------------------------------------------------------
; Подготовка к косвенной адресации: запись в регистр W адреса регистра младшего
; разряда (LED0).
; ("привязка" к 7-сегментному индикатору, с активации которого начинается полный
; цикл 1-го большого кольца индикации).
;--------------------------------------------------------------------------------
movlw LED0 ; Запись в регистр W адреса регистра LED0.
addwf Index,W ; Увеличение адреса регистра LED0 на величину
; числа, записанного в регистре счетчика
8
; количества малых колец индикации Index,
; c сохранением результата в регистре W.
;--------------------------------------------------------------------------------
; Косвенная адресация.
;--------------------------------------------------------------------------------
movwf FSR ; Копирование содержимого регистра W
; в регистр FSR.
movf IndF,W ; Копирование содержимого регистра с адресом,
; записанным в регистре FSR, в регистр W.
call TABLE ; Условный переход в ПП TABLE.
;---> Возврат по стеку из ПП TABLE.

; Примечание: так как в данном случае, запятая не выставляется, то группа команд


; установки запятой удалена.
;--------------------------------------------------------------------------------
; Вывод десятичной цифры на индикацию.
;--------------------------------------------------------------------------------
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,3 ; Сценарий №3. На выводе RC3 выставляется 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 - число не
; равное 3), то переход на новое малое
; кольцо индикации.
; Если =0 (в регистре Index - число равное
; 3), то программа исполняется далее.
;--------------------------------------------------------------------------------
; После того, как последовательно активизируются все 3 7-сегментных индикатора
; линейки, - подготовка к переходу на новое большое кольцо индикации.
;--------------------------------------------------------------------------------
clrf Index ; Сброс в 0 содержимого регистра Index.
;--------------------------------------------------------------------------------
9
; Уменьшение на 1 содержимого счетчика количества больших колец индикации Count.
;--------------------------------------------------------------------------------
decfsz Count,F ; Декремент содержимого счетчика количества
; больших колец индикации Count с сохранением
; результата в нем же.
goto CYCLE ; Если результат декремента не=0, то переход
; на новое большое кольцо индикации.
; Если результат декремента =0, то программа
; исполняется далее (переход на новый полный
; цикл динамической индикации).
;--------------------------------------------------------------------------------
; Выход из ПП динамической индикации.
;--------------------------------------------------------------------------------
clrf PortB ; "Гашение" всех сегментов.
goto SNOVA ; Переход на новый цикл преобразования.
;********************************************************************************
end ; Конец программы.

Предлагаемая Вашему вниманию программа (Schim_7.asm, прилагается) есть "гибрид"


ранее составленных программ Analog_6.asm и Schim_5.asm.
Поэтому, остановлюсь только на особенностях.
"Связка" из подпрограмм 2/10 преобразования, гашения незначащих нулей и
динамической индикации, "врезана" перед переходом на "новый виток" полного цикла
программы (перед goto SNOVA).
И это должно быть понятным, так как сначала нужно заиметь то, что нужно
обработать и вывести на индикацию, а только после этого обрабатывать и выводить.
Так как вывод RC2 задействован для целей, не связанных с дешифрованием
("намертво застолблен" под выход модуля CCP, работающего в режиме ШИМ), то
управляющим выводом старшего, десятичного разряда индикатора назначен вывод RC3
(а куда деваться?).
В принципе, можно было бы "синхронно перебросить" выходы дешифратора, например,
на выводы RC5, RC6, RC7 (чтобы они были "в куче") или еще как-то, но, с целью
обеспечения минимальной "возни" с перепайкой более "ранней" конструкции, я не стал
этого делать.
Желающие, для "тренировки" (или с другой целью), могут осуществить этот "переброс"
самостоятельно.
Соответственно, пришлось "модернизировать" и дешифратор, и группы команд, которые
обеспечивают установку единиц на выходе дешифратора в начале исполнения
программы и в начале ПП CYCLE (эти группы команд одинаковые).
Так как задействованные выводы портов В и С должны работать "на выход", то они и
настраиваются ("оптово") на работу "на выход".
Задействованный вывод порта А (RA0), настраивается на работу "на вход" по
умолчанию.
Далее, вплоть до конца процедуры АЦП, все то же самое, что и в программе
Shim_5.asm.
После отработки АЦП, с целью формирования "зоны числового запрета" и обеспечения
"мигания" символа младшего, десятичного разряда (при попадании результата АЦП в
эту "зону"), в текст программы "врезаются" группы команд "числового запрета" и
задержки (взяты из программы Analog_6.asm).
В данном случае, при попадании результата АЦП в "запретную зону", на индикацию
выведется не "мигающий" символ "0", а "мигающий" символ "1".
Это намек на то, что, при 100-процентном коэффициенте заполнения, формируется
уровень единицы.
Далее, "штатно" отрабатывается "плавающая" задержка (под флаг TMR2IF), и
осуществляется "загрузка" результата АЦП, из Temp_H/Temp_L, в CCPR1L/CCP1CON,5,4.
Но при этом, есть одна особенность.
Дело в том, что, если ничего не предпринять, то, на момент "входа" в ПП Bin2_10,
содержимое регистра Temp_L не будет соответствовать истинному результату АЦП.
Почему?
Потому, что было 2 сдвига, результат которых сохранен в регистре Temp_L
(см. rrf Temp_L,F).
10
Следовательно, в начале "загрузки" результата АЦП, из Temp_H/Temp_L, в
CCPR1L/CCP1CON,5,4, нужно сохранить содержимое Temp_L в каком-нибудь регистре
оперативной памяти (в данном случае, в регистре Temp),
;------------------------------------------------------------
; Сохранение содержимого Temp_L в Temp (для ПП Bin2_10).
;------------------------------------------------------------
movf Temp_L,W ; Temp_L --> Temp.
movwf Temp ;
а затем использовать этот регистр в ПП Bin2_10 (вместо Temp_L), что и сделано.
И еще одна доработка: так как управляющим выводом, для индикатора старшего
разряда, является не вывод RC2 (это было раньше), а вывод RC3, то, в группе
команд дешифратора, команда bcf PortC,2 заменена на команду bcf PortC,3.
Примечание: подпрограммы 2/10 преобразования, гашения незначащих нулей и
динамической индикации просто "передраны" из программы Analog_6.asm, после чего, с
учетом сказанного выше, "модернизированы" (ПП гашения незначащих нулей - без
изменения).
Одна задача решена.
Теперь нужно "модернизировать" программу Schim_7.asm под левое выравнивание
результата АЦП.
Получилась программа Schim_8.asm (прилагается):

;********************************************************************************
; Schim_8.asm Регулятор скважности
; (вариант с левым выравниванием результата АЦП)
;--------------------------------------------------------------------------------
; Задействуется модуль АЦП и модуль ССP, работающий в режиме ШИМ.
; Скважность регулируется переменным резистором.
; Числовое значение длительности импульса (в мкс., запятой нет) выводится на
; индикацию в линейку из 3-х 7-сегментных индикаторов.
; Незначащие нули гасятся в двух десятичных разрядах (кроме младшего).
; Индикация - динамическая.
; Диапазон изменения длительности импульса от 1мкс. до 999мкс. с разрешающей
; способностью 1 мкс.
; Импульсная последовательность, длительность импульсов которой индицируется,
; выводится на RC2.
;********************************************************************************
; "Практикум по конструированию устройств на PIC контроллерах"
; (http://ikarab.narod.ru)
; Корабельников Евгений Александрович karabea@Lipetsk.ru
;********************************************************************************
; Функции выводов порта А:
; RA0 - активный входной канал АЦП,
; остальные выводы порта А не задействованы.
; Функции выводов порта В:
; RB0...RB7 - управление секторами A,B,C,D,E,F,H,G.
; Функции выводов порта С:
; RC2 - выход модуля CCP (выход ШИМ),
; RC0, RC1, RC3 - выходы дешифратора,
; остальные выводы порта C не задействованы.
; Кварц 4000 Кгц (1 м.ц.= 1 мкс.).
; Опорное напряжение -> Uпит. ПИКа.
; Частота импульсов -> 1000 Гц.
; Используется PIC16F873A.
;----------------------------------------------
; Объем программы: 170 слов в памяти программ.
;================================================================================
LIST p=16F873A ; "Привязка" к типу микроконтроллера.
__CONFIG 3F31H ; XT-генератор, PWRT вкл., защита выкл., сброс
; BOR запрещен, LVP выкл., DEBUG выкл.
;================================================================================
; Регистры специального назначения.
;================================================================================
IndF equ 00h ; Доступ к памяти через FSR.
PCL equ 02h ; Счетчик команд.
11
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).
;-------------------------------------
; Регистры, обеспечивающие ШИМ.
;-------------------------------------
PIR1 equ 0Ch ; Регистр флагов прерываний
; от периферийных модулей.
T2CON equ 12h ; Регистр управления модулем таймера TMR2.
CCP1CON equ 17h ; Регистр управления модулем CCP.
CCPR1L equ 15h ; Регистр младшего байта CCP.
PR2 equ 12h ; Регистр периода (банк 1).
;================================================================================
; Регистры общего назачения.
;================================================================================
LED0 equ 20h ; Регистр хранения результатов преобразований
; 1-го двоично-десятичного разряда.
LED1 equ 21h ; ------- 2-го -------------------------
LED2 equ 22h ; ------- 3-го -------------------------
Index equ 23h ; Счетчик количества малых колец индикации.
Temp equ 24h ; Регистр временного хранения данных.
Mem equ 25h ; Регистр оперативной памяти.
Count equ 26h ; Регистр счетчика.
Temp_L equ 27h ; Регистр младшего разряда 2-байтного
; двоичного числа.
Temp_H equ 28h ; Регистр старшего разряда 2-байтного
; двоичного числа.
;================================================================================
; Определение места размещения результатов операций.
;================================================================================
W equ 0 ; Результат направить в аккумулятор.
F equ 1 ; Результат направить в регистр.
;================================================================================
; Присвоение битам названий.
;================================================================================
C equ 0 ; Флаг переноса-заема.
Z equ 2 ; Флаг нулевого результата.
RP0 equ 5 ; Бит выбора банка.
GO equ 2 ; Бит статуса модуля АЦП.
TMR2IF equ 1 ; Флаг прерывания по переполнению TMR2.
;================================================================================
org 0 ; Начать выполнение программы
; с 0-го адреса PC.
;********************************************************************************

;********************************************************************************
; НАЧАЛО ПРОГРАММЫ.
;********************************************************************************
; Подготовительные операции.
;================================================================================
; Перевод в пассивное состояние всех выходов дешифратора
; (для исключения "мелькания" при включении питания).
;-------------------------------------------------------
12
bsf PortC,0 ; Предустановка состояний
bsf PortC,1 ; выходов дешифратора
bsf PortC,3 ; RC0, RC1, RC3.
;-------------------------------------------
; Задание длительности периода сигнала ШИМ
; и настройка направлений работы.
;-------------------------------------------
bsf Status,RP0 ; Переход в 1-й банк.
clrf TrisC ; Все выводы порта С работают на выход.
clrf TrisB ; Все выводы порта В работают на выход.
movlw .249 ; Задание длительности
movwf PR2 ; периода (.249).
;-------------------------------------------
; Работа с регистром Adcon1.
;-------------------------------------------
movlw b'00001110' ; Диапазон квантования напряжения от -Vss до +
movwf Adcon1 ; Vdd, AN0-аналоговый вход, AN1...AN4-цифровые
; каналы ввода/вывода, левое выравнивание.
bcf Status,RP0 ; Переход в 0-й банк.
;------------------------------------------
; Настройка модуля CCP.
;------------------------------------------
movlw b'00001111' ; Включение
movwf CCP1CON ; режима ШИМ.
;------------------------------------------
; Настройка модуля TMR2.
;------------------------------------------
movlw b'00000101' ; TMR2 включен, Кдел.предделителя = 4,
movwf T2CON ; Кдел.выходного делителя = 1.

;################################################################################
; Циклическая подпрограмма "оцифровки" уровня аналогового сигнала,
; присутствующего на выводе 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.
;-------------------------------------------
13
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 ; Для снижения потребляемого устройством тока,
; модуль АЦП выключается до конца отработки
; текущего полного цикла программы.
;--------------------------------------------------------------------------------
; Блокировка результата измерения с числовым значением от .64000 и более.
; Примечание: разложение числа 64000 (11111010 00000000) = 256 х 250 + 0
;--------------------------------------------------------------------------------
movlw .250 ; Проверка байта Temp_L на "залегание в нем"
subwf Temp_H,W ; числа 250 (1111 1010).
btfss Status,C ; Если это число меньше или равно 250 (С=1),
goto CCP ; то переход в ПП CCP.
clrf Temp_H ; Если это число больше 250 (С=0), то
clrf Temp_L ; результат замера сбрасывается в .1,
bsf Temp_L,6 ; которая и выводится на индикацию.
;----------------------------------------------------------
; Задержка 0,2 секунды (для обеспечения "мигания"
; символа "1" в младшем разряде, при показаниях более 999).
;----------------------------------------------------------
movlw .186 ;
movwf LED0 ;
movlw .4 ;
movwf LED1 ;
movlw .2 ;
movwf Count ;

decfsz LED0,F ; Стандартный,


goto $-1 ; вычитающий,
decfsz LED1,F ; 3-байтный
goto $-3 ; счетчик.
decfsz Count,F ;
goto $-5 ;
;********************************************************************************
; Далее производится перевод результата "оцифровки" в длительность импульса
; (задействуется модуль CCP, работающий в режиме ШИМ).
;********************************************************************************
; "Загрузка" результата АЦП, из Temp_H/Temp_L, в CCPR1L/CCP1CON,5,4.
;================================================================================
; Определение момента начала "загрузки" в CCPR1L/CCP1CON,5,4.
;------------------------------------------------------------
CCP bcf PIR1,TMR2IF ; Сброс флага прерывания по переполнению TMR2.

btfss PIR1,TMR2IF ; Проверка состояния флага


goto $-1 ; прерывания по переполнению TMR2.
;------------------------------------------------------------
; "Загрузка" Temp_L,7,6 в CCP1CON,5,4 (7-->5, 6-->4).
;------------------------------------------------------------
btfsc Temp_L,7 ;
goto $+3 ; Бит №7 регистра Temp_L
bcf CCP1CON,5 ; копируется в бит №5
goto $+2 ; регистра CCP1CON.
bsf CCP1CON,5 ;

btfsc Temp_L,6 ;
goto $+3 ; Бит №6 регистра Temp_L
14
bcf CCP1CON,4 ; копируется в бит №4
goto $+2 ; регистра CCP1CON.
bsf CCP1CON,4 ;
;------------------------------------------------------------
; "Загрузка" Temp_H в CCPR1L.
;------------------------------------------------------------
movf Temp_H,W ; Содержимое Temp_H
movwf CCPR1L ; "загружается" в CCPR1L.

bcf PIR1,TMR2IF ; Сброс флага прерывания по переполнению TMR2.

;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; ГРУППА ПОДПРОГРАММ ПРЕОБРАЗОВАНИЯ 2-БАЙТНЫХ ДВОИЧНЫХ ЧИСЕЛ
; В 3-РАЗРЯДНЫЕ ДЕСЯТИЧНЫЕ ЧИСЛА (разрядность двоичного числа - 10).
;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; Подготовка к преобразованию.
;================================================================================
Bin2_10 bcf Status,C ; Сброс флага переноса-заема.

movlw 6 ; Задание количества


movwf Temp ; сдвигов.

rrf Temp_H,F ; Сдвиг вправо,


rrf Temp_L,F ; на 6 битов,
decfsz Temp,F ; содержимого
goto $-3 ; Temp_H/Temp_L.

bcf Status,C ; Сброс флага переноса-заема.


movlw .16 ; "Закладка" в регистр Count числа
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 GASH ; Переход в ПП гашения незначащих нулей.

;================================================================================
; Запись в регистр FSR адресов регистров LED0...1 для дальнейшей косвенной
; адресации к ним в ПП adjBCD.
; Переход к обработке следующего LED - после возврата по стеку.
;================================================================================
15
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 увеличивается
; на величину содержимого 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
retlw 0 ; ........ = гашение всех сегментов.
;================================================================================
; Подпрограмма гашения незначащих нулей (в LED0, ноль не гасится).
;================================================================================
GASH movf LED2,W ; Если содержимое LED2=0, то в него
movlw .10 ; записывается число.10
btfss Status,Z ; (сценарий гашения всех сегментов).
goto DINAM ; Если оно не=0, то рабочая точка программы
movwf LED2 ; "улетает" в ПП динамической индикации.

movf LED1,W ;
movlw .10 ; То же самое,
btfss Status,Z ; только для
goto DINAM ; LED1.
movwf LED1 ;

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

CYCLE bsf PortC,0 ; Предустановка состояний


bsf PortC,1 ; выходов дешифратора
bsf PortC,3 ; RC0, RC1, RC3.
;--------------------------------------------------------------------------------
; Подготовка к косвенной адресации: запись в регистр 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 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,3 ; Сценарий №3. На выводе RC3 выставляется 0.
goto $+4 ; Завершение дешифровки.
D_0 bcf PortC,0 ; На выводе RC0 выставляется 0.
goto $+2 ; Завершение дешифровки.
D_1 bcf PortC,1 ; На выводе RC1 выставляется 0.
;--------------------------------------------------------------------------------
; Группа команд задержки, определяющей время нахождения одного 7-сегментного
; индикатора в активном состоянии (определяющей время прохождения
; малого кольца индикации).
;--------------------------------------------------------------------------------
17
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 - число не
; равное 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 ; Конец программы.

Разница между программами Schim_7.asm и Schim_8.asm заключается в следующем:


1. Переход с правого на левое выравнивание (сдвиг на 6 битов) эквивалентен
умножению числа на 2 в степени 6, то есть, на 64.
Следовательно, при установке "границы убийственной зоны", нужно ориентироваться не
на число .1000, а на число .1000 х 64 = .64000, что и имеет место быть:

;--------------------------------------------------------------------------------
; Блокировка результата измерения с числовым значением от .64000 и более.
; Примечание: разложение числа 64000 (11111010 00000000) = 256 х 250 + 0
;--------------------------------------------------------------------------------
movlw .250 ; Проверка байта Temp_L на "залегание в нем"
subwf Temp_H,W ; числа 250 (1111 1010).
btfss Status,C ; Если это число меньше или равно 250 (С=1),
goto CCP ; то переход в ПП CCP.
clrf Temp_H ; Если это число больше 250 (С=0), то
clrf Temp_L ; результат замера сбрасывается в .1,
bsf Temp_L,6 ; которая и выводится на индикацию.

В разложении числа .64000, младший байт имеет нулевое значение.

18
Это раз.
Перенос в старший байт будет осуществлен только через 256 квантовок, то есть, при
количестве квантовок значительно превышающем число 1024, чего никогда не будет.
Это два.
Вывод: при установке "границы убийственной зоны", нужно работать только со старшим
байтом, а младший байт проигнорировать (выигрыш и по количеству команд, и по
скорости, и по чему угодно).
Это Вы и видите.
2. Мало того, что, по сравнению с правым выравниванием результата АЦП, при
применении левого выравнивания результата АЦП, количество команд процедуры
"загрузки" результата АЦП, из Temp_H/Temp_L, в CCPR1L/CCP1CON,5,4, уменьшается,
но и отпадает необходимость сохранения содержимого регистра Temp_L в регистре
Temp.
Почему?
Потому, что, в данном случае, содержимое регистра Temp_L не сдвигается.
То есть, оно не изменяется.
Но в этом случае, возникают "числовые проблемы" ("непонимайки", отсутствие
"числовой любви") в ПП Bin2_10.
Вывод: после "загрузки" результата АЦП, из Temp_H/Temp_L, в CCPR1L/CCP1CON,5,4,
нужно осуществить переход от левого выравнивания результата АЦП к правому, иначе,
в показаниях, будет "страшное, числовое враньё" (специально, ради любопытства,
попробовал. Получился "тихий ужас").
Чтобы этого не было, нужно сделать так:
;================================================================================
; Подготовка к преобразованию.
;================================================================================
Bin2_10 bcf Status,C ; Сброс флага переноса-заема.

movlw 6 ; Задание количества


movwf Temp ; сдвигов.

rrf Temp_H,F ; Сдвиг вправо,


rrf Temp_L,F ; на 6 битов,
decfsz Temp,F ; содержимого
goto $-3 ; Temp_H/Temp_L.

Для "ваяния" такой "штуковины", "ума палата" не нужна.


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

Результат работы программ Schim_7.asm и Schim_8.asm (в "железе") - одинаковый.


Каждая из них имеет свои плюсы и свои минусы.
Лично мне, больше нравится программа Schim_8.asm.
Ее "слегка портит" переход с одного типа выравнивания результата АЦП на другой, но
и выигрыш в 11 команд "на дороге не валяется".
В данном случае, этот переход реализован в виде функционально обособленной,
дополнительной процедуры, которая, по мере необходимости, может "пристегиваться" к
ПП Bin2_10 (или "отстегиваться" от нее), но вполне разумно предположить, что если
продолжить "рыть" в этом направлении, то, вмешавшись в базовый алгоритм ПП
Bin2_10, можно создать специализированную подпрограмму 2/10 преобразования,
приспособленную под левое выравнивание, а также и сделать то же самое по
отношению к другим "конструкциям" ПП 2/10 преобразования (например, с ПП 2/10
преобразования Сергея Рослика).

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

19