Код: Выделить всё
T1 equ .212 ; задержка 1
T2 equ .2
TP equ .200 ; определяет задержку между приемом посылок
Tn equ .50 ; начальная задержка (ближе к середине полубита)
Sys equ .253 ; номер системы (29) + 2SB=1 + TB=1
CMD_1 equ .1 ; код команды 1
CMD_2 equ .2 ; код команды 2
CMD_3 equ .3 ; код команды 3
CMD_4 equ .4 ; код команды 4
Директива equ - это сокращение от слова equivalent, она сообщает компилятору, что везде в тексте программы нужно заменить буквенные обозначения на соответствующее число. Точка перед числом - признак десятичной системы исчисления. То есть если компилятор встретит, например, запись movlw T1, то поймёт её так: movlw .212 и будет знать, что речь идёт о загрузке в регистр w числа 212.
Что это значит? "Определяет задержку".
Задержку можно организовать двумя способами: 1) Позаниматься нужное время чем-то бесполезным. Для этого в пиках даже есть специальная команда - nop, которая ничего не делает. Если нужно подольше - пишут несколько таких команд, если ещё больше, то организуют так называемые "пустые циклы" - когда контроллер занимается тем, что в цикле выполняет нужное количество таких команд (или даже просто весь цикл занимается тем, что изменяет значение счётчика и проверяет - не пора ли уже заканчивать с этим циклом). 2) Использовать таймер. Тут можно пока таймер работает позаниматься чем-то полезным или "поспать" (если железо позволяет просыпаться от таймера), а потом от таймера приходит прерывание и мы понимаем, что наша задержка закончилась.
В проге реализован первый способ (как самый простой) и числа T1, TP, Tn определяют сколько раз нужно в цикле выполнять nop.
Регистры у нас 8-ми битные, со счётчиком на таком регистре можно сделать максимум 255 циклов задержки. А что делать, если этого мало? А тогда можно сделать вложенный цикл (когда внутри одного цикла есть ещё один цикл), вот как здесь:
Код: Выделить всё
wait movlw T2
movwf Counter2
pause2 movlw T1 <---
movwf Counter1 |
pause1 nop <--- |
decfsz Counter1,1 | |
goto pause1 --- |
decfsz Counter2,1 |
goto pause2 ---
return
Внешний цикл со счётчиком в регистре Counter2 определяет сколько раз нужно выполнить внутренний цикл со счётчиком Counter1 (сами циклы выше стрелочками показаны). Команды movlw T2, movwf Counter2 записывают в регистр Counter2 число 2 (регистр Counter2 - это счётчик для внешнего цикла), команды decfsz Counter2,1, goto pause2 уменьшают значение счётчика на единицу и если оно не стало равным нулю, - выполняется переход на метку pause2 и цикл повторяется.
Как посчитать, - сколько на всё это затрачивается времени? Тут всё просто. Нужно посчитать за сколько тактов выполнятся все эти циклы и умножить на время выполнения одного такта. Время выполнения одного такта определяется тактовой частотой: T=1/f и для 4МГц составляет 0,25 мкс. В доке на контроллер (там, где описание команд) написано сколько тактов затрачивается на выполнение каждой команды (для пиков написано не количество тактов, а количество машинных циклов, 1 машинный цикл равен 4-м тактам).
Можно проще. В MPLab, во вкладке Windows есть пункт Stopwatch. Запускаешь пошаговое выполнение программы (F8), устанавливаешь указатель команд на метку Wait (Debug->Run->Change Program Counter), ресетишь Stopwatch, ставишь Breakpoint на команду return (правой кнопкой) и запускаешь выполнение (F9). Прога будет выполняться от метки Wait до того места, где установлен Breakpoint, а в окошке stopwatch посчитается сколько на это уйдёт времени и машинных циклов. Прибавишь к этому время выполнения команд Call и return - узнаешь общее время задержки.
не понимаю что за компаратор и что значит поднять 0..2 биты?
Поднять - значит записать туда единицу. Бит может быть либо нулём, либо единицей. Когда говорят "поднять бит" (или флаг, который обычно и является битом в каком-нибудь регистре), то это означает, что надо сделать этот бит равным единице. Когда говорят "сбросить бит" - значит его нужно сделать равным нулю. Теперь про компараторы. В контроллере обычно есть куча всякой периферии (всяких встроенных устройств), а выводов (то есть ножек) мало, и можно специальными флагами подключать к выводам ту или иную периферию, в зависимости от этого у ножек будут те или иные функции. При загрузке у нашего контроллера в регистре CMCON биты 0..2 сброшены, для контроллера это означает, что ноги GP0, GP1, GP2 подключены ко встроенным компараторам и используются как аналоговые входы этих компараторов. А если биты 0..2 в регистре CMCON поднять, то контроллер отключит от выводов компараторы и будет использовать эти ноги как цифровые входы/выходы (как входы или как выходы определяется битами в регистре TrisIO).
Вот тут почему старт бит 7 по счёту и почему проверяем 5 бит?
Если нога настроена на вход, то при чтении GPIO в пятом бите будет значение на входе GP5. GP5 - это у нас вход, к которому подключен фотоприёмник. Фотоприёмник у нас сигнал инвертирует. То есть когда он ничего не принимает - у него на выходе высокий уровень, то есть на входе контроллера висит 1. Когда он принимает импульсы на несущей частоте - у него на выходе низкий уровень, на входе контроллера получается ноль. Вот мы и проверяем эту ногу, пока она в ноль не упадёт. Как упала - значит появился старт-бит. Седьмым по счёту он окажется потому что мы так сигнал принимаем. Мы принимаем бит, сдвигаем все биты в приёмном регистре влево и потом младшим битом записываем этот принятый бит. Приняв таким образом в регистр 8 бит, самый первый принятый окажется самым старшим (то есть седьмым, биты же с нуля считаются).