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

6/3. Объяснение работы модуля TMR1.

Пример его применения или “убийство”


подпрограммы досчета (действующий ЧМ/ЦШ на PIC16F628A, с ЖКИ модулем
на основе HT1611/1613, без ПП досчета). Практикум по переводу программы с
PIC16F84A на PIC16F628A.

Если говорить по рабоче – крестьянски, то таймер TMR1 это такая же “корова”, что и
таймер TMR0, но только более “упитанная”.
Соответственно, “мяса” будет больше.
Главное преимущество таймера TMR1 (по сравнению с таймером TMR0) - повышенная
“байтность”: таймер TMR1 формирует результат подсчета в виде 2-байтного, а не 1-
байтного слова.
Соответственно, имеется регистр младшего разряда и регистр старшего разряда.
А если это так, значит должен быть организован перенос из младшего разряда в
старший.
В данном случае, “ломать голову” над этим не стоит, так никакого программного
переноса организовывать не нужно.
Почему?
Потому, что перенос организуется аппаратно.
Короче, красота и ляпота: нужно только сконфигурировать модуль TMR1 под
внутренний или внешний такт и сделать так, чтобы этот такт имел место быть.
При этом, переполнение TMR1 будет наступать не при переходе от 255-го к 256-му
(то есть, к нулевому) состоянию (как в TMR0), а при переходе от 65535-го к 65536-му
(опять же, к нулевому) состоянию.
Чтобы достигнуть таких “высот”, таймер TMR0 должен работать с предделителем, в
котором выставлен максимальный коэффициент деления (256).
По этой причине, TMR1 без предделителя заменяет TMR0 с предделителем.
А ведь у TMR1 есть и свой предделитель, правда с небольшим коэффициентом
деления (1:1, 1:2, 1:4, 1:8).
Поэтому, по количеству подсчитанных имульсов (от нуля и до переполнения), работа
“связки” “предделитель – TMR1” до 8 раз более выигрышна, чем работа “ связки”
“предделитель – TMR0”.
Без учета предделителей, эта цифра возрастает до 256.
Это и есть то, что выше названо “мясом” (и это еще не все “мясо”).
Получается, что TMR1 без предделителя заменяет TMR0 с предделителем (если
Кдел. предделителя = 256).
А нельзя ли эффективно использовать этот вывод на практике?
И можно, и нужно.
Давайте посмотрим что из этого получится.
“Привяжусь” к своему частотомеру – цифровой шкале (ЧМ/ЦШ).
В нем работает “связка” “предделитель - TMR0”, причем, предделитель имеет Кдел. =
256.
Наличие однобайтного таймера и предделителя вынуждает применить ПП досчета, и от
этого никуда не денешься.
А теперь “провернем простенькую комбинацию из двух пальцев”, то есть, заменим
“связку” “предделитель - TMR0” на TMR1 без предделителя.
Примечание: словосочетание “TMR1 без предделителя” не свидетельствует о том, что
предделитель вообще не работает. Он работает, только с Кдел. = 1.
В соответствии со сказанным выше, такая замена эквивалентна.
Получается то, что регистр младшего разряда таймера TMR1 заменяет
предделитель (тот, который подключен к TMR0, с Кдел. = 256), а регистр старшего
разряда таймера TMR1 заменяет таймер TMR0.
Но в отличие от предделителя, подключенного к TMR0, из которого, после окончания
счета, нужно “выпихивать” байт данных при помощи ПП досчета, содержимое регистра
младшего разряда TMR1 можно просто банально считать.
И никаких “выкрутасов”, в виде ПП досчета.
В данном случае, она просто не нужна, и ее можно (и нужно) “убить”.
Как Вам такая перспектива?
По-моему, она очень заманчива и “аппетитно пахнет”.

1
А раз это так, то “шашки наголо”, и нечего “увязать в даташитной теории”, которая
сильно грешит отсутствием “привязки к жизни” (скукатища несусветная. Написано для
биороботов).
“Беру за шкирку” этот TMR1 и сразу же “сую его в железяку”.
Пусть, родимый, ощутит своими “рецепторами”, что он попал “не к теще на блины”, а
в надежные и бесцеремонные “лапы”: раз назвался и под горячую руку подвернулся,
значит сразу полезай в то место, в котором от тебя больше всего толка.
Ниже, я на Ваших глазах заставлю этого “даташитного тунеядца” “пахать в поте лица”,
а по ходу дела, постепенно выведаю остальные его секреты.
По-моему, это самый эффективный способ “въезда”.
Итак, прежде чем “сунуть TMR1 в железяку”, нужно выбрать “программу – мать”.
Я выбрал программу Lcd1611c.asm (есть на CD).
Это программа ЧМ/ЦШ, прошивка которой “лежит” на сайте (ЧМ/ЦШ на PIC16F84A с
ЖКИ модулем на основе HT1611/1613).
Так как программа Lcd1611c.asm составлена под PIC16F84A и модуля таймера TMR1 в
составе этого ПИКа нет, то нужно переделать программу под тот тип ПИКа, который
этот модуль имеет.
Лучше всего переделать программу под PIC16F628A.
В этом случае потребуется простейшая доработка принципиальной схемы.
Начну с объяснения “механики” работы модуля таймера TMR1 (это конечно нудно, но
необходимо).
Она примерно такая же, как и “механика” работы модуля таймера TMR0, но со своей
спецификой.
Модулем таймера TMR1 управляет не регистр OPTION_REG, а регистр T1CON (см.
стр. 48 даташита PIC16F628A).
За включение/выключение модуля TMR1 “отвечает” бит №0 регистра T1CON с
названием TMR1ON.
TMR1ON = 1 - модуль TMR1 включен.
TMR1ON = 0 - модуль TMR1 выключен.
По умолчанию, модуль TMR1 выключен.
Если модуль TMR1 включен, то задействуются выводы RB6 и RB7.
TMR1, от нуля и до переполнения, считает не до .255, а до .65535 (только
инкремент).
При этом, результат счета “оседает” в 2-байтном регистре TMR1L/TMR1H (адреса в
области оперативной памяти PIC16F628A, 0Eh и 0Fh соответственно).
Этот результат, либо выборочно, либо в два приема, можно считать, а также и
произвести предустановку (запись).
Перенос из TMR1L в TMR1H осуществляется автоматически (аппаратно).
При переходе от 65535-го состояния к 65536-му состоянию (то есть, к 0), поднимается
флаг прерывания по переполнению TMR1 (бит №0 с названием TMR1IE регистра
PIR1), причем, он поднимается независимо от того, разрешено или нет прерывание по
переполнению TMR1 (это важно).
После обнаружения поднятия флага TMR1IE и соответствующих этому событию
“оргвыводов”, его нужно программно сбросить.
TMR1, так же, как и TMR0, может работать от внутреннего такта (CLKOUT).
При этом, бит №1 (TMR1CS) регистра T1CON должен быть установлен в 0.
При применении кварца на 4 Мгц., приращение содержимого TMR1 будет происходить
каждую микросекунду (1 / {Fкв / 4}) и оно, естественно, будет синхронизировано с
внутренним тактом.
TMR1, так же, как и TMR0, может работать от внешнего такта (TMR1CS = 1), причем,
кроме обычного способа подачи внешнего такта на счетный вход модуля TMR1,
внешний такт можно сформировать при помощи кварца (в модуле таймера TMR0 этого
нет).
Что касается последнего, то, не смотря на то, что “потроха” кварцевого генератора
расположены внутри ПИКа, кварц является внешним элементом, и именно его наличие
определяет то, что, в данном случае, имеет место быть разновидность внешнего такта.
В этом деле, сразу нужно “навести терминологический порядок”.

2
Условимся называть внешний такт, подаваемый обычным способом, на счетный вход
модуля таймера TMR1 (как при работе с TMR0), стандартным внешним тактом, а
внешний такт, формируемый при помощи кварца, внешним тактом генератора TMR1.
Внутри модуля TMR1, имеется инвертор (основа любого генератора), два вывода
которого “выведены наружу” (см. рис. 7-1 на стр. 49 даташита PIC16F628A).
К ним (RB6 и RB7) и подключается кварц (максимальная частота кварца - 200 Кгц.).
В основном, генератор TMR1 работает с “часовым кварцем” (для этого и придуман),
что позволяет отсчитывать интервалы времени равные одной секунде.
Если нужно задействовать кварцевый генератор TMR1, то к выводам RB6, RB7 нужно
подключить кварц и установить бит №3 (T1OSCEN) регистра T1CON в 1 (генератор
включен).
При этом, выводы RB6 и RB7 аппаратно настраиваются на работу “на вход”
(состояния битов регистра TRISB с №№6 и 7 не важны).
Если кварц подключен, то работать со стандартным внешним тактом нельзя, а если он
отключен, то можно.
В последнем случае, нужно подать стандартный внешний такт на вывод RB7.
Кроме того, можно выключить генератор TMR1, путем установки бита №3 (T1OSCEN)
регистра T1CON в 0, и подать стандартный внешний такт на вывод RB6.
Последний способ работы со стандартным внешним тактом, в дальнейшем, и будет
использован.
В связи с этим, обращаю Ваше внимание на то, что, если генератор TMR1 выключен
(T1OSCEN = 0), то состояния битов №№6 и 7 регистра TRISA уже не игнорируются.
В этих битах нужно выставить 1 (работа на вход).
Таким образом, имеется две разновидности подачи стандартного внешнего такта на
счетный вход модуля таймера TMR1.
Более подробно.
В случае включения генератора TMR1, стандартный внешний такт нельзя подавать на
вывод RB6, так как, из-за объединения выходов инвертора генератора TMR1 и
источника внешнего такта, возникает электрический конфликт.
Выход из положения - подключение источника стандартного внешнего такта ко входу
инвертора, то есть, к выводу RB7, что и имеет место быть.
В случае выключения генератора TMR1 (T1OSCEN = 0), выход инвертора переводится в
Z – состояние и резистор обратной связи отключается.
В этом случае, ничто не мешает подключить выход источника стандартного внешнего
такта к выводу RB6, что и имеет место быть.
В обеих случаях, приращения содержимого TMR1 происходят по фронтам импульсной
последовательности внешнего такта (переход от 0 к 1).
В большинстве случаев, не важно, по фронту или спаду происходит приращение, но
такого рода информация может потребоваться в будущем.

О синхронизации.
При работе от внешнего такта, синхронизация внешнего такта может быть либо
разрешена, либо запрещена.
“За это дело отвечает” бит №2 регистра T1CON с названием T1SYNC.
T1SYNC = 1 - асинхронный режим.
T1SYNC = 0 - синхронный режим.
Этот бит активен только при работе от внешнего такта.
При работе от внутреннего такта (TMR1CS = 0), синхронизация обеспечивается по
определению.
Модуль таймера TMR1 может быть задействован в работе модуля CCP (о нем
расскажу позднее).
В этом случае, если используется внешний такт, то модуль таймера TMR1 должен
работать в синхронном режиме (T1SYNC = 0)
Если используется внутренний такт, то значение бита T1SYNC не важно.
В большинстве случаев (но не во всех), о синхронизации вспоминается только при
совместной работе модулей TMR1 и CCP.
А раз это так, то и нечего сейчас “забивать ей себе голову”.
При “ковырянии” модуля CCP (в части касающейся его совместной работы с модулем
TMR1), я о ней вспомню.
3
Без учета этого, в большинстве случаев, когда речь идет о подсчете количества
импульсов внешнего такта за калиброванный интервал времени, лучше применить
асинхронный режим работы.
Почему? Постараюсь объяснить.
Каков практический смысл “привязки” момента смены чисел, в сдвоенном регистре
TMR1H/TMR1L, к внутреннему такту (а это и есть результат синхронизации)?
Такая “привязка” имеет практический смысл только в том случае, когда необходимо
произвести гарантированно надежное чтение содержимого TMR1H/TMR1L (чтение
производится не в момент смены значения числа, а в момент его надежной
фиксации).
В этом случае, “у матросов нет вопросов”: синхронизация есть “зер гут”.
А теперь обратим внимание на конкретное устройство - ЧМ/ЦШ, и “примерим” его к
таймеру TMR1, работающему в асинхронном режиме.
В ЧМ/ЦШ, при незаблокированном внешнем такте, подсчитывается только количество
переполнений TMR1, и то, что происходит на “огроменном” (по меркам “микромира”)
интервале времени от переполнения к переполнению (вспомните про число 65536) -
“по барабану”.
В этом случае, вероятность попадания момента проверки состояния флага прерывания
по переполнению TMR1, на момент поднятия этого флага, и соответственно,
вероятность пропуска факта его поднятия (ошибки счета), исчезающе мала (практически
нулевая) даже для случаев замеров частот близких к “потолку” аппаратного
быстродействия устройства.
В добавок к этому, чтение содержимого TMR1H/TMR1L происходит только после
прерывания (блокировки) внешнего такта (фиксация уровней - надежнее некуда).
Несколько забегая вперед, скажу, что я произвел сравнительную, визуальную оценку
работы ЧМ/ЦШ с синхронизированным и несинхронизированным внешним тактом,
используя, в качестве источника внешнего такта, хорошо “прогретый” кварцевый
генератор.
В случае несинхронизированного внешнего такта (T1SYNC = 1), показания были
стабильнее, чем в случае синхронизированного внешнего такта (T1SYNC = 0).
Получается то, что синхронизатор (см. рис. 7-1 на стр. 49 даташита) вносит в работу
ЧМ/ЦШ некие “разброды и шатания”, и особенно это заметно на высоких частотах, так
как, при работе без предделителя (Кдел. = 1:1), синхронизатор, как минимум,
“подрезает” верхнюю “границу” аппаратного быстродействия по счетному входу TMR1
(существуют ограничения по времени периода внешнего такта, см. подраздел 7.2.1
даташита).
При работе без синхронизатора, то есть, в асинхронном режиме модуля TMR1, этого,
естественно, нет.
Почему в “материнском” ЧМ/ЦШ (на PIC16F84A) модуль TMR0 (не путать с TMR1), при
работе в синхронном режиме (а TMR0 и не может работать в асинхронном режиме) не
“подрезает” верхнюю границу быстродействия по счетному входу модуля TMR0?
А потому, что перед синхронизатором включен предделитель с Кдел. = 256, что
соответствует очень существенному (в 256 раз) поднятию верхней “границы”
быстродействия по счетному входу модуля TMR0 (по сравнению с работой модуля
TMR0 без предделителя).

Асинхронный режим. Чтение содержимого TMR1 и запись в него.


Так как модуль таймера TMR1 содержит в своем составе 2-байтный регистр
TMR1H/TMR1L, то считать его содержимое можно только побайтно.
Поэтому, при работе в асинхронном режиме, в случае, когда счет не может быть
остановлен, между моментами считывания этих двух байтов (считывать можно в
любом порядке), проходит время, в течение которого может произойти изменение
содержимого 2-байтного регистра TMR1H/TMR1L, в том числе и его переполнение.
Выход из этого положения заключается в применении процедуры верификации (сверки
с “эталоном”).
Сначала, в регистры временного хранения, побайтно, записываются результаты первого
(“эталонного”) считывания, а затем производится второе считывание.

4
Если результаты обеих считываний совпадают, то рабочая точка программы выходит
из группы команд считывания/верификации, а если не совпадают, то считывание и
верификация продолжаются “до победного конца” (совпадения).
Ничего мудреного в этой процедуре нет.
Пример ее программной реализации приведен на стр. 50 даташита PIC16F628A
(пример 7-1).
Правда, не смотря на то, что в регистры временного хранения записываются оба
“эталона”, в этом примере производится верификация только байта старшего разряда,
но можно самостоятельно перейти на верификацию байта младшего разряда или
сделать и то, и другое. Это совсем не сложно.
Если имеется возможность остановки счета, то считывание нужно произвести после
нее.
В этом случае, никакая верификация не нужна, и байты можно считать стандартным
способом, не опасаясь указанной выше “бяки”.
С целью недопущения аналогичной “бяки” при записи (в этом случае, “бяка” гораздо
“зловреднее”, чем при чтении), запись в регистры TMR1H и TMR1L нужно производить
только во время отсутствия счета, то есть, в то время, когда внешний такт
заблокирован.
Эта “бяка” заключается в том, что запись, производимая в момент приращения
содержимого регистра, может привести к тому, что в регистр запишется случайное
число.
При записи любого числа в регистры TMR1H и TMR1L, происходит сброс в ноль
предделителя модуля TMR1.

Особенности работы модуля TMR1 в спящем режиме (SLEEP).


1. Если модуль TMR1 работает в асинхронном режиме, то после перехода в SLEEP,
модуль TMR1 продолжает работать.
Если разрешены прерывания по переполнению TMR1, то переполнение TMR1 приведет
к выходу из режима SLEEP.
2. Если модуль TMR1 работает в синхронном режиме, то после перехода в SLEEP,
происходит фиксация (оперативное запоминание) содержимого 2-байтного регистра
TMR1H/TMR1L.
При этом, предделитель модуля TMR1 продолжает свой, в данном случае,
“бестолковый” счет.
Так как, в этом случае, переполнения TMR1 однозначно не произойдет, то выход из
режима SLEEP производится за счет других “пробудителей от спячки”.

Сбросы.
1. Содержимое двухбайтного регистра TMR1H/TMR1L сбрасывается в ноль только по
управляющему сигналу модуля CCP (будет рассмотрено при “въезде” в модуль CCP).
Сбросы (POR и т.д.) не приводят к сбросу содержимого двухбайтного регистра
TMR1H/TMR1L.
2. Содержимое управляющего регистра T1CON сбрасывается в ноль только при
сбросах POR и BOR, и не изменяется, если имеют место быть остальные виды
сброса.

Итак, “артподготовка” произведена и теперь можно “давить ослабленного противника


как немцев под Сталинградом”.
Сначала нужно осуществить перевод программы Lcd1611c.asm на тот тип ПИКа,
который имеет в своем составе модуль таймера TMR1, то есть, на PIC16F628A
(оговорено выше).
Значит, перво – наперво, нужно “перекроить шапку” программы.
Так как все познается в сравнении, то ниже опубликованы “шапки” обеих программ:
“материнской” - Lcd1611c.asm, и “дочерней” - 1611_628.asm (полные тексты этих
программ прилагаются).

5
“Шапка матери” (PIC16F84A):
;********************************************************************************
; Lcd1611c.asm ЖКИ-ЧМ/ЦШ с ЖКИ на основе HT1611/1613.
;********************************************************************************
LIST p=16F84a ; Используется микроконтроллер PIC16F84A.
__CONFIG 03FF5H ; Бит защиты выключен, WDT включен,
; стандартный генератор XT.
;********************************************************************************
; "Самоучитель по программированию PIC контроллеров для начинающих".
; http://ikarab.narod.ru karabea@lipetsk.ru
; Частота кварца 4000 кГц.
;================================================================================
; Определение положения регистров специального назначения.
;================================================================================
IndF equ 00h ;
Timer0 equ 01h ;
OptionR equ 01h ;
PC equ 02h ;
Status equ 03h ;
FSR equ 04h ;
PortA equ 05h ; Регистры спец. назначения,
TrisA equ 05h ; задействованные в программе.
PortB equ 06h ;
TrisB equ 06h ;
IntCon equ 0Bh ;

EEData equ 08h ;


EECon1 equ 08h ;
EEAdr equ 09h ;
EECon2 equ 09h ;
;================================================================================
; Определение названия и положения регистров общего назначения.
;================================================================================
KeyBuf equ 0Ch ; Буфер клавиатуры.
KeyWait equ 0Dh ; Ожидание клавиатуры.
Count equ 0Eh ; Регистр временного хранения данных.
Count1 equ 0Fh ; Еще один.
LED1 equ 010h ; Регистр хранения 2/10 чисел младшего разряда
LED2 equ 011h ; ------------------"-------------------------
LED3 equ 012h ; ------------------"-------------------------
LED4 equ 013h ; ------------------"------ старшего разряда.
Migalka equ 014H ; Регистр указателя адреса ПЧ в EEPROM-памяти.
Mode equ 015h ; Регистр режима.
Mode1 equ 016h ; Регистр хранения символа "пусто" в младшем
; полубайте при его установке в 3 позиции ЖКИ.
Temp equ 017h ; Регистр временного хранения данных.
Temp1 equ 018h ; Еще один.
Mask equ 019h ; Регистр хранения промежуточных данных
; результатов перераспределения чисел при
; преобразовании 2 - 2/10.
TimerL equ 01ah ; Регистр младшего разряда счетчика частоты.
TimerM equ 01bh ; ------- среднего ------------------------
TimerH equ 01ch ; ------- старшего ------------------------
TimerHH equ 2Fh ; ------- самого старшего -----------------
IF_L equ 01dh ; Младший байт ПЧ.
IF_M equ 01eh ; Средний байт ПЧ.
IF_H equ 01fh ; Старший байт ПЧ.
SecL equ 20h ; Младший байт счетчика времени измерения.
SecH equ 21h ; Старший байт счетчика времени измерения.
Kalib equ 22h ; Калибровочный регистр.
Kalib_1 equ 23h ; Еще один.
Mem equ 24h ; Регистр оперативной памяти клавиатуры.
Mem1 equ 25h ; Регистр оперативной памяти признаков ЧМ/ЦШ.
TRIG equ 26h ; Переключатель режимов работы ЧМ/ЦШ.
ABD equ 27h ; Счетчик времени переключения режимов работы.

6
EFG equ 28h ; Указатель кнопки переключения режимов
; работы: 0,1с./минусПЧ.
Mode2 equ 29h ; Регистр хранения символа "0" в младшем
; полубайте при его установке в 3 позиции ЖКИ.
;================================================================================
; Определение места размещения результатов операций.
;================================================================================
W equ 0 ; Результат направить в аккумулятор.
F equ 1 ; Результат направить в регистр.
;================================================================================
; Присвоение битам флагов и биту выбора банка названий.
;================================================================================
C equ 0 ; Флаг переноса-заема.
Z equ 2 ; Флаг нулевого результата.
RP0 equ 5 ; Бит выбора банка.
;================================================================================
; Распределение констант по ячейкам EEPROM-памяти.
;================================================================================
org 2100h
DE 010h,053h,0B0h ; 10.7000 мГц.
;================================================================================
org 0
goto Start
;********************************************************************************

“Шапка дочери” (PIC16F628A):


;********************************************************************************
; 1611_628.asm ЧАСТОТОМЕР - ЦИФРОВАЯ ШКАЛА с ЖКИ модулем на основе HT1611/1613.
; "Мать" - программа Lcd1611c.asm
;********************************************************************************
; Осуществлен перевод программы с PIC16F84A на PIC16F628A.
; Подпрограмма досчета "убита" (так как применен TMR1).
;********************************************************************************
; Эта программа входит в состав 6-го раздела "Практикума по конструированию
; устройств на PIC контроллерах".
; Корабельников Евгений Александрович, г.Липецк.
; http://ikarab.narod.ru karabea@lipetsk.ru
;********************************************************************************
; Частота кварца 4000 кГц.
; Объем программы: 660 команд.
;********************************************************************************
LIST p=16F628A ; Используется микроконтроллер PIC16F628A.
__CONFIG 03F25H ; Бит защиты выключен, WDT включен,
; стандартный генератор XT.
;================================================================================
; Определение положения регистров специального назначения.
;================================================================================
IndF equ 00h ;
OptionR equ 01h ;
PC equ 02h ;
Status equ 03h ;
FSR equ 04h ;
PortA equ 05h ; Регистры спец. назначения,
TrisA equ 05h ; задействованные в программе.
PortB equ 06h ;
TrisB equ 06h ;
IntCon equ 0Bh ;

EEData equ 1Ah ;


EECon1 equ 1Ch ;
EEAdr equ 1Bh ;
EECon2 equ 1Dh ;

7
CMCON equ 1Fh ; Регистр управления модулем компараторов.
PIR1 equ 0Ch ; Регистр флагов прерываний от периферийных
; модулей.
T1CON equ 10h ; Регистр управления модулем таймера TMR1.
TMR1L equ 0Eh ; Регистр младшего разряда TMR1.
TMR1H equ 0Fh ; Регистр старшего разряда TMR1.
;================================================================================
; Определение названия и положения регистров общего назначения.
;================================================================================
LED1 equ 70h ; Регистр хранения 2/10 чисел младшего разряда
LED2 equ 71h ; ------------------"-------------------------
LED3 equ 72h ; ------------------"-------------------------
LED4 equ 73h ; ------------------"------- старшего разряда.
Migalka equ 74h ; Регистр указателя адреса ПЧ в EEPROM-памяти.
Mode equ 75h ; Регистр режима.
Mode1 equ 76h ; Регистр хранения символа "пусто" в младшем
; полубайте при его установке в 3 позиции ЖКИ.
Temp equ 77h ; Регистр временного хранения данных.
Temp1 equ 78h ; Еще один.
Mask equ 79h ; Регистр хранения промежуточных данных
; результатов перераспределения чисел при
; преобразовании 2 - 2/10.
TRIG equ 7Ah ; Переключатель режимов работы ЧМ/ЦШ.
Mem equ 7Bh ; Регистр оперативной памяти клавиатуры.
Mem1 equ 7Ch ; Регистр оперативной памяти признаков ЧМ/ЦШ.
IF_L equ 7Dh ; Младший байт ПЧ.
IF_M equ 7Eh ; Средний байт ПЧ.
IF_H equ 7Fh ; Старший байт ПЧ.
SecL equ 20h ; Младший байт счетчика времени измерения.
SecH equ 21h ; Старший байт счетчика времени измерения.
Kalib equ 22h ; Калибровочный регистр.
Kalib_1 equ 23h ; Еще один.
TimerL equ 26h ; Регистр младшего разряда счетчика частоты.
TimerM equ 24h ; ------- среднего ------------------------
TimerH equ 25h ; ------- старшего ------------------------
TimerHH equ 2Fh ; ------- самого старшего -----------------
ABD equ 27h ; Счетчик времени переключения режимов работы.
EFG equ 28h ; Указатель кнопки переключения режимов
; работы: 0,1с./минусПЧ.
Mode2 equ 29h ; Регистр хранения символа "0" в младшем
; полубайте при его установке в 3 позиции ЖКИ.
KeyBuf equ 2Ch ; Буфер клавиатуры.
KeyWait equ 2Dh ; Ожидание клавиатуры.
Count equ 2Eh ; Регистр временного хранения данных.
Count1 equ 2Bh ; Еще один.
;================================================================================
; Определение места размещения результатов операций.
;================================================================================
W equ 0 ; Результат направить в аккумулятор.
F equ 1 ; Результат направить в регистр.
;================================================================================
; Присвоение битам флагов и биту выбора банка названий.
;================================================================================
C equ 0 ; Флаг переноса-заема.
Z equ 2 ; Флаг нулевого результата.
RP0 equ 5 ; Бит выбора банка.
TMR1IF equ 0 ; Флаг прерывания по переполнению TMR1.
;================================================================================
; Распределение констант по ячейкам EEPROM-памяти.
;================================================================================
org 2100h
DE 010h,053h,0B0h ; ПЧ по умолчанию 10,7000 мГц.
;================================================================================
org 0
goto Start
8
;********************************************************************************

“Боевая раскраска”:
Добавленное - выделено синим цветом.
Измененное - выделено зеленым цветом.
Удаленное - выделено красным цветом.

Регистры специального назначения.


В области оперативной памяти PIC16F628A, адреса регистров EEData, EEAdr, EECon1
и EECon2 иные, нежели в области оперативной памяти PIC16F84A.
Это и объясняет соответствующие изменения их “прописки” (см. выделенное зеленым
цветом).
Синим цветом выделена “свежая струя”.

CMCON equ 1Fh ; Регистр управления модулем компараторов.


PIR1 equ 0Ch ; Регистр флагов прерываний от периферийных
; модулей.
T1CON equ 10h ; Регистр управления модулем таймера TMR1.
TMR1L equ 0Eh ; Регистр младшего разряда TMR1.
TMR1H equ 0Fh ; Регистр старшего разряда TMR1.

Регистр CMCON нужно “прописать” для того, чтобы можно было отключить модуль
компараторов.
Регистр PIR1 нужно “прописать” для того, чтобы можно было обратиться к
задействованным в программе флагам, “лежащим” в этом регистре.
Регистры T1CON, TMR1L и TMR1H нужно “прописать” для того, чтобы можно было
работать с модулем таймера TMR1.
Так как, в программе 1611_828.asm, вместо модуля таймера TMR0 используется
модуль таймера TMR1, то “прописка” регистра TMR0 просто не нужна (“убит”).
В части касающейся регистров специального назначения, остальное - без изменений.

Регистры общего назначения.


В программе 1611_628.asm, в части касающейся количества и названий регистров
общего назначения, ничего не изменилось.
Изменилась только их адресация.
Это, опять же, обусловлено иной, нежели в PIC16F84A, “конструкцией” области
оперативной памяти.
Адресация большей части регистров изменена, то есть, “адаптирована” к области
оперативной памяти PIC16F628A.
16 регистров “переброшены” в отображаемую, во всех банках, строку области
оперативной памяти PIC16F628A (адреса с 70h по 7Fh), в том числе и регистры TPIG,
Mem и Mem1, обращение к которым происходит как из 0-го, так и из 1-го банков.
Если “прописать” эти регистры в “неотображаемой” строке области оперативной памяти
0-го банка (например, в строке с 20h до 2Fh), то те “навороты”, которые они
обслуживают, работать не будут.
С целью надежного уяснения “железобетонного” смысла сказанного (чтобы, “влетев в
одно ухо, из другого уха уже не вылетело”), желательно “протащить этот смысл” через
свои органы чувств (то есть, “заложить” информацию в подсознание), учебно –
тренировочно изменив “прописку” хотя бы одного из указанных выше регистров,
указанную в тексте программы 1611_628.asm, на “прописку” в “неотображаемой” строке
области области оперативной памяти PIC16F628A и убедившись в наличии, после
этого, большой “бяки”.
Присвоение названий битам.
Для “визуального удобства”, в “шапку” программы 1611_628.asm добавлена “прописка”
бита TMR1IF (в программе есть обращения к этому биту).
Все остальное - без изменений.

Перехожу к “рабочей” части программы.


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

1.
;================================================================================
; Косвенная адресация к регистрам, хранящим коды символов (LED1 ...LED4).
;--------------------------------------------------------------------------------
Display movlw b'00001010' ; Запись в младший полубайт кода символа "0"
movwf Mode1 ; (W --> Mode1).

movlw 70h ;(10h) ; Запись в регистр FSR


movwf FSR ; адреса регистра LED1.

2.
;--------------------------------------------------------------------------------
; Запись в FSR адреса регистра Mode1.
;--------------------------------------------------------------------------------
Prow movlw 76h ;(16h) ; Запись в регистр FSR
movwf FSR ; адреса регистра Mode1.
call displ2 ; Условный переход в ПП displ1
;----> Возврат по стеку из ПП displ2

3.
;--------------------------------------------------------------------------------
; Запись в FSR адреса регистра Mode2.
;--------------------------------------------------------------------------------
movlw 29h ;(не изменилось) ; Запись в регистр FSR
movwf FSR ; адреса регистра Mode2.
call displ2 ; Условный переход в ПП displ1
;--------------------------------------------------------------------------------
; Запись в FSR адреса регистра Mode.
;--------------------------------------------------------------------------------
;----> Возврат по стеку из ПП displ2
Pro movlw 75h ;(15h) ; Запись в регистр FSR
movwf FSR ; адреса регистра Mode.

Принцип дальнейшей работы по сравнению “вырезок” из текстов “материнской”


и “дочерней” программ, в которых имеются расхождения, - сверху вниз по
текстам программ (по порядку).
В каждой паре этих “вырезок”, сверху будет “вырезка” из текста “материнской”
программы (Lcd1611c.asm), а снизу - “вырезка” из текста “дочерней” программы
(1611_628.asm).
Кое-что (по мелочам) я оптимизировал.
4.
;--------------------------------------------------------------------------------
; Подготовительные операции. (PIC16F84A)
;--------------------------------------------------------------------------------
KeyQuery bsf Status,RP0 ; Настройка выводов Бит № 0 регистра TRIG:
movlw b'00010000' ; порта А и В. 0 - режим ЧМ,
movwf TrisA ; ------"------ 1 - режим ЦШ.
movlw b'11111111' ; ------"------
movwf TrisB ; ------"------
movlw b'00100111' ; ------"------
movwf OptionR ; TMR0 работает от внешнего такта с
bcf Status,RP0 ; приращением по переднему фронту.
; Предделитель с Кдел=256 подключен к TMR0.
; Подтягивающие резисторы подключены к выводам
; порта В.
btfsc TRIG,0 ; Если в регистре TRIG находится нечетное
goto GGG ; число: -> переход на время измерения 0,1 сек
; Если четное: -> переход к опросу клавиатуры.

10
call Inkey ; Условный переход на опрос клавиатуры.
;--------------------------------------------------------------------------------
+++++++++++++++++++++++++++++++РАЗДЕЛИТЕЛЬ++++++++++++++++++++++++++++++++
;--------------------------------------------------------------------------------
; Анализ состояния бита №0 регистра TRIG. (PIC16F628A)
;--------------------------------------------------------------------------------
KeyQuery btfsc TRIG,0 ; Если в регистре TRIG находится нечетное
goto GGG ; число: -> переход на время измерения 0,1 сек
; Если четное: -> переход к опросу клавиатуры.
call Inkey ; Условный переход на опрос клавиатуры.
;--------------------------------------------------------------------------------
Пояснения: в “материнской” программе, настройка регистров TrisA, TrisB и OptionR
происходит 2 раза: в ПП Start и в начале процедуры опроса клавиатуры.
В “дочерней” программе, я решил избавиться от этой “перестраховки” и оставил
только, “адаптированную” под PIC16F628A, настройку в ПП Start, а настройку, которая
происходит в начале процедуры опроса клавиатуры, “убил”.

5.
;--------------------------------------------------------------------------------
; Запись содержимого регистра TRIG в EEPROM. (PIC16F84A)
;--------------------------------------------------------------------------------
bcf EECon1,4 ; Запись содержимого
bcf Status,RP0 ; регистра TRIG по
movlw .48 ; адресу .48 EEPROM.
movwf EEAdr ; Необходима для
movf TRIG,W ; реализации
movwf EEData ; энергонезависимой
bsf Status,RP0 ; памяти
bsf EECon1,2 ; режимов работы ЧМ/ЦШ.
;
movlw 055h ; Обязательная
movwf EECon2 ; процедура
movlw 0AAh ; при записи.
movwf EECon2 ; ----"----
bsf EECon1,1 ; ----"----

wr5 btfss EECon1,4 ; Если запись в EEPROM не завершена


goto wr5 ; или не начата - переход в начало ПП wr5.
bcf EECon1,4 ; Если запись данных завершена - сбро-
bcf Status,RP0 ; сить флаг EEIF в регистре EECon1.
;--------------------------------------------------------------------------------
+++++++++++++++++++++++++++++++РАЗДЕЛИТЕЛЬ++++++++++++++++++++++++++++++++
;--------------------------------------------------------------------------------
; Запись содержимого регистра TRIG в EEPROM. (PIC16F628A)
;--------------------------------------------------------------------------------
bsf Status,RP0 ; Переход в 1-й банк.
movlw .48 ; Запись содержимого регистра TRIG
movwf EEAdr ; в 48-ю ячейку EEPROM.
movf TRIG,W ; Необходима для реализации энергонезависимой
movwf EEData ; памяти режимов работы ЧМ/ЦШ.
bsf EECon1,2 ; Разрешение записи.

bcf Status,RP0 ; Переход в 0-й банк.


bcf PIR1,7 ; Сброс флага прерывания по окончанию
; записи в EEPROM (EEIF).
bsf Status,RP0 ; Переход в 1-й банк.

clrf IntCon ; Запрет всех прерываний.


movlw 055h ; Обязательная
movwf EECon2 ; процедура
movlw 0AAh ; при записи.
movwf EECon2 ; ----"----
bsf EECon1,1 ; ----"----

11
bcf Status,RP0 ; Переход в 0-й банк.
we3 btfss PIR1,7 ; Флаг EEIF поднялся или нет?
goto we3 ; Нет --> еще одна проверка.
bsf Status,RP0 ; Да --> переход в 1-й банк.
bcf EECon1,2 ; Запрет записи.
bcf Status,RP0 ; Переход в 0-й банк.
;--------------------------------------------------------------------------------
Пояснения: различия в процедурах записи естественны (я о них рассказывал ранее),
так как “конструкции” областей оперативной памяти PIC16F84A и PIC16F628A
отличаются друг от друга.

6.
;--------------------------------------------------------------------------------
; (PIC16F84A)
;--------------------------------------------------------------------------------
Query bcf EECon1,4 ; Запись содержимого
bcf Status,RP0 ; регистра Mem1 по
movlw .47 ; адресу .47 EEPROM.
movwf EEAdr ; Необходима для
movf Mem1,W ; реализации
movwf EEData ; энергонезависимой
bsf Status,RP0 ; памяти
bsf EECon1,2 ; режимов работы ЦШ.
;
movlw 055h ; Обязательная
movwf EECon2 ; процедура
movlw 0AAh ; при записи.
movwf EECon2 ; ----"----
bsf EECon1,1 ; ----"----

wr4 btfss EECon1,4 ; Если запись в EEPROM не завершена


goto wr4 ; или не начата - переход в начало ПП wr4.
bcf EECon1,4 ; Если запись данных завершена - сбро-
bcf Status,RP0 ; сить флаг EEIF в регистре EECon1.
;--------------------------------------------------------------------------------
+++++++++++++++++++++++++++++++РАЗДЕЛИТЕЛЬ++++++++++++++++++++++++++++++++
;--------------------------------------------------------------------------------
; (PIC16F628A)
;-------------------------------------------------------------------------------
Query bsf Status,RP0 ; Переход в 1-й банк.
clrf IntCon ; Запрет прерываний.

movlw .47 ; Запись содержимого регистра IF_H


movwf EEAdr ; в ячейку EEPROM с адресом .47
movf Mem1,W ; -------"-------
movwf EEData ; -------"-------
bsf EECon1,2 ; Разрешение записи.

bcf Status,RP0 ; Переход в 0-й банк.


bcf PIR1,7 ; Сброс флага прерывания по окончанию
; записи в EEPROM (EEIF).
bsf Status,RP0 ; Переход в 1-й банк.

movlw 055h ; Обязательная


movwf EECon2 ; процедура
movlw 0AAh ; при записи.
movwf EECon2 ; ----"----
bsf EECon1,1 ; ----"----

bcf Status,RP0 ; Переход в 0-й банк.


wee4 btfss PIR1,7 ; Флаг EEIF поднялся или нет?
goto wee4 ; Нет --> еще одна проверка.
bsf Status,RP0 ; Да --> переход в 1-й банк.
bcf EECon1,2 ; Запрет записи.
bcf Status,RP0 ; Переход в 0-й банк.
12
;--------------------------------------------------------------------------------
Пояснения: это то же самое, что и в случае 5, только в нижней “вырезке”, команда
clrf IntCon переставлена в другое место (можно “хоть так, хоть эдак”).

7.
;********************************************************************************
; НАЧАЛО ПРОГРАММЫ ***************************************************(PIC16F84A)
;********************************************************************************
; Подготовительные операции.
;--------------------------------------------------------------------------------
Start clrwdt
clrf IntCon

bsf Status,RP0 ; Переход в 1-й банк.


movlw b'00010000' ; RA0...RA3 работают на выход,
movwf TrisA ; RA4/TOCKI работает на вход.
movlw b'11111111' ; Все выводы порта В
movwf TrisB ; работают на вход.
movlw b'00100111' ; Таймер TMR0 работает от внешнего такта
movwf OptionR ; (вывод RA4/TOCKI) с приращением по переднему
; фронту. Предделитель с Кдел=1:256 подключен
; к входу TMR0. Подтягивающие резисторы
; подключены к выводам порта В.
bcf Status,RP0 ; Переход в 0-й банк.

clrf Mode ; Сбросить в ноль регистр Mode.


clrf LED1 ; ----------"----------- LED1.
clrf LED2 ; ----------"----------- LED2.
clrf LED3 ; ----------"----------- LED3.
clrf LED4 ; ----------"----------- LED4.
clrf TimerL ; ----------"----------- TimerL.
clrf TimerM ; ----------"----------- TimerM.
clrf TimerH ; ----------"----------- TimerH.
clrf TimerHH ; ----------"----------- TimerHH.
;--------------------------------------------------------------------------------
+++++++++++++++++++++++++++++++РАЗДЕЛИТЕЛЬ++++++++++++++++++++++++++++++++
;********************************************************************************
; НАЧАЛО ПРОГРАММЫ **************************************************(PIC16F628A)
;********************************************************************************
; Подготовительные операции.
;--------------------------------------------------------------------------------
Start clrwdt ; Сброс WDT.
clrf IntCon ; Запрет всех прерываний.

movlw 7 ; Выключение модуля


movwf CMCON ; компараторов.
movlw b'00000111' ; Включение TMR1, внешний такт с вывода RB6,
movwf T1CON ; внешний такт не синхронизируется, внутренний
; тактовый генератор выключен, предделитель с
; Кдел. 1:1.
bsf Status,RP0 ; Переход в 1-й банк.
clrf TrisA ; Все выводы порта А работают на выход.
movlw b'11111111' ; Все выводы порта В
movwf TrisB ; работают на вход.
movlw b'00001111' ; Предделитель с Кдел. 1:128 подключен к
movwf OptionR ; WDT, подтягивающие резисторы включены.
bcf Status,RP0 ; Переход в 0-й банк.

clrf Mode ; Сброс в ноль содержимого регистра Mode.


clrf LED1 ; ----------"----------- LED1.
clrf LED2 ; ----------"----------- LED2.
clrf LED3 ; ----------"----------- LED3.
clrf LED4 ; ----------"----------- LED4.
clrf TimerL ; ----------"----------- TimerL.
clrf TimerM ; ----------"----------- TimerM.
13
clrf TimerH ; ----------"----------- TimerH.
clrf TimerHH ; ----------"----------- TimerHH.
;--------------------------------------------------------------------------------
Пояснения: в части касающейся нижней “вырезки”, нужно обязательно выключить
только модуль компараторов.
Остальные, не задействованные в программе, модули выключены по умолчанию.
Комментарии настройки модуля таймера TMR1 я выделил темно-синим цветом.
Сверьтесь с данными страницы 48 даташита PIC16F628A.
Как видите, программно, ничего сложного в этой настройке нет.
Нужно только четко представлять себе функции битов регистра T1CON.
Почему все выводы порта А настраиваются на работу “на выход”?
Во-первых, состояния битов регистра TrisA с №№5,6,7 не важны, так как PIC16F628A
сконфигурирован под XT генератор и работу вывода RA5 как MCLR.
По этой причине, в битах с №№5,6,7 можно выставить любой уровень.
В данном случае, все они нулевые.
Во-вторых, выводы RA0 и RA1 (такт и данные) подключены к ЖКИ модулю, и они
постоянно должны работать “на выход” (однонаправленная работа).
В-третьих, выводы RA2 и RA4 не задействуются.
В-четвертых, вывод RA3 используется как блокировочный (запрет/разрешение счета).
Вот Вам и clrf TrisA.
Для полной ясности, нужна принципиальная схема.
Вот она:

Это аналог принципиальной схемы моего ЧМ/ЦШ (опубликована на сайте: “связка”


PIC16F84A – ЖКИ HT1611/1613), только с использованием PIC16F628A, плюс, очень
простая доработка схемы .
В данном случае, блокировочным является вывод RA3 (я просто “привязался” к схеме
на PIC16F84A), но можно назначить и другой вывод порта/портов.
RA3 блокирует счетный вход модуля таймера TMR1 (вывод RB6).
При настройке этого устройства, нужно учесть следующую аппаратную особенность.
Вывод RA3 (а также и другие выводы портов) PIC16F628A, в отличие от вывода RA3
PIC16F84A, многофункционален (RA3/AN3/CMP1).
То есть, разработчики “повесили” на него еще две дополнительные функции.
Хотя, в данном случае, эти функции и отключены, но соответствующие электрические
соединения имеются, и они к чему-то, внутри ПИКа, подключены.
14
Это приводит к тому, что сопротивление вывода RA3 (относительно корпуса)
PIC16F628A, при его настройке на работу “на выход” и закрытом транзисторе
выходного каскада его защелки, меньше, чем у вывода RA3 PIC16F84A (при прочих
равных условиях), причем, настолько, что, на счетном входе модуля таймера TMR1
(RB6), амплитуда входного сигнала “режется” (RA3 и RB6 электрически соединены)
даже при закрытом транзисторе оконечного каскада защелки (разрешение счета).
При этом, работа ЧМ/ЦШ нарушается: он просто ничего не считает.
Для того чтобы устройство начало считать, нужно применить резистор R7, номинал
которого желательно подобрать (обозначено звездочкой).
На время такой “подборки”, нужно вместо R7 включить подстроечный резистор на
1 Ком., выставить в нем нулевое сопротивление, а затем постепенно повышать его до
момента появления счета (перед этим, к входу ЧМ/ЦШ нужно подключить источник
сигнала).
Затем нужно замерить получившееся сопротивление и немного “накинуть сверху”
(желательно не в разы, а то блокировка перестанет работать).
Затем подстроечный резистор удаляется и вместо него устанавливается постоянный
резистор.
На рис. 1, R7 = 1 Ком. (большой запас. Перестраховаваюсь), но желательно, чтобы этот
номинал был меньше.
После этой аппаратной “лирики”, вернусь к своим программным “котлетам”.
Все выводы порта В настраиваются на работу “на вход”.
И это должно быть понятным, так как к ним подключены кнопки (RB0 и RB1) и вывод
RB6 является счетным входом модуля таймера TMR1.
Направления работы остальных выводов не важны (не задействуются), и они, “за
компанию”, настраиваются на работу “на вход”.
От регистра OptionR требуется только включение подтягивающих резисторов (по
умолчанию, они отключены) для того чтобы обеспечить нормальное функционирование
кнопок.
Ну и “за компанию”, я подключил к WDT предделитель и выставил коэффициент его
деления равный 128 (максимальный), хотя, он может быть любым из дозволенных, и
вообще, предделитель можно отключить от WDT (подключить к TMR0).
От этого нормальная работа устройства не нарушится (сбросы происходят через
интервалы времени меньшие чем 18 мс.).

8.
;--------------------------------------------------------------------------------
; Извлечение из EEPROM информации о режиме работы (ЧМ/ЦШ) до последнего
; выключения питания. (PIC16F84A)
;--------------------------------------------------------------------------------
bcf EECon1,2 ; Чтение из EEPROM
movlw .48 ; и копирование
movwf EEAdr ; извлеченных
bsf Status,RP0 ; данных в
bsf EECon1,0 ; регистр TRIG.
bcf Status,RP0 ; -----"-----
movf EEData,W ; -----"-----
movwf TRIG ; -----"-----
;--------------------------------------------------------------------------------
; Извлечение из EEPROM информации о режиме работы ЦШ ("плюс ПЧ"/"минус ПЧ")
; до последнего выключения питания.
;--------------------------------------------------------------------------------
bcf EECon1,2 ; Чтение из EEPROM
movlw .47 ; и копирование
movwf EEAdr ; прочитанных
bsf Status,RP0 ; данных в
bsf EECon1,0 ; регистр Mem1.
bcf Status,RP0 ; -----"-----
movf EEData,W ; -----"-----
movwf Mem1 ; -----"-----
;--------------------------------------------------------------------------------
+++++++++++++++++++++++++++++++РАЗДЕЛИТЕЛЬ++++++++++++++++++++++++++++++++

15
;--------------------------------------------------------------------------------
; Извлечение из EEPROM информации о режиме работы (ЧМ/ЦШ) до последнего
; выключения питания. (PIC16F628A)
;--------------------------------------------------------------------------------
bsf Status,RP0 ; Переход в 1-й банк.
bcf EECon1,2 ; Запрет записи в EEPROM.

movlw .48 ; Копирование данных


movwf EEAdr ; из ячейки EEPROM
bsf EECon1,0 ; с адресом .48
movf EEData,W ; в регистр W.
movwf TRIG ; Копирование данных из регистра W
; в регистр TRIG.
;--------------------------------------------------------------------------------
; Извлечение из EEPROM информации о режиме работы ЦШ ("плюс ПЧ"/"минус ПЧ")
; до последнего выключения питания.
;--------------------------------------------------------------------------------
bcf EECon1,2 ; Запрет записи в EEPROM.

movlw .47 ; Копирование данных


movwf EEAdr ; из ячейки EEPROM
bsf EECon1,0 ; с адресом .47
movf EEData,W ; в регистр W.
movwf Mem1 ; Копирование данных из регистра W
; в регистр Mem1.
; Переход в 0-й банк происходит не здесь, а через одну команду.
;--------------------------------------------------------------------------------
Пояснения: при чтении из EEPROM, так же, как и при записи в EEPROM,
программные различия обусловлены разными “конструкциями” областей оперативной
памяти PIC16F84A и PIC16F628A.
Обращаю Ваше внимание на то, что, в программе 1611_628.asm, регистры TRIG и
Mem1 “прописаны” в “отображаемой” строке области оперативной памяти и поэтому с
ними можно работать в любом банке.

9.
;--------------------------------------------------------------------------------
; Чтение из EEPROM значения ПЧ и запись их в (PIC16F84A)
; регистры IF_H, IF_M, IF_L.
;--------------------------------------------------------------------------------
bcf EECon1,2 ; Запрет записи.

movlw 0 ; Копирование данных,


movwf EEAdr ; находящихся по
bsf Status,RP0 ; адресу 00h EEPROM
bsf EECon1,0 ; в регистр IF_H.
bcf Status,RP0 ; ------"------
movf EEData,W ; ------"------
movwf IF_H ; ------"------
;--------------------------------------------------------------------------------
movlw 1 ; Копирование данных,
movwf EEAdr ; находящихся по
bsf Status,RP0 ; адресу 01h EEPROM
bsf EECon1,0 ; в регистр IF_M.
bcf Status,RP0 ; ------"------
movf EEData,W ; ------"------
movwf IF_M ; ------"------
;--------------------------------------------------------------------------------
movlw 2 ; Копирование данных,
movwf EEAdr ; находящихся по
bsf Status,RP0 ; адресу 02h EEPROM
bsf EECon1,0 ; в регистр IF_L.
bcf Status,RP0 ; ------"------
movf EEData,W ; ------"------
movwf IF_L ; ------"------

16
;--------------------------------------------------------------------------------
+++++++++++++++++++++++++++++++РАЗДЕЛИТЕЛЬ++++++++++++++++++++++++++++++++
;--------------------------------------------------------------------------------
; Копирование из EEPROM в регистры IF_H, IF_M, IF_L значения ПЧ. (PIC16F628A)
;--------------------------------------------------------------------------------
bsf Status,RP0 ; Переход в 1-й банк.
movlw 0 ; Копирование данных
movwf EEAdr ; из ячейки EEPROM
bsf EECon1,0 ; с адресом .00
movf EEData,W ; в регистр W.
movwf IF_H ; Копирование данных из регистра W
; в регистр IF_H.
;--------------------------------------------------------------------------------
movlw 1 ; Копирование данных
movwf EEAdr ; из ячейки EEPROM
bsf EECon1,0 ; с адресом .01
movf EEData,W ; в регистр W.
movwf IF_M ; Копирование данных из регистра W
; в регистр IF_M.
;--------------------------------------------------------------------------------
movlw 2 ; Копирование данных
movwf EEAdr ; из ячейки EEPROM
bsf EECon1,0 ; с адресом .02
movf EEData,W ; в регистр W.
movwf IF_L ; Копирование данных из регистра W
; в регистр IF_L.
bcf Status,RP0 ; Переход в 0-й банк.
;--------------------------------------------------------------------------------
Пояснения: в нижней “вырезке”, команды bcf EECon1,2 (запрет записи) нет потому, что
запрет записи был произведен ранее (зачем подтверждать ранее установленное
состояние?).
В остальном, пункт 9 аналогичен пункту 8.

10.
;--------------------------------------------------------------------------------
; Подготовка к началу измерения. (PIC16F84A)
;--------------------------------------------------------------------------------
;---> Возврат по стеку из ПП displ1
clrf IntCon ; Сброс бита переполнения TMR0,
; запрет всех прерываний.
clrf TimerL ; Сброс байтов счетчика частоты.
clrf TimerM ; --------"--------
clrf TimerH ; --------"--------
clrf TimerHH ; --------"--------
clrf Timer0 ; Сброс TMR0 и предделителя.
; TMR0 готов к заполнению.
movlw .164 ; Запись количества циклов измерения
movwf Temp1 ; в регистр Temp1.
;================================================================================
+++++++++++++++++++++++++++++++РАЗДЕЛИТЕЛЬ++++++++++++++++++++++++++++++++
;--------------------------------------------------------------------------------
; Подготовка к началу измерения. (PIC16F628A)
;--------------------------------------------------------------------------------
;---> Возврат по стеку из ПП displ1
clrf IntCon ; Сброс бита переполнения TMR0,
; запрет всех прерываний.
clrf TimerL ; Сброс байтов счетчика частоты.
clrf TimerM ; --------"--------
clrf TimerH ; --------"--------
clrf TimerHH ; --------"--------

clrf TMR1L ; Сброс в 0


clrf TMR1H ; регистров TMR1.

17
movlw .164 ; Запись количества циклов измерения
movwf Temp1 ; в регистр Temp1.
;================================================================================
Пояснения: на мой взгляд, пояснений не требуется.

11.
;================================================================================
; Начало цикла измерения. (PIC16F84A)
;================================================================================
bsf Status,RP0 ; Переход в 1-й банк.
movlw b'00011000' ;
On movwf TrisA ; RA4/TOCKI и RA3 <--- точка начала измерения
; работают на вход, остальные - на выход.
; Вход TMR0 RA4/TOCKI разблокируется
; и он готов считать.
bcf Status,RP0 ; Переход в 0-й банк.
;================================================================================
; Цикл измерения.
;================================================================================
; Проверка TMR0 на переполнение №1(заполнение старшего байта счетчика частоты
; TimerH и, в случае его переполнения, - регистра переполнения TimerHH).
;--------------------------------------------------------------------------------
Cycle btfss IntCon,2 ; Переполнение TMR0 есть ?
goto DoNothing ; Нет --> переход в ПП DoNoting.
movf TimerH,W ; Есть --> в TimerH, до его инкремента,
; число .255 ?
sublw .255 ; TimerH - .255 = ?
btfsc Status,Z ;

goto DoNot_1 ; Да, это число .255 --> переход в ПП DoNot_1.


incf TimerH,F ; Нет, это не число .255 --> инкремент TimerH
bcf IntCon,2 ; без инкремента TimerHH.
nop ;
nop ;
nop ;
goto O_K ; Переход в ПП O_K.

DoNot_1 incf TimerH,F ; Инкременты TimerH


incf TimerHH,F ; и TimerHH.
bcf IntCon,2 ;
nop ;
goto O_K ; Переход в ПП O_K.
;--------------------------------------------------------------------------------
; Задержка, обеспечивающая равенство временных интервалов заполнения счетчика
; частоты, в случаях: "TMR0 переполнен" - "TMR0 не переполнен".
;--------------------------------------------------------------------------------
DoNothing nop ; Нет операции:
nop ; "пустые" машинные
nop ; циклы (задержка).
nop ; --------"--------
nop ; --------"--------
nop ; --------"--------
nop ; --------"--------
nop ; --------"--------
nop ; --------"--------
nop ; --------"--------
;--------------------------------------------------------------------------------
; Формирование времени одного цикла измерения.
;--------------------------------------------------------------------------------
O_K movlw .200 ; Запись времязадающей константы
movwf Temp ; в регистр Temp.

Pause decfsz Temp,F ; Формирование времени одного


goto Pause ; цикла измерения.

18
clrwdt
;--------------------------------------------------------------------------------
; Переход на следующий цикл измерения.
;--------------------------------------------------------------------------------
Sec decfsz SecL,F
goto Cycle

incfsz SecH,F
goto Sec
;--------------------------------------------------------------------------------
; Окончательное формирование времени измерения частоты ("доводка" до 0,1-1-10
сек.).
;--------------------------------------------------------------------------------
EndPause nop ;
decfsz Kalib,F ; Декремент содержимого регистра
goto EndPause ; Kalib до его очищения.

EndPau_1 decfsz Kalib_1,F ; Декремент содержимого регистра


goto EndPau_1 ; Kalib_1 до его очищения.
nop ;
;--------------------------------------------------------------------------------
; Подготовка к окончанию счета.
;--------------------------------------------------------------------------------
Nx clrf PortA ; Сброс всех защелок порта А.
;--------------------------------------------------------------------------------
; Окончание счета.
;--------------------------------------------------------------------------------
bsf Status,RP0 ; Переход в 1-й банк.
movlw b'00010000' ; RA4/TOCKI работает на вход, остальные – на
; выход.
Off movwf TrisA ; RA3 блокирует вход TMR0 <---завершение счета
bcf Status,RP0 ; Переход в 0-й банк.
;================================================================================
; Формирование содержимого регистров счетчика частоты TimerH,TimerM,TimerL.
;================================================================================
; Проверка TMR0 на переполнение №2
; (коррекция содержимого регистра TimerH и TimerHH).
;--------------------------------------------------------------------------------
btfss IntCon,2 ; Если с момента последней проверки TMR0 на
goto Analyse ; переполнение №1 и до окончания счета
movf TimerH,W ; произошло переполнение TMR0, содержимое
; TimerH увеличивается на 1.
; Если до инкремента TimerH, его содержимое
sublw .255 ; равнялось .255, то, после его инкремента,
btfsc Status,Z ; оно станет = 0, а содержимое TimerHH
goto Nx_1 ; увеличится на 1 (аналогия с проверкой TMR0
; на переполнение №1).
incf TimerH,F ; -------------"--------------
bcf IntCon,2 ; -------------"--------------
goto Analyse ; -------------"--------------
Nx_1 incf TimerH,F ; -------------"--------------
incf TimerHH,F ; -------------"--------------
bcf IntCon,2 ; -------------"--------------
goto Analyse ; -------------"--------------
;--------------------------------------------------------------------------------
; Загрузка данными регистра TimerM, подготовка к загрузке данными
; регистра TimerL.
;--------------------------------------------------------------------------------
Analyse movf Timer0,W ; Содержимое регистра TMR0
movwf TimerM ; копируется в регистр TimerM.

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


;--------------------------------------------------------------------------------
; Загрузка данными регистра TimerL.
;--------------------------------------------------------------------------------
CountIt incf TimerL,F ; Инкремент содержимого регистра TimerL.
19
bsf PortA,3 ; Формирование счетного импульса.
nop ; -------------"-------------
bcf PortA,3 ; -------------"-------------
nop ; -------------"-------------
movf Timer0,W ; Копирование содержимого регистра TMR0 в W.
subwf TimerM,W ; Вычитание из содержимого регистра TimerM
; содержимого регистра W.
btfsc Status,Z ; Результат операции вычитания равен
; или нет нулю?
goto CountIt ; Да, равен --> переход в ПП CountIt.
incf TimerL,F ; Нет, не равен --> инкремент содержимого
; регистра TimerL.
comf TimerL,F ; Инверсия всех битов регистра TimerL.
incf TimerL,F ; Инкремент содержимого регистра TimerL.
incf TimerL,F ; -------------"--------------
;--------------------------------------------------------------------------------
; Регистры TimerH,TimerM,TimerL заполнены результатами измерения.
;--------------------------------------------------------------------------------
goto KeyQuery ; Переход на опрос клавиатуры.
;--------------------------------------------------------------------------------
+++++++++++++++++++++++++++++++РАЗДЕЛИТЕЛЬ++++++++++++++++++++++++++++++++
;================================================================================
; Начало цикла измерения. (PIC16F628A)
;================================================================================
bsf Status,RP0 ; Переход в 1-й банк.
movlw b'00001000' ; Разблокировка счетного входа
On movlw TrisA ; <--- НАЧАЛО СЧЕТА.
bcf Status,RP0 ; Переход в 0-й банк.
;================================================================================
; Цикл измерения.
;================================================================================
; Проверка TMR1 на переполнение №1 (заполнение регистра
; TimerH и в случае его переполнения - регистра TimerHH).
;--------------------------------------------------------------------------------
Cycle btfss PIR1,TMR1IF ; Переполнение TMR1 есть или нет?
goto DoNothing ; Нет --> переход в ПП DoNoting.
movf TimerH,W ; Есть --> в TimerH, до его инкремента,
; число .255 ?
sublw .255 ; TimerH - .255 = ?
btfsc Status,Z ; Проверка флага Z.
goto DoNot_1 ; Да, это число .255 --> переход в ПП DoNot_1.
incf TimerH,F ; Нет, это не число .255 --> инкремент TimerH
; без инкремента TimerHH.
bcf PIR1,TMR1IF ; Сброс флага TMR1IF.
nop ; ----"----
nop ; Выравнивание.
nop ; ----"----
goto O_K ; Переход в ПП O_K.
DoNot_1 incf TimerH,F ; Инкременты TimerH
incf TimerHH,F ; и TimerHH.
bcf PIR1,TMR1IF ; Сброс флага TMR1IF.
nop ; Выравнивание.
goto O_K ; Переход в ПП O_K.
;--------------------------------------------------------------------------------
; Задержка, обеспечивающая равенство временных интервалов заполнения счетчика
; частоты, в случаях: "TMR1 переполнен" - "TMR1 не переполнен".
;--------------------------------------------------------------------------------
DoNothing nop ; --------"--------
nop ; --------"--------
nop ; --------"--------
nop ; --------"--------
nop ; Выравнивание.
nop ; --------"--------
nop ; --------"--------
nop ; --------"--------

20
nop ; --------"--------
nop ; --------"--------
;--------------------------------------------------------------------------------
; Формирование времени одного цикла измерения.
;--------------------------------------------------------------------------------
O_K movlw .200 ; Запись времязадающей константы
movwf Temp ; в регистр Temp.
Pause decfsz Temp,F ; Формирование времени одного
goto Pause ; цикла измерения.
clrwdt ; Сброс WDT.
;--------------------------------------------------------------------------------
; Переход на следующий цикл измерения.
;--------------------------------------------------------------------------------
Sec decfsz SecL,F ; Если содержимое SecH/SecL не равно 0,
goto Cycle ; то переход на следующий цикл
incfsz SecH,F ; измерения.
goto Sec ; Если =0, то программа исполняется далее.
;--------------------------------------------------------------------------------
; Окончательное формирование времени измерения частоты
; ("доводка" до 0,1-1-10 сек.).
;--------------------------------------------------------------------------------
EndPause nop ; Калибровочный NOP.
decfsz Kalib,F ; Декремент содержимого регистра
goto EndPause ; Kalib до его очищения.
EndPau_1 decfsz Kalib_1,F ; Декремент содержимого регистра
goto EndPau_1 ; Kalib_1 до его очищения.
nop ; Калибровочный NOP.
;--------------------------------------------------------------------------------
; Подготовка к окончанию счета.
;--------------------------------------------------------------------------------
clrf PortA ; Сброс всех защелок порта А.
;--------------------------------------------------------------------------------
; Окончание счета.
;--------------------------------------------------------------------------------
bsf Status,RP0 ; Переход в 1-й банк.
movlw b'00000000'
Off movwf TrisA
bcf Status,RP0 ; Переход в 0-й банк.
;================================================================================
; Формирование содержимого регистров счетчика частоты TimerH,TimerM,TimerL.
;================================================================================
; Проверка TMR1 на переполнение №2
; (коррекция содержимого регистра TimerH и TimerHH).
;--------------------------------------------------------------------------------
btfss PIR1,TMR1IF ; Если с момента последней проверки TMR1 на
goto Analyse ; переполнение №1 и до окончания счета
movf TimerH,W ; произошло переполнение TMR1, то содержимое
; TimerH увеличивается на 1.
; Если до инкремента TimerH, его содержимое
sublw .255 ; равнялось .255, то, после его инкремента,
btfsc Status,Z ; оно станет = 0, а содержимое TimerHH
goto Nx_1 ; увеличится на 1 (аналогия с проверкой TMR1
incf TimerH,F ; на переполнение №1).
bcf PIR1,TMR1IF ; -------------"--------------
goto Analyse ; -------------"--------------
Nx_1 incf TimerH,F ; -------------"--------------
incf TimerHH,F ; -------------"--------------
bcf PIR1,TMR1IF ; -------------"--------------
goto Analyse ; -------------"--------------
;--------------------------------------------------------------------------------
; Загрузка данными регистра TimerM и TimerL.
;--------------------------------------------------------------------------------
Analyse movf TMR1H,W ; В TimerM переписывается
movwf TimerM ; число из TMR1H.
movf TMR1L,W ; В TimerL переписывается
movwf TimerL ; число из TMR1L.
21
;--------------------------------------------------------------------------------
; Регистры TimerHH, TimerH,TimerM,TimerL заполнены результатами измерения.
;--------------------------------------------------------------------------------
goto KeyQuery ; Переход на опрос клавиатуры.
;--------------------------------------------------------------------------------
Пояснения: сначала об изменениях (выделены зеленым цветом).
Вывод RA4/TOCKI в программе 1611_628.asm не используется.
Его функции перешли к выводу RB6.
Этим и объясняется различие числовых значений констант, записываемых в регистр
TrisA в начале и в конце цикла счета (см. On и Off).
Вообще-то, эти числовые значения можно было бы и не изменять (RA4/TOCKI в
программе 1611_628.asm не используется), но я их изменил для обеспечения “порядка”
(чтобы единица в бите №4 с толка не сбивала).
В обеих процедурах проверок на переполнение (№1 и №2), все команды btfss IntCon,2
просто заменены на команды btfss PIR1,TMR1IF.
Так как, при задействовании модуля таймера TMR1, досчет не нужен, то все, что с
ним (а также и с регистром TMR0) связано, “убито” (см. выделение красным цветом),
а вместо всего этого “хозяйства”, использована простая процедура последовательной
“переправки” содержимого регистров TimerM и TimerL в регистры TMR1H и TMR1L
соответственно (см. выделение синим цветом).
Обращаю Ваше внимание на то, что эта “переправка” производится после окончания
счета и поэтому никакой верификации не нужно.
Изменились ли, после такого вмешательства в цикл счета, величины калиброванных
интервалов времени?
Не в коем разе, так как команды в этот цикл не добавлялись и не удалялись, а
произведена только замена “рабочих частей” соответствующих команд, что на время их
исполнения никак не влияет.
Вывод: коррекции величин интервалов времени измерения не требуется (“зер гут”).
На всякий случай, проверено. Так и есть.

12.
;--------------------------------------------------------------------------------
; Запись в EEPROM. (PIC16F84A)
;--------------------------------------------------------------------------------
WrtMem movlw 0 ; Запись в W нуля.
movwf IntCon ; Запрет прерываний.

movwf EEAdr ; Содержимое регистра IF_H


movf IF_H,W ; записывается в EEPROM
movwf EEData ; в ячейку с адресом 00h.
bsf Status,RP0 ; ----------"----------
bsf EECon1,2 ; ----------"----------

movlw 055h ; Обязательная после-


movwf EECon2 ; довательность при
movlw 0AAh ; записи.
movwf EECon2 ; ----------"----------
bsf EECon1,1 ; ----------"----------

wr1 btfss EECon1,4 ; Проверка: запись


goto wr1 ; закончена или
bcf EECon1,4 ; нет?
bcf Status,RP0 ; Переход в 0-й банк.
;--------------------------------------------------------------------------------
movlw 1
movwf EEAdr ; Содержимое регистра IF_M
movf IF_M,W ; записывается в EEPROM
movwf EEData ; в ячейку с адресом 01h.
bsf Status,RP0 ; ----------"----------
bsf EECon1,2 ; ----------"----------

movlw 055h ; Обязательная после-


movwf EECon2 ; довательность при
22
movlw 0AAh ; записи.
movwf EECon2 ; ----------"----------
bsf EECon1,1 ; ----------"----------

wr2 btfss EECon1,4 ; Проверка: запись


goto wr2 ; закончена или
bcf EECon1,4 ; нет?
bcf Status,RP0 ; Переход в 0-й банк.
;--------------------------------------------------------------------------------
movlw 2
movwf EEAdr ; Содержимое регистра IF_L
movf IF_L,W ; записывается в EEPROM
movwf EEData ; в ячейку с адресом 02h.
bsf Status,RP0 ; ----------"----------
bsf EECon1,2 ; ----------"----------

movlw 055h ; Обязательная после-


movwf EECon2 ; довательность при
movlw 0AAh ; записи.
movwf EECon2 ; ----------"----------
bsf EECon1,1 ; ----------"----------

wr3 btfss EECon1,4 ; Проверка: запись


goto wr3 ; закончена или
bcf EECon1,4 ; нет?
bcf Status,RP0 ; Переход в 0-й банк.
;--------------------------------------------------------------------------------
+++++++++++++++++++++++++++++++РАЗДЕЛИТЕЛЬ++++++++++++++++++++++++++++++++
;--------------------------------------------------------------------------------
; Запись в EEPROM. (PIC16F628A)
;--------------------------------------------------------------------------------
WrtMem bsf Status,RP0 ; Переход в 1-й банк.
clrf IntCon ; Запрет прерываний.

movlw 0 ; Запись содержимого регистра IF_H


movwf EEAdr ; в ячейку EEPROM с адресом .00
movf IF_H,W ; -------"-------
movwf EEData ; -------"-------
bsf EECon1,2 ; Разрешение записи.

bcf Status,RP0 ; Переход в 0-й банк.


bcf PIR1,7 ; Подготовка к записи в EEPROM.
bsf Status,RP0 ; Переход в 1-й банк.

movlw 055h ; Обязательная


movwf EECon2 ; процедура
movlw 0AAh ; при записи.
movwf EECon2 ; ----"----
bsf EECon1,1 ; ----"----

bcf Status,RP0 ; Переход в 0-й банк.


wee1 btfss PIR1,7 ; Запись завершена или нет?
goto wee1 ; Если нет, то ждем.
bsf Status,RP0 ; Если да, то переход в 1-й банк.
bcf EECon1,2 ; Запрет записи.
;--------------------------------------------------------------------------------
movlw 1 ; Запись содержимого регистра IF_M
movwf EEAdr ; в ячейку EEPROM с адресом .01
movf IF_M,W ; -------"-------
movwf EEData ; -------"-------
bsf EECon1,2 ; -------"-------

bcf Status,RP0 ; -------"-------


bcf PIR1,7 ; -------"-------
bsf Status,RP0 ; -------"-------

23
movlw 055h ; -------"-------
movwf EECon2 ; -------"-------
movlw 0AAh ; -------"-------
movwf EECon2 ; -------"-------
bsf EECon1,1 ; -------"-------

bcf Status,RP0 ; -------"-------


wee2 btfss PIR1,7 ; -------"-------
goto wee2 ; -------"-------
bsf Status,RP0 ; -------"-------
bcf EECon1,2 ; -------"-------
;--------------------------------------------------------------------------------
movlw 2 ; Запись содержимого регистра IF_L
movwf EEAdr ; в ячейку EEPROM с адресом .02
movf IF_L,W ; -------"-------
movwf EEData ; -------"-------
bsf EECon1,2 ; -------"-------

bcf Status,RP0 ; -------"-------


bcf PIR1,7 ; -------"-------
bsf Status,RP0 ; -------"-------

movlw 055h ; -------"-------


movwf EECon2 ; -------"-------
movlw 0AAh ; -------"-------
movwf EECon2 ; -------"-------
bsf EECon1,1 ; -------"-------

bcf Status,RP0 ; -------"-------


wee3 btfss PIR1,7 ; -------"-------
goto wee3 ; -------"-------
bsf Status,RP0 ; -------"-------
bcf EECon1,2 ; -------"-------
bcf Status,RP0 ; Переход в 0-й банк.
;--------------------------------------------------------------------------------
Пояснения: это тоже самое, что и в случае 6, но только применительно к потоковой
записи в EEPROM.

Общее пояснение: программа 1611_628.asm является рабочей (проверена в “железе”).


В связи с моими “наполеоновскими” планами и “морем” информации, которую нужно
“перелопатить”, “возиться” с этим устройством мне просто недосуг.
Буду благодарен, если кто-то из Вас как следует “погоняет” эту “железяку” в работе,
выяснит ее недостатки (если они есть) и напишет мне о них.
Кстати, этот ЧМ/ЦШ очень экономичен (ЖКИ модуль потребляет микроамперы) и его
смело можно “сажать” на батарейное питание.

Если разобраться, то ничего особо сложного, в сказанном выше, нет.


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

24
А теперь давайте трезво помечтаем, ведь именно с этого и начинается любая
эффективная работа.
Вопрос: “Можно ли в программе 1611_828.asm организовать второй счет”?
А почему бы и нельзя, ведь вывод RA4/TOCKI свободен “как ветер в поле”, да и с
наличием блокировочного вывода нет проблем.
Предделитель можно без проблем “перебросить” с WDT на TMR0.
Что еще нужно “для полного счастья”?
Только “шевеление извилиной” и “ваяние в поте лица”.
Что это дает?
А это дает то, что можно обрабатывать не один, а два внешних сигнала, причем, как
раздельно, так и с вычислением их суммы, разницы, кратности частот и т.д.
Если “включить буйную фантазию”, то на этой “базе” можно понапридумать много
всякого.
Фантазия?
Безусловно.
Но эта фантазия абсолютно реальна.
“Подкидываю” Вам эту идею с умыслом: мозги не должны “киснуть”.
Мы же из породы “гомо сапиенсов”, да еще и русскоговорящих!
С моей точки зрения, это большой плюс.
Мозги должны использоваться по своему прямому назначению.
Вот и используйте. “Семь футов под килем”.
А я “пошел терзать” следующий модуль.

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

25
26