Материал из EPIRB Wiki
Перейти к: навигация, поиск
(→‎Версия прошивки 3.2, цикл 30с/120с; 60с/60с; 1м/4м)
(→‎Версия прошивки 3.1, циклы 30с/120с; 60с/60с; 1м/4м)
 
(не показано 9 промежуточных версии этого же участника)
Строка 2: Строка 2:
  
 
[[File:Pic_beacon.jpg|300px|thumb|none|Контроллер маяка на PIC16F630]]
 
[[File:Pic_beacon.jpg|300px|thumb|none|Контроллер маяка на PIC16F630]]
−
 
−
[[File:Pic_beacon_1.jpg|300px|thumb|none|Контроллер маяка на PIC16F630 в корпусе]]
 
  
 
[[File:Key3_amo.gif|299px|thumb|none|Переключатель для управления маяком]]
 
[[File:Key3_amo.gif|299px|thumb|none|Переключатель для управления маяком]]
Строка 10: Строка 8:
  
 
===Версия прошивки 3.0, циклы 30с/30с; 60с/60с; 1м/4м===
 
===Версия прошивки 3.0, циклы 30с/30с; 60с/60с; 1м/4м===
 +
 +
[[file:Mf3.HEX.zip]]
 +
 
<pre>
 
<pre>
  
Строка 640: Строка 641:
  
 
===Версия прошивки 3.1, циклы 30с/120с; 60с/60с; 1м/4м===
 
===Версия прошивки 3.1, циклы 30с/120с; 60с/60с; 1м/4м===
 +
 +
[[file:Mf31.HEX.zip]]
  
 
<pre>
 
<pre>
Строка 1910: Строка 1913:
 
</pre>
 
</pre>
  
 +
===Вариант для управления радиостанцией, 30с/120с; 60с/60с; 1м/4м, передача позывного===
  
 +
[[File:Pic_beacon_1.jpg|300px|thumb|none|Контроллер маяка на PIC16F630 в корпусе]]
  
−
Cntrl_spb_amw.gif
+
[[File:Cntrl_spb_amw.gif|697px|thumb|none|Схема для управления маяком для городской охоты, возможно подключение обычной радиостанции]]
 +
 
 +
<pre>
 +
; на 11 ногу можно повесить управление TX (высокий уровень при передаче)
 +
 
 +
; PIC16F630
 +
; WDT off, intLC, MCLR on, BOR on, PWRTE on
 +
;
 +
list P=16F630
 +
radix HEX
 +
 
 +
;====================================================================
 +
; именование пользовательских регистров
 +
;
 +
CBLOCK 0X20 ; начальный адрес пользовательских регистров
 +
        TMPW ; временный регистр для хранения W во время прерывания
 +
TMPS ; временный регистр для хранения STATUS                                                   
 +
SEC_CNT ; счетчик пар секунд
 +
MIN_CNT ; счетчик минут (пятиминуток, автовыключение)
 +
FLAG ; регистр флагов:
 +
; FLAG,0 разрешает передачу позывного в свое время
 +
; FLAG,2 флаг задержки включения (1-можно работать)
 +
                        ; FLAG,3 флаг взводится через 5 мин после начала работы
 +
; и отменяет задержку включения при сбросе
 +
; FLAG,4 флаг устанавливается за 10 сек до конца цикла
 +
 
 +
 
 +
DELAY ; счетчик пятиминуток, задержка включения
 +
TX_ALL_CNT ; счетчик пар секунд в цикле
 +
TX_OFF ; с какой секунды пауза
 +
TX_ALL ; сколько пар секунд в цикле
 +
 
 +
SWITCH ; состояние переключателя
 +
CHAR_INDEX ; номер передаваемого символа
 +
 
 +
CW_SPEED ; скорость передачи
 +
 
 +
; процедура SEND_TONE
 +
NBR_DIT ; NBR_DIT кол-во пропускаемых точек
 +
CTR_NBR ; счетчик пропускаемых точек
 +
TONE ; счетчик частоты
 +
SET_TONE ; установка тона передаваемого сигнала
 +
; процедура SEND_SPACE
 +
NBR_SPACE ; колво пропускаемых точек
 +
CTR_DIT ; счетчик пропускаемых точек
 +
; процедура SEND_ONE_CHAR
 +
CW_CHAR ; передаваемый символ
 +
ENDC
 +
 
 +
 
 +
;
 +
; Именование регистров микроконтроллера
 +
;
 +
CMCON EQU 0X19 ; регистр контроля компаратора
 +
TMR0 EQU 0X01 ; timer0
 +
TMR1L EQU 0X0E ; timer1 младший байт
 +
TMR1H EQU 0X0F ; timer1 старший байт   
 +
T1CON EQU 0X10 ; timer1 control register
 +
PCL EQU 0X02 ; программный счетчик
 +
STATUS EQU 0X03 ; регистр status
 +
FSR EQU 0X04 ; указатель адреса в памяти данных
 +
PORTA EQU 0X05 ; порт A
 +
PORTC EQU 0X07 ; порт C
 +
PCLATH EQU 0X0A ; верхние 5 бит программного счетчика
 +
INTCON EQU 0X0B ; регистр контроля прерываний
 +
TRISA EQU 0X85 ; управляющий регистр порта A
 +
TRISC EQU 0X87 ; управляющий регистр порта C
 +
OPTION_REG EQU 0X81 ; регистр option
 +
EEADR EQU 0X9B ; адресный регистр EEPROM
 +
EECON1 EQU 0X9C ; содержит бит RD
 +
EEDAT EQU 0X9A ; прочитанные из EEPROM данные
 +
PCON EQU 0X8E ; регистр power control
 +
PIE1 EQU 0X8C ; регистр контроля периферийных прерываний
 +
PIR1 EQU 0X0C ; регистр флагов прерываний от
 +
; периферийных модулей
 +
 
 +
;
 +
; присвоение значений символьным константам
 +
;
 +
RP0 EQU 0X05 ; бит-указатель страницы данных в STATUS
 +
W EQU 0X00 ; file register designator = W
 +
F EQU 0X01 ; file register designator = F
 +
Z EQU 0X02 ; бит нуля в STATUS
 +
C EQU 0X00 ; бит преноса в STATUS
 +
RD EQU 0X00 ; инициализация чтения EEPROM
 +
POR EQU 0X01 ; бит POR регистра PCON обнуляется, если был
 +
; сброс по включению питания
 +
BOR EQU 0X00 ; сброс по снижению питания
 +
TMR1IF EQU 0X00 ; бит переполнения TMR1 in register PIR1
 +
TMR1ON EQU 0X00 ;
 +
GIE EQU 0X07 ;
 +
TMR1IE EQU 0X00 ; бит разрешения прерываний от TMR1
 +
PON EQU 0X00 ; POWER ON IN FLAG
 +
;
 +
;=================================================================
 +
; vector table
 +
;
 +
ORG 0X000 ; стартовый адрес
 +
GOTO START ;
 +
 
 +
;==================================================================
 +
; TIMER1 INTERRUPT
 +
;
 +
ORG 0X004 ; адрес прерывания
 +
MOVWF TMPW ; сохраняем W
 +
SWAPF STATUS,W
 +
MOVWF TMPS ; сохраняем STATUS
 +
 +
BTFSC PIR1,0 ; прерывание от TMR1?
 +
GOTO T1_INT ; да
 +
        NOP ; обработчик левого прерывания
 +
GOTO END_ISR ;
 +
 
 +
T1_INT
 +
MOVF TX_ALL_CNT,W ; вычитание
 +
SUBWF TX_OFF,W ; TX_OFF-TX_ALL_CNT
 +
 +
BCF FLAG,0 ;
 +
SKPC ; пропустить, если результат >=0
 +
BSF FLAG,0 ;
 +
 
 +
 
 +
 +
 
 +
 
 +
 
 +
 
 +
 
 +
; MOVF TX_ALL_CNT,W ; ускоряемся за 10 сек до конца цикла
 +
; SUBLW D'125' ; ставим флаг, по которому во время передачи
 +
; SKPNZ ; меняем скорость
 +
; BSF FLAG,4 ; только при 5 мин цикле
 +
 
 +
; использовать либо верхнее, либо нижнее
 +
 
 +
;SUBLW D'250' ; а это костыль для ускорения за 10 сек
 +
;SKPNZ ; до конца любого цикла, даже если
 +
;BSF FLAG,4 ; работаем непрерывно
 +
 
 +
DECFSZ TX_ALL_CNT,F ; TX_ALL_CNT-1, пропустить, если 0
 +
GOTO POP_TX
 +
MOVF TX_ALL,W ; восстанавливаем
 +
MOVWF TX_ALL_CNT ;
 +
 
 +
; BCF FLAG,4 ; в конце цикла сбросить флаг ускорения
 +
POP_TX
 +
 
 +
      DECFSZ SEC_CNT, F ; SEC_CNT-1
 +
GOTO POP ;
 +
MOVLW D'150' ; 300 секунд = 5 мин
 +
MOVWF SEC_CNT
 +
 +
BTFSS FLAG,2 ; если задержка активирована, то
 +
BSF FLAG,3 ; через 5 мин после запуска поднимаем флаг
 +
; отмены задержки включения
 +
 
 +
BTFSC FLAG,2 ; если флаг разрешения работы установлен, начинаем отсчет
 +
; задержки отключения
 +
DECF MIN_CNT,F ; MIN_CNT-1 минуты работы считаем после
 +
; окончании задержки включения
 +
 
 +
 
 +
DECFSZ DELAY,F ; DELAY-1, пропустить след, если 0
 +
GOTO POP ; задержка окончилась
 +
BSF FLAG,2 ; устанавливаем флаг разрешения работы
 +
 
 +
 
 +
POP
 +
BCF PIR1,0 ; сброс флага переполнения
 +
 
 +
END_ISR
 +
SWAPF TMPS,W ; восстанавливаем регистры W and SATUS
 +
MOVWF STATUS ;
 +
SWAPF TMPW,F ;
 +
SWAPF TMPW,W ;
 +
RETFIE ; возврат из прерывания
 +
 
 +
;==================================================================
 +
;  Начало основной программы
 +
;==================================================================
 +
START
 +
MOVLW B'10001110'      ;
 +
BSF STATUS, RP0 ; bank 1
 +
MOVWF OPTION_REG ; инициализация регистра option
 +
BCF STATUS, RP0 ; bank 0
 +
 +
CLRF PORTA ; очистка порта A
 +
CLRF PORTC ; очистка порта C
 +
 
 +
MOVLW B'00000111' ;
 +
MOVWF CMCON ; запрещаем работу компаратора
 +
 
 +
BSF STATUS, RP0 ; bank 1
 +
MOVLW B'00000000' ;
 +
MOVWF TRISA ; порт A - все выходы
 +
MOVLW B'11111111' ;
 +
MOVWF TRISC ; порт C - все входы
 +
BCF STATUS, RP0 ; bank 0
 +
 
 +
CLRF TMR0 ; на всякий случай. Говорят, надо...
 +
CLRWDT ; сбрасываем WDT
 +
 
 +
 
 +
;==================================================================
 +
; инициализация TMR1
 +
;
 +
CLRF T1CON ; очистить TIMER1 control register
 +
CLRF TMR1H ; очистить верхний байт TMR1
 +
CLRF TMR1L ; очистить нижний байт TMR1
 +
CLRF INTCON ; запретить прерывания
 +
BSF STATUS,RP0 ; bank 1
 +
CLRF PIE1 ; очистить рег контроля периферийных прерываний
 +
BCF STATUS, RP0 ; bank 0
 +
CLRF PIR1 ; очистить рег флагов периферийных прерываний
 +
MOVLW B'00001110' ; инициализация TIMER1 control register
 +
MOVWF T1CON ; с этого момента генератор 32.768 включен
 +
 
 +
 
 +
;==================================================================
 +
 
 +
MOVLW D'150' ; инициализация счетчика пар секунд
 +
MOVWF SEC_CNT ; 150 пар = 300 сек = 5 мин
 +
        DECF SEC_CNT,F ; имитируем прерывание
 +
 
 +
;MOVLW D'2' ; сколько пятиминуток будем работать
 +
MOVLW D'96' ; сколько пятиминуток будем работать
 +
MOVWF MIN_CNT ; 96х5=8 час
 +
 
 +
; MOVLW D'2' ; сколько пятиминуток задержка включения
 +
MOVLW D'24' ; сколько пятиминуток задержка включения
 +
MOVWF DELAY ; 24х5=120 мин
 +
 
 +
MOVLW D'178' ; тон звука, 178 ~ 1000 Гц
 +
MOVWF SET_TONE ; чем больше, тем ниже частота
 +
 
 +
BSF FLAG,0 ; поднимаем флаг
 +
 
 +
; BCF FLAG,4
 +
 
 +
 
 +
;==================================================================
 +
; если это включение питания, то выполняется задержка для
 +
; гарантированного запуска генератора 32768 и его инициализация
 +
; если другой сброс, то инициализация и задержка пропускаются
 +
;
 +
BSF STATUS, RP0 ; bank 1
 +
MOVF PCON,W ; PCON -> W
 +
BCF STATUS, RP0 ; bank 0
 +
 
 +
MOVWF TMPW ; W -> TMPW
 +
BTFSS TMPW,POR ; проверяем состояние POR, если 0, то был сброс
 +
GOTO DELAY_START ; по включению - задержка однозначно нужна
 +
BTFSC TMPW,BOR          ; а это был сброс по снижению напр питания
 +
        GOTO SKIP_DELAY        ; или не был...
 +
 +
DELAY_START
 +
 
 +
BCF FLAG,3 ; при первом включении очистить FLAG,3
 +
 
 +
; задержка
 +
MOVLW D'255' ; скорость передачи
 +
MOVWF CW_SPEED ; чем больше, тем медленней
 +
 +
MOVLW 0X80
 +
MOVWF CW_CHAR ;
 +
        CALL SEND_ONE_CHAR ; в качестве задержки предаем 7 точек
 +
 
 +
BSF STATUS, RP0 ; bank 1
 +
BSF PCON,POR ; устанавливаем POR=1
 +
BSF PCON,BOR ; устанавливаем BOR=1
 +
BCF STATUS, RP0 ; bank 0
 +
 
 +
SLEEP ; ожидаем запуск
 +
 
 +
SKIP_DELAY
 +
 
 +
 
 +
;==================================================================
 +
; читаем переключатель
 +
;
 +
 
 +
BSF PORTA,2 ; на 11 ноге висят подтягивающие резисторы,
 +
; подключенные к переключателю
 +
; после считывания напряжение с переключателя
 +
; снимается для экономии энергии
 +
 
 +
 
 +
        MOVF PORTC,W ; читаем порт C
 +
ANDLW B'00011100' ; маска
 +
MOVWF SWITCH ; сохраняем состояние переключателя
 +
 
 +
        MOVF PORTC,W ; читаем порт C
 +
ANDLW B'00000011' ; маска двух младших бит
 +
 
 +
BCF FLAG,2 ; обнуляем флаг задержки
 +
BTFSC PORTC,5 ; если перекл. on (на землю, 0) пропуск. след.
 +
BSF FLAG,2 ; устанавливаем флаг, можно работать
 +
 
 +
BCF PORTA,2 ; отключаем подтягивающие резисторы
 +
 
 +
ADDWF PCL,F ; таблица
 +
GOTO SW00
 +
GOTO SW01
 +
GOTO SW10
 +
GOTO SW11
 +
SW00 ; непрерывно
 +
MOVLW D'0' ; молчим последние 0 с
 +
MOVWF TX_OFF ;
 +
MOVLW D'30' ; цикл 60 сек
 +
GOTO END_SW
 +
SW01 ; цикл 30сек/120сек
 +
MOVLW D'60' ; молчим последние 120 с
 +
MOVWF TX_OFF ;
 +
MOVLW D'75' ; цикл 150 сек
 +
GOTO END_SW
 +
SW10 ; цикл 1 мин/1 мин
 +
MOVLW D'30' ; молчим последние 60 с
 +
MOVWF TX_OFF ;
 +
MOVLW D'60' ; цикл 120 сек
 +
GOTO END_SW
 +
SW11 ; цикл 1 мин/4 мин
 +
MOVLW D'120' ; молчим последние 4 m
 +
MOVWF TX_OFF ;
 +
MOVLW D'150' ; цикл 5 m
 +
 
 +
END_SW
 +
MOVWF TX_ALL ;
 +
MOVWF TX_ALL_CNT ; инициализация
 +
        DECF TX_ALL_CNT,F ; считаем, что 1 прерывание уже случилось
 +
 
 +
;==================================================================
 +
; Окончание инициализации TIMER1
 +
;
 +
 
 +
MOVLW B'11000000' ; разрешить прерывания от периферийных модулей
 +
MOVWF INTCON
 +
 
 +
BSF STATUS,RP0 ; bank 1
 +
BSF PIE1,TMR1IE ; разрешить прерывания от TMR1
 +
BCF STATUS, RP0 ; bank 0
 +
BSF T1CON,TMR1ON        ; TMR1 ON
 +
 
 +
 
 +
;==================================================================
 +
; Если с момента запуска прошло 5 мин, то при сбросе задержку
 +
; включения игнорируем
 +
 
 +
BTFSC FLAG,3 ; FLAG,3 поднимается через 5 м после начала
 +
; работы
 +
BSF FLAG,2 ; задержка включения не нужна
 +
 
 +
;==================================================================
 +
; MAIN
 +
; передача последовательности символов
 +
; можно предавать любое количество, 0XFF означает конец последовательности,
 +
; после чего формируется пауза и передача циклически повторяется
 +
;
 +
SEND_MSG
 +
                                ; если автоотключение не нужно, то три
 +
; нижеследующих строчки надо закомментировать
 +
MOVF MIN_CNT,F ; проверяем, не обнулился ли
 +
SKPNZ ; счетчик пятиминуток
 +
GOTO POWER_OFF ; если да, то выключаемся
 +
 
 +
BTFSS FLAG,2 ; пропустить след, если задержка включения
 +
; кончилась (1-разрешение работы)
 +
GOTO FLASH ; мигнуть и sleep
 +
 
 +
        BTFSS FLAG,0 ; если флаг сброшен
 +
BSF PORTA,2 ; TX выключаем
 +
 
 +
        BTFSS FLAG,0 ; если флаг сброшен, то идем спать
 +
GOTO TO_SLEEP
 +
 +
 
 +
BSF PORTA,2 ; на 11 ногу можно повесить управление TX
 +
 
 +
 
 +
MOVF SWITCH,W
 +
MOVWF CHAR_INDEX ; SWITCH -> CHAR_INDEX
 +
 
 +
GET_MSG
 +
MOVF CHAR_INDEX,W
 +
BCF INTCON,GIE ; запрещаем прерывания
 +
BSF STATUS, RP0 ; bank 1
 +
MOVWF EEADR ; значение CHAR_INDEX = адресу кода в EEPROM
 +
BSF EECON1,RD ; разрешаем чтение EEPROM
 +
MOVF EEDAT,W ; значение ячейки -> регистр W
 +
BCF STATUS, RP0 ; bank 0
 +
BSF INTCON,GIE ; разрешаем прерывания
 +
;MOVLW 0x06
 +
MOVWF CW_CHAR ; W -> CW_CHAR
 +
 
 +
MOVLW 0XFF ; конец сообщения?
 +
SUBWF CW_CHAR,W ;
 +
SKPNZ
 +
GOTO END_MSG ; да, перейти к END_MSG
 +
 
 +
; MOVLW D'60' ; скорость передачи быстро
 +
; BTFSS FLAG,4 ; устанавливается за 10 с до конца цикла
 +
;
 +
MOVLW D'80' ; скорость передачи медленно
 +
MOVWF CW_SPEED ; чем больше, тем медленней
 +
 
 +
CALL SEND_CHAR ; передаем букву и паузу в 3 точки
 +
                                ; или паузу 6 точек, если SPACE
 +
INCF CHAR_INDEX ; CHAR_INDEX+1
 +
GOTO GET_MSG
 +
 
 +
END_MSG
 +
CALL WORD_SPACE        ; пауза 6 точек
 +
GOTO SEND_MSG ;
 +
 
 +
; время работы закончилось
 +
POWER_OFF ; отсюда выход только через RESET
 +
 
 +
CLRF FLAG ; очистка регистра флагов
 +
CLRF T1CON ; очистить TIMER1 control register, выключаем
 +
; генератор 32768
 +
;BCF T1CON,TMR1ON      ; TMR1 OFF
 +
CLRF INTCON ; запретить прерывания
 +
 
 +
; после сброса считаем, что это сброс по питанию
 +
BSF STATUS, RP0 ; bank 1
 +
BCF PCON,POR ; устанавливаем POR=0
 +
BCF PCON,BOR ; устанавливаем BOR=0
 +
BCF STATUS, RP0 ; bank 0
 +
 
 +
TO_SLEEP ;
 +
CLRF PORTA
 +
SLEEP
 +
NOP
 +
GOTO SEND_MSG
 +
;========================================================================
 +
; индикатор включенной задержки
 +
; мигаем порт A.1
 +
FLASH
 +
MOVLW D'60' ; скорость передачи
 +
MOVWF CW_SPEED ; чем больше, тем медленней
 +
BSF PORTA,1
 +
MOVLW 0X01 ;
 +
MOVWF NBR_SPACE ; пауза в 1 точку
 +
CALL SEND_SPACE ;
 +
BCF PORTA,1
 +
GOTO TO_SLEEP
 +
;========================================================================
 +
; SEND_CHAR
 +
; Подпрограмма получает код символа в регистре CW_CHAR, побитно перебирает
 +
; его, и, в зависимости от состояния бита, передает: тире, если бит = 1;
 +
; точку, если бит = 0.
 +
; Знак передается, пока в слове есть хоть одна единица. Последняя единица
 +
; "съедается", она означает конец слова.
 +
;
 +
SEND_CHAR
 +
MOVLW 0X00 ; пауза?
 +
SUBWF CW_CHAR,W ;
 +
SKPNZ ;
 +
GOTO WORD_SPACE
 +
 
 +
SEND_ONE_CHAR
 +
        BTFSS FLAG,0 ; обрываем передачу, если флаг сброшен
 +
RETURN
 +
 
 +
CLRC ; очистить бит переноса
 +
RRF CW_CHAR, F ; сдвиг вправо через перенос
 +
;
 +
MOVF CW_CHAR, F        ; проверяем содержимое CW_CHAR, если все "0"
 +
SKPNZ                  ; то Z=1, выполняем RETURN, иначе пропускаем
 +
GOTO PAUSE2 ; конец буквы
 +
SKPC ; проверить бит переноса, пропустить, если=1
 +
GOTO SEND_A_DIT ; перейти к SEND_A_DIT
 +
 
 +
SEND_A_DAH ; передаем тире
 +
MOVLW 0X03 ; 1 тире = 3 точки
 +
MOVWF NBR_DIT
 +
MOVLW 0X01 ;
 +
MOVWF NBR_SPACE ; после тире - пауза в 1 точку
 +
BSF PORTA,0 ; включаем PORT A.2
 +
CALL SEND_TONE ; генериуем звук, оно же - пауза
 +
BCF PORTA,0 ; выключаем PORT A.2
 +
CALL SEND_SPACE
 +
GOTO SEND_ONE_CHAR
 +
 
 +
SEND_A_DIT
 +
MOVLW 0X01 ; передаем точку
 +
MOVWF NBR_DIT
 +
MOVWF NBR_SPACE ; после точки - пауза в 1 точку
 +
BSF PORTA,0 ; включаем PORT A.2
 +
CALL SEND_TONE          ; генерируем звук, оно же - пауза
 +
BCF PORTA,0 ; выключаем PORT A.2
 +
CALL SEND_SPACE
 +
GOTO SEND_ONE_CHAR
 +
 
 +
PAUSE2
 +
MOVLW D'2' ; пауза в 2 точки после буквы
 +
MOVWF NBR_SPACE ;
 +
CALL SEND_SPACE        ;
 +
RETURN
 +
 
 +
WORD_SPACE
 +
MOVLW D'6' ; пауза в 6 точек между словами
 +
MOVWF NBR_SPACE ;
 +
CALL SEND_SPACE        ;
 +
RETURN
 +
 
 +
;==================================================================
 +
; SEND_TONE
 +
; Подпрограмма осуществляет задержку и одновременно формирует сигнал
 +
; звуковой частоты (порт A.1)
 +
;
 +
 
 +
SEND_TONE
 +
 +
MOVF NBR_DIT, W ; NBR_DIT кол-во пропускаемых точек
 +
MOVWF CTR_NBR ;
 +
 
 +
DIT_LENGTH
 +
MOVF CW_SPEED, W ; CW_SPEED скорость передачи
 +
MOVWF CTR_DIT ;
 +
 
 +
START_CYCLE
 +
BSF PORTA,1 ; A.1=1 в начале цикла
 +
MOVF SET_TONE,W ;
 +
MOVWF TONE ; заносим значение в счетчик цикла задержки
 +
 
 +
HIGH_HALF
 +
DECFSZ TONE, F ; считаем до нуля
 +
GOTO HIGH_HALF
 +
BCF PORTA,1 ; A.1=0 в конце цикла
 +
 
 +
MOVF SET_TONE,W ;
 +
MOVWF TONE
 +
 
 +
LOW_HALF
 +
DECFSZ TONE, F ;
 +
GOTO LOW_HALF
 +
DECFSZ CTR_DIT, F ;
 +
GOTO START_CYCLE
 +
DECFSZ CTR_NBR, F
 +
GOTO DIT_LENGTH ;
 +
RETURN ;
 +
 
 +
;================================================================
 +
; SEND_SPACE
 +
; Делает тоже самое, что и SEND_TONE, только вместо команд управления
 +
; портами стоит команда NOP
 +
;
 +
 
 +
SEND_SPACE
 +
 +
MOVF NBR_SPACE, W ;
 +
MOVWF CTR_NBR
 +
 
 +
DIT_LENGTH_SP
 +
MOVF CW_SPEED, W ;
 +
MOVWF CTR_DIT
 +
 
 +
START_CYCLE_SP
 +
NOP
 +
MOVF SET_TONE,W
 +
MOVWF TONE ;
 +
 
 +
HIGH_HALF_SP
 +
DECFSZ TONE, F ;
 +
GOTO HIGH_HALF_SP
 +
NOP
 +
MOVF SET_TONE,W
 +
MOVWF TONE
 +
 
 +
LOW_HALF_SP
 +
DECFSZ TONE, F ;
 +
GOTO LOW_HALF_SP
 +
DECFSZ CTR_DIT, F ;
 +
GOTO START_CYCLE_SP
 +
DECFSZ CTR_NBR, F
 +
GOTO DIT_LENGTH_SP ;
 +
RETURN ;
 +
 
 +
;==================================================================
 +
;==================================================================
 +
; Идентификатор
 +
ORG  0x2000 ; стартовый адрес
 +
 
 +
        DATA 0x0132
 +
        DATA 0xF321
 +
        DATA 0x0000
 +
        DATA 0x0000
 +
 
 +
;==================================================================
 +
; Слово конфигурации
 +
ORG  0x2007 ; стартовый адрес
 +
 
 +
; DATA 0x31E4
 +
DATA 0x1024 ; вкл защиту данных
 +
; DATA 0x11A4
 +
;==================================================================
 +
; Запись в EEPROM при программировании
 +
; Переключателем адресуется номер ячейки, кратный 4. Соответственно, маяк
 +
; может передавать последовательно три символа Морзе, четвертым обязательно
 +
; должен быть EOM
 +
; В последнюю адресуемую ячейку можно записать большее количество символов
 +
 
 +
ORG  0X2100 ; стартовый адрес
 +
 
 +
DATA 0x07 ; M --    00000111
 +
DATA 0x0F ; O ---  00001111
 +
        DATA 0xFF ; EOM    11111111
 +
        DATA 0xFF ; EOM    11111111
 +
 
 +
DATA 0x07 ; M --    00000111
 +
DATA 0x0F ; O ---  00001111
 +
        DATA 0x02 ; E .    00000010 
 +
        DATA 0xFF ; EOM    11111111
 +
 
 +
DATA 0x07 ; M --    00000111
 +
DATA 0x0F ; O ---  00001111
 +
DATA 0x04 ; I ..    00000100
 +
        DATA 0xFF ; EOM    11111111
 +
 
 +
DATA 0x07 ; M --    00000111
 +
DATA 0x0F ; O ---  00001111
 +
DATA 0x08 ; S ...  00001000
 +
        DATA 0xFF ; EOM    11111111
 +
 
 +
DATA 0x07 ; M --    00000111
 +
DATA 0x0F ; O ---  00001111
 +
DATA 0x10 ; H ....  00010000
 +
        DATA 0xFF ; EOM    11111111
 +
 
 +
DATA 0x07 ; M --    00000111
 +
DATA 0x0F ; O ---  00001111
 +
DATA 0x20 ; 5 ..... 00100000
 +
        DATA 0xFF ; EOM    11111111
 +
 
 +
DATA 0x07 ; M --    00000111
 +
DATA 0x0F ; O ---  00001111
 +
DATA 0x03 ; T -    00000011
 +
        DATA 0xFF ; EOM    11111111
 +
 
 +
DATA 0x09 ; D
 +
DATA 0x02 ; E
 +
DATA 0x00 ; PAUSE
 +
DATA 0x0A ; R .-. 
 +
        DATA 0x06 ; A .-
 +
        DATA 0x3E ; 1 .----
 +
        DATA 0x06 ; A .-
 +
        DATA 0x07 ; M --
 +
        DATA 0x0E ; W ---
 +
DATA 0x00 ; PAUSE
 +
DATA 0x11 ; B
 +
DATA 0x02 ; E
 +
DATA 0x06 ; A
 +
DATA 0x15 ; C
 +
DATA 0x0F ; O ---  00001111
 +
DATA 0x05 ; N
 +
        DATA 0xFF ; EOM    11111111
 +
 
 +
END
 +
</pre>
 +
 
 +
===Программирование кодов Морзе===
 +
 
 +
<pre>
 +
DATA 0x3F ; 0 ----- 00111111
 +
DATA 0x3E ; 1 .---- 00111110 
 +
DATA 0x3C ; 2 ..--- 00111100
 +
DATA 0x38 ; 3 ...-- 00111000
 +
DATA 0x30 ; 4 ....- 00110000
 +
DATA 0x20 ; 5 ..... 00100000
 +
DATA 0x21 ; 6 -.... 00100001
 +
DATA 0x23 ; 7 --... 00100011
 +
DATA 0x27 ; 8 ---.. 00100111
 +
DATA 0x2F ; 9 ----. 00101111
 +
 
 +
DATA 0x06 ; A .-    00000110
 +
DATA 0x11 ; B -...  00010001
 +
DATA 0x15 ; C -.-.  00010101
 +
DATA 0x09 ; D -..  00001001
 +
DATA 0x02 ; E .    00000010
 +
DATA 0X14 ; F ..-.  00010100
 +
DATA 0X0B ; G --.  00001011
 +
DATA 0x10 ; H ....  00010000
 +
DATA 0x04 ; I ..    00000100
 +
DATA 0x1E ; J .---  00011110
 +
DATA 0x0D ; K -.-  00001101
 +
DATA 0x12 ; L .-..  00010010
 +
DATA 0x07 ; M --    00000111
 +
DATA 0x05 ; N -.    00000101
 +
DATA 0x0F ; O ---  00001111
 +
DATA 0x16 ; P .--.  00010110
 +
DATA 0x1B ; Q --.-  00011011
 +
DATA 0x0A ; R .-.  00001010
 +
DATA 0x08 ; S ...  00001000
 +
DATA 0x03 ; T -    00000011
 +
DATA 0x0C ; U ..-  00001100
 +
DATA 0x18 ; V ...-  00011000
 +
DATA 0x0E ; W .--  00001110
 +
DATA 0X19 ; X -..-  00011001
 +
DATA 0X1D ; Y -.--  00011101
 +
DATA 0X13 ; Z --..  00010011
 +
DATA 0x29 ; / -..-. 00101001
 +
DATA 0x00 ; PAUSE  00000000
 +
DATA 0xFF ; EOM    11111111
 +
</pre>

Текущая версия на 12:57, 25 марта 2017

Контроллер маяка на PIC16F630

Контроллер маяка на PIC16F630
Переключатель для управления маяком
Схема контроллера

Версия прошивки 3.0, циклы 30с/30с; 60с/60с; 1м/4м

Файл:Mf3.HEX.zip


;-Передает в режиме лисы код Морзе (MO, MOE, MOI, MOS, MOH, MO5, MOT, T). Вариант кода задается переключателем.
;-Может работать непрерывно или циклом: 30с/30с; 60с/60с; 1м/4м.
;-Есть выход 1000 Гц для модуляции маяка на 144 МГц.
;-Автоотключение через 8 часов.
;-Потребление в выключенном состоянии 0.08 ма, во время работы, при передаче позывного, 0.5 ма.
;-Уход часов определяется кварцем.
;-Код с переключателя считывается один раз после сброса.
;-Режим отложенного старта (ОС), задержка 120 минут
;-Ускорение передачи позывного за 10 сек до конца цикла (только для 5 мин цикла)
;-Питание от 3 до 5 вольт 
;
; PIC16F630
; WDT off, intLC, MCLR on, BOR on, PWRTE on
;
	list	P=16F630
	radix	HEX

;====================================================================
; именование пользовательских регистров
;	
 	CBLOCK	0X20	; начальный адрес пользовательских регистров
        TMPW		; временный регистр для хранения W во время прерывания
	TMPS		; временный регистр для хранения STATUS                                                    
	SEC_CNT		; счетчик пар секунд
	MIN_CNT 	; счетчик минут (пятиминуток, автовыключение)
	FLAG		; регистр флагов:
			; FLAG,0 разрешает передачу позывного в свое время
			; FLAG,2 флаг задержки включения (1-можно работать)
                        ; FLAG,3 флаг взводится через 5 мин после начала работы
			; и отменяет задержку включения при сбросе
			; FLAG,4 флаг устанавливается за 10 сек до конца цикла


	DELAY		; счетчик пятиминуток, задержка включения
	TX_ALL_CNT	; счетчик пар секунд в цикле
	TX_OFF		; с какой секунды пауза
	TX_ALL		; сколько пар секунд в цикле

	SWITCH		; состояние переключателя
	CHAR_INDEX	; номер передаваемого символа

	CW_SPEED	; скорость передачи

; процедура SEND_TONE
	NBR_DIT		; NBR_DIT кол-во пропускаемых точек
	CTR_NBR		; счетчик пропускаемых точек
	TONE		; счетчик частоты
	SET_TONE	; установка тона передаваемого сигнала
; процедура SEND_SPACE
	NBR_SPACE	; колво пропускаемых точек
	CTR_DIT		; счетчик пропускаемых точек
; процедура SEND_ONE_CHAR
	CW_CHAR		; передаваемый символ
	ENDC


;
; Именование регистров микроконтроллера
;
CMCON		EQU	0X19	; регистр контроля компаратора
TMR0		EQU	0X01	; timer0
TMR1L		EQU	0X0E	; timer1 младший байт
TMR1H		EQU	0X0F	; timer1 старший байт     
T1CON		EQU	0X10	; timer1 control register
PCL		EQU	0X02	; программный счетчик
STATUS		EQU	0X03	; регистр status
FSR		EQU	0X04	; указатель адреса в памяти данных
PORTA		EQU	0X05	; порт A
PORTC		EQU	0X07	; порт C
PCLATH		EQU	0X0A	; верхние 5 бит программного счетчика
INTCON		EQU	0X0B	; регистр контроля прерываний
TRISA		EQU	0X85	; управляющий регистр порта A
TRISC		EQU	0X87	; управляющий регистр порта C 
OPTION_REG	EQU	0X81	; регистр option
EEADR		EQU	0X9B	; адресный регистр EEPROM
EECON1		EQU	0X9C	; содержит бит RD
EEDAT		EQU	0X9A	; прочитанные из EEPROM данные
PCON		EQU	0X8E	; регистр power control
PIE1		EQU	0X8C	; регистр контроля периферийных прерываний
PIR1		EQU	0X0C	; регистр флагов прерываний от 
				; периферийных модулей

;
; присвоение значений символьным константам
;
RP0		EQU	0X05	; бит-указатель страницы данных в STATUS
W		EQU	0X00	; file register designator = W
F		EQU	0X01	; file register designator = F 
Z		EQU	0X02	; бит нуля в STATUS 
C		EQU	0X00	; бит преноса в STATUS
RD		EQU	0X00	; инициализация чтения EEPROM
POR		EQU	0X01	; бит POR регистра PCON обнуляется, если был
				; сброс по включению питания
BOR		EQU	0X00	; сброс по снижению питания
TMR1IF		EQU	0X00	; бит переполнения TMR1 in register PIR1
TMR1ON		EQU	0X00	;
GIE		EQU	0X07	;
TMR1IE		EQU	0X00	; бит разрешения прерываний от TMR1
PON		EQU	0X00	; POWER ON IN FLAG
;
;=================================================================
; vector table
;
	ORG 0X000		; стартовый адрес	
	GOTO START		; 

;==================================================================
; TIMER1 INTERRUPT 
;
	ORG 0X004		; адрес	прерывания
	MOVWF TMPW		; сохраняем W
	SWAPF STATUS,W
	MOVWF TMPS		; сохраняем STATUS
	
	BTFSC PIR1,0		; прерывание от TMR1?
	GOTO T1_INT		; да
        NOP			; обработчик левого прерывания
	GOTO END_ISR		; 

T1_INT
	MOVF TX_ALL_CNT,W	; вычитание
	SUBWF TX_OFF,W		; TX_OFF-TX_ALL_CNT
	
	BCF FLAG,0		;
	SKPC			; пропустить, если результат >=0
	BSF FLAG,0		;


	MOVF TX_ALL_CNT,W	; ускоряемся за 10 сек до конца цикла
	SUBLW D'125'		; ставим флаг, по которому во время передачи
	SKPNZ			; меняем скорость
	BSF FLAG,4		; только при 5 мин цикле

				; использовать либо верхнее, либо нижнее

	;SUBLW D'250'		; а это костыль для ускорения за 10 сек
	;SKPNZ			; до конца любого цикла, даже если
	;BSF FLAG,4		; работаем непрерывно

	DECFSZ TX_ALL_CNT,F	; TX_ALL_CNT-1, пропустить, если 0
	GOTO POP_TX
	MOVF TX_ALL,W		; восстанавливаем
	MOVWF TX_ALL_CNT	;

	BCF FLAG,4		; в конце цикла сбросить флаг ускорения
POP_TX

       	DECFSZ SEC_CNT, F	; SEC_CNT-1
	GOTO POP		; 
	MOVLW D'150'		; 300 секунд = 5 мин
	MOVWF SEC_CNT
	
	BTFSS FLAG,2		; если задержка активирована, то
	BSF FLAG,3		; через 5 мин после запуска поднимаем флаг
				; отмены задержки включения

	DECF MIN_CNT,F		; MIN_CNT-1
	DECFSZ DELAY,F		; DELAY-1, пропустить след, если 0
	GOTO POP
	BSF FLAG,2		; устанавливаем флаг разрешения работы	

POP	
	BCF PIR1,0		; сброс флага переполнения

END_ISR
	SWAPF TMPS,W		; восстанавливаем регистры W and SATUS
	MOVWF STATUS		;
	SWAPF TMPW,F		;
	SWAPF TMPW,W		;
	RETFIE			; возврат из прерывания

;==================================================================
;  Начало основной программы 
;==================================================================
START	
	MOVLW B'10001110'       ;
	BSF STATUS, RP0		; bank 1
	MOVWF OPTION_REG	; инициализация регистра option
	BCF STATUS, RP0		; bank 0	
			
	CLRF PORTA		; очистка порта A 
	CLRF PORTC		; очистка порта C

	MOVLW B'00000111'	; 
	MOVWF CMCON		; запрещаем работу компаратора

	BSF STATUS, RP0		; bank 1
	MOVLW B'00000000'	; 
	MOVWF TRISA		; порт A - все выходы
	MOVLW B'11111111'	; 
	MOVWF TRISC		; порт C - все входы
	BCF STATUS, RP0		; bank 0	

	CLRF TMR0		; на всякий случай. Говорят, надо...
	CLRWDT			; сбрасываем WDT

	BSF PORTA,2		; на 11 ноге висят подтягивающие резисторы,
				; подключенные к переключателю
				; после считывания напряжение с переключателя
				; снимается для экономии энергии

;==================================================================
; инициализация TMR1
;
	CLRF T1CON		; очистить TIMER1 control register
	CLRF TMR1H		; очистить верхний байт TMR1
	CLRF TMR1L		; очистить нижний байт TMR1
	CLRF INTCON		; запретить прерывания
	BSF STATUS,RP0		; bank 1
	CLRF PIE1		; очистить рег контроля периферийных прерываний
	BCF STATUS, RP0		; bank 0	
	CLRF PIR1		; очистить рег флагов периферийных прерываний
	MOVLW B'00001110'	; инициализация TIMER1 control register
	MOVWF T1CON		; с этого момента генератор 32.768 включен


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

	MOVLW D'150'		; инициализация счетчика пар секунд
	MOVWF SEC_CNT		; 150 пар = 300 сек = 5 мин
        DECF SEC_CNT,F		; имитируем прерывание

	;MOVLW D'2'		; сколько пятиминуток будем работать	
	MOVLW D'96'		; сколько пятиминуток будем работать
	MOVWF MIN_CNT		; 96х5=8 час

;	MOVLW D'2'		; сколько пятиминуток задержка включения
	MOVLW D'24'		; сколько пятиминуток задержка включения
	MOVWF DELAY		; 24х5=120 мин

	MOVLW D'178'		; тон звука, 178 ~ 1000 Гц
	MOVWF SET_TONE		; чем больше, тем ниже частота

	BSF FLAG,0		; поднимаем флаг

	BCF FLAG,4


;==================================================================
; если это включение питания, то выполняется задержка для
; гарантированного запуска генератора 32768 и его инициализация
; если другой сброс, то инициализация и задержка пропускаются
;
	BSF STATUS, RP0		; bank 1
	MOVF PCON,W		; PCON -> W
	BCF STATUS, RP0		; bank 0

	MOVWF TMPW		; W -> TMPW
	BTFSS TMPW,POR		; проверяем состояние POR, если 0, то был сброс
	GOTO DELAY_START	; по включению - задержка однозначно нужна
	BTFSC TMPW,BOR          ; а это был сброс по снижению напр питания
        GOTO SKIP_DELAY         ; или не был...
	
DELAY_START

	BCF FLAG,3		; при первом включении очистить FLAG,3

	; задержка 
	MOVLW D'255'		; скорость передачи 
	MOVWF CW_SPEED		; чем больше, тем медленней
	 
 	MOVLW 0X80	
	MOVWF CW_CHAR		; 
        CALL SEND_ONE_CHAR	; в качестве задержки предаем 7 точек

	BSF STATUS, RP0		; bank 1
	BSF PCON,POR		; устанавливаем POR=1
	BSF PCON,BOR		; устанавливаем BOR=1
	BCF STATUS, RP0		; bank 0

	SLEEP			; ожидаем запуск

SKIP_DELAY


;==================================================================
; читаем переключатель
;
        MOVF PORTC,W		; читаем порт C
	ANDLW B'00011100'	; маска 
	MOVWF SWITCH		; сохраняем состояние переключателя

        MOVF PORTC,W		; читаем порт C
	ANDLW B'00000011'	; маска двух младших бит

	BCF FLAG,2		; обнуляем флаг задержки
	BTFSC PORTC,5		; если перекл. on (на землю, 0) пропуск. след.
	BSF FLAG,2		; устанавливаем флаг, можно работать

	BCF PORTA,2		; отключаем подтягивающие резисторы

	ADDWF PCL,F		; таблица
	GOTO SW00
	GOTO SW01
	GOTO SW10
	GOTO SW11
SW00			; непрерывно
	MOVLW D'0'		; молчим последние 0 с
	MOVWF TX_OFF		;
	MOVLW D'30'		; цикл 60 сек
	GOTO END_SW
SW01			; цикл 30сек/30сек
	MOVLW D'15'		; молчим последние 30 с
	MOVWF TX_OFF		;
	MOVLW D'30'		; цикл 60 сек
	GOTO END_SW
SW10			; цикл 1 мин/1 мин
	MOVLW D'30'		; молчим последние 60 с
	MOVWF TX_OFF		;
	MOVLW D'60'		; цикл 120 сек
	GOTO END_SW
SW11			; цикл 1 мин/4 мин
	MOVLW D'120'		; молчим последние 4 m
	MOVWF TX_OFF		;
	MOVLW D'150'		; цикл 5 m

END_SW
	MOVWF TX_ALL		;
	MOVWF TX_ALL_CNT	; инициализация	
        DECF TX_ALL_CNT,F	; считаем, что 1 прерывание уже случилось

;==================================================================
; Окончание инициализации TIMER1
;

	MOVLW B'11000000'	; разрешить прерывания от периферийных модулей
	MOVWF INTCON

	BSF STATUS,RP0		; bank 1
	BSF PIE1,TMR1IE		; разрешить прерывания от TMR1
	BCF STATUS, RP0		; bank 0	
	BSF T1CON,TMR1ON        ; TMR1 ON


;==================================================================
; Если с момента запуска прошло 5 мин, то при сбросе задержку 
; включения игнорируем

	BTFSC FLAG,3		; FLAG,3 поднимается через 5 м после начала
				; работы
	BSF FLAG,2		; задержка включения не нужна

;==================================================================
; MAIN
; передача последовательности символов
; можно предавать любое количество, 0XFF означает конец последовательности,
; после чего формируется пауза и передача циклически повторяется
;
SEND_MSG
                                ; если автоотключение не нужно, то три 
				; нижеследующих строчки надо закомментировать
	MOVF MIN_CNT,F		; проверяем, не обнулился ли 
	SKPNZ			; счетчик пятиминуток
	GOTO POWER_OFF		; если да, то выключаемся

	BTFSS FLAG,2		; пропустить след, если задержка включения
				; кончилась (1-разрешение работы)
	GOTO FLASH		; мигнуть и sleep

        BTFSS FLAG,0		; если флаг сброшен, то идем спать
	GOTO TO_SLEEP
	
	MOVF SWITCH,W
	MOVWF CHAR_INDEX	; SWITCH -> CHAR_INDEX

GET_MSG
	MOVF CHAR_INDEX,W		
	BCF INTCON,GIE		; запрещаем прерывания
	BSF STATUS, RP0		; bank 1
	MOVWF EEADR		; значение CHAR_INDEX = адресу кода в EEPROM
	BSF EECON1,RD		; разрешаем чтение EEPROM
	MOVF EEDAT,W		; значение ячейки -> регистр W
	BCF STATUS, RP0		; bank 0	 
	BSF INTCON,GIE		; разрешаем прерывания
	;MOVLW 0x06
	MOVWF CW_CHAR		; W -> CW_CHAR	

	MOVLW 0XFF		; конец сообщения?
	SUBWF CW_CHAR,W		;
	SKPNZ
	GOTO END_MSG		; да, перейти к END_MSG

	MOVLW D'60'		; скорость передачи быстро
	BTFSS FLAG,4		; устанавливается за 10 с до конца цикла
	MOVLW D'160'		; скорость передачи медленно
	MOVWF CW_SPEED		; чем больше, тем медленней

	CALL SEND_CHAR		; передаем букву и паузу в 3 точки
                                ; или паузу 6 точек, если SPACE
	INCF CHAR_INDEX		; CHAR_INDEX+1	
	GOTO GET_MSG

END_MSG
	CALL WORD_SPACE         ; пауза 6 точек 
	GOTO SEND_MSG		;	

				; время работы закончилось
POWER_OFF			; отсюда выход только через RESET
	CLRF T1CON		; очистить TIMER1 control register, выключаем
				; генератор 32768
	;BCF T1CON,TMR1ON       ; TMR1 OFF
	CLRF INTCON		; запретить прерывания

				; после сброса считаем, что это сброс по питанию
	BSF STATUS, RP0		; bank 1
	BCF PCON,POR		; устанавливаем POR=0
	BCF PCON,BOR		; устанавливаем BOR=0
	BCF STATUS, RP0		; bank 0

TO_SLEEP			;
	CLRF PORTA
	SLEEP
	NOP
	GOTO SEND_MSG
;========================================================================
; индикатор включенной задержки
; мигаем порт A.1
FLASH
	MOVLW D'60'		; скорость передачи 
	MOVWF CW_SPEED		; чем больше, тем медленней
	BSF PORTA,1
	MOVLW 0X01		;
	MOVWF NBR_SPACE		; пауза в 1 точку
	CALL SEND_SPACE		;
	BCF PORTA,1
	GOTO TO_SLEEP
;========================================================================
; SEND_CHAR
; Подпрограмма получает код символа в регистре CW_CHAR, побитно перебирает 
; его, и, в зависимости от состояния бита, передает: тире, если бит = 1;
; точку, если бит = 0.
; Знак передается, пока в слове есть хоть одна единица. Последняя единица
; "съедается", она означает конец слова. 
;
SEND_CHAR
	MOVLW 0X00		; пауза?
	SUBWF CW_CHAR,W		;
	SKPNZ			; 
	GOTO WORD_SPACE

SEND_ONE_CHAR 
        BTFSS FLAG,0		; обрываем передачу, если флаг сброшен
	RETURN

	CLRC			; очистить бит переноса
	RRF CW_CHAR, F		; сдвиг вправо через перенос
				; 
	MOVF CW_CHAR, F         ; проверяем содержимое CW_CHAR, если все "0"
	SKPNZ                   ; то Z=1, выполняем RETURN, иначе пропускаем
	GOTO PAUSE2		; конец буквы
	SKPC			; проверить бит переноса, пропустить, если=1
	GOTO SEND_A_DIT		; перейти к SEND_A_DIT

SEND_A_DAH			; передаем тире 
	MOVLW 0X03		; 1 тире = 3 точки
	MOVWF NBR_DIT
	MOVLW 0X01		;
	MOVWF NBR_SPACE		; после тире - пауза в 1 точку
	BSF PORTA,0		; включаем PORT A.2
	CALL SEND_TONE		; генериуем звук, оно же - пауза
	BCF PORTA,0		; выключаем PORT A.2
	CALL SEND_SPACE
	GOTO SEND_ONE_CHAR

SEND_A_DIT 
	MOVLW 0X01		; передаем точку
	MOVWF NBR_DIT
	MOVWF NBR_SPACE		; после точки - пауза в 1 точку
	BSF PORTA,0		; включаем PORT A.2
	CALL SEND_TONE          ; генерируем звук, оно же - пауза
	BCF PORTA,0		; выключаем PORT A.2
	CALL SEND_SPACE
	GOTO SEND_ONE_CHAR

PAUSE2
	MOVLW D'2'		; пауза в 2 точки после буквы	
	MOVWF NBR_SPACE		; 
	CALL SEND_SPACE         ;
	RETURN

WORD_SPACE
	MOVLW D'6'		; пауза в 6 точек между словами	
	MOVWF NBR_SPACE		; 
	CALL SEND_SPACE         ;
	RETURN

;==================================================================
; SEND_TONE
; Подпрограмма осуществляет задержку и одновременно формирует сигнал
; звуковой частоты (порт A.1)
;

SEND_TONE
 
	MOVF NBR_DIT, W		; NBR_DIT кол-во пропускаемых точек 
	MOVWF CTR_NBR		; 

DIT_LENGTH 
	MOVF CW_SPEED, W	; CW_SPEED скорость передачи
	MOVWF CTR_DIT		;

START_CYCLE 
	BSF PORTA,1		; A.1=1 в начале цикла
	MOVF SET_TONE,W		; 
	MOVWF TONE		; заносим значение в счетчик цикла задержки

HIGH_HALF 
	DECFSZ TONE, F		; считаем до нуля
	GOTO HIGH_HALF
	BCF PORTA,1		; A.1=0 в конце цикла

	MOVF SET_TONE,W		;
	MOVWF TONE

LOW_HALF 
	DECFSZ TONE, F		; 
	GOTO LOW_HALF
	DECFSZ CTR_DIT, F	;
	GOTO START_CYCLE
	DECFSZ CTR_NBR, F
	GOTO DIT_LENGTH		; 
	RETURN			; 

;================================================================
; SEND_SPACE
; Делает тоже самое, что и SEND_TONE, только вместо команд управления
; портами стоит команда NOP
;

SEND_SPACE
 
	MOVF NBR_SPACE, W	; 
	MOVWF CTR_NBR

DIT_LENGTH_SP 
	MOVF CW_SPEED, W	; 
	MOVWF CTR_DIT

START_CYCLE_SP
	NOP
	MOVF SET_TONE,W
	MOVWF TONE		; 

HIGH_HALF_SP 
	DECFSZ TONE, F		; 
	GOTO HIGH_HALF_SP
	NOP
	MOVF SET_TONE,W
	MOVWF TONE

LOW_HALF_SP 
	DECFSZ TONE, F		; 
	GOTO LOW_HALF_SP
	DECFSZ CTR_DIT, F	;
	GOTO START_CYCLE_SP
	DECFSZ CTR_NBR, F
	GOTO DIT_LENGTH_SP	; 
	RETURN			; 

;==================================================================
;==================================================================
; Идентификатор
	ORG  0x2000	; стартовый адрес

        DATA 0x0000
        DATA 0x0000
        DATA 0x0000
        DATA 0x0000

;==================================================================
; Слово конфигурации
	ORG  0x2007	; стартовый адрес

	DATA 0x31E4

;==================================================================
; Запись в EEPROM при программировании
; Переключателем адресуется номер ячейки, кратный 4. Соответственно, маяк
; может передавать последовательно три символа Морзе, четвертым обязательно
; должен быть EOM
; В последнюю адресуемую ячейку можно записать большее количество символов

	ORG  0X2100	; стартовый адрес

	DATA 0x07	; M --    00000111
	DATA 0x0F	; O ---   00001111
        DATA 0xFF	; EOM     11111111
        DATA 0xFF	; EOM     11111111

	DATA 0x07	; M --    00000111
	DATA 0x0F	; O ---   00001111
        DATA 0x02	; E .     00000010  	
        DATA 0xFF	; EOM     11111111

	DATA 0x07	; M --    00000111
	DATA 0x0F	; O ---   00001111
	DATA 0x04	; I ..    00000100
        DATA 0xFF	; EOM     11111111

	DATA 0x07	; M --    00000111
	DATA 0x0F	; O ---   00001111
	DATA 0x08	; S ...   00001000
        DATA 0xFF	; EOM     11111111

	DATA 0x07	; M --    00000111
	DATA 0x0F	; O ---   00001111
	DATA 0x10	; H ....  00010000
        DATA 0xFF	; EOM     11111111

	DATA 0x07	; M --    00000111
	DATA 0x0F	; O ---   00001111
	DATA 0x20	; 5 ..... 00100000
        DATA 0xFF	; EOM     11111111

	DATA 0x07	; M --    00000111
	DATA 0x0F	; O ---   00001111
	DATA 0x03	; T -     00000011
        DATA 0xFF	; EOM     11111111

	DATA 0x03	; T -     00000011
        DATA 0xFF	; EOM     11111111
        DATA 0xFF	; EOM     11111111
        DATA 0xFF	; EOM     11111111

	END

Версия прошивки 3.1, циклы 30с/120с; 60с/60с; 1м/4м

Файл:Mf31.HEX.zip

;-Передает в режиме лисы код Морзе (MO, MOE, MOI, MOS, MOH, MO5, MOT, T). Вариант кода задается переключателем.
;-Может работать непрерывно или циклом: 30с/120с; 60с/60с; 1м/4м.
;-Есть выход 1000 Гц для модуляции маяка на 144 МГц.
;-Автоотключение через 8 часов.
;-Потребление в выключенном состоянии 0.08 ма, во время работы, при передаче позывного, 0.5 ма.
;-Уход часов определяется кварцем.
;-Код с переключателя считывается один раз после сброса.
;-Режим отложенного старта (ОС), задержка 60 минут
;-Ускорение передачи позывного за 10 сек до конца цикла (только для 5 мин цикла)
;-Питание от 3 до 5 вольт 
;
; PIC16F630
; WDT off, intLC, MCLR on, BOR on, PWRTE on
;
	list	P=16F630
	radix	HEX

;====================================================================
; именование пользовательских регистров
;	
 	CBLOCK	0X20	; начальный адрес пользовательских регистров
        TMPW		; временный регистр для хранения W во время прерывания
	TMPS		; временный регистр для хранения STATUS                                                    
	SEC_CNT		; счетчик пар секунд
	MIN_CNT 	; счетчик минут (пятиминуток, автовыключение)
	FLAG		; регистр флагов:
			; FLAG,0 разрешает передачу позывного в свое время
			; FLAG,2 флаг задержки включения (1-можно работать)
                        ; FLAG,3 флаг взводится через 5 мин после начала работы
			; и отменяет задержку включения при сбросе
			; FLAG,4 флаг устанавливается за 10 сек до конца цикла


	DELAY		; счетчик пятиминуток, задержка включения
	TX_ALL_CNT	; счетчик пар секунд в цикле
	TX_OFF		; с какой секунды пауза
	TX_ALL		; сколько пар секунд в цикле

	SWITCH		; состояние переключателя
	CHAR_INDEX	; номер передаваемого символа

	CW_SPEED	; скорость передачи

; процедура SEND_TONE
	NBR_DIT		; NBR_DIT кол-во пропускаемых точек
	CTR_NBR		; счетчик пропускаемых точек
	TONE		; счетчик частоты
	SET_TONE	; установка тона передаваемого сигнала
; процедура SEND_SPACE
	NBR_SPACE	; колво пропускаемых точек
	CTR_DIT		; счетчик пропускаемых точек
; процедура SEND_ONE_CHAR
	CW_CHAR		; передаваемый символ
	ENDC


;
; Именование регистров микроконтроллера
;
CMCON		EQU	0X19	; регистр контроля компаратора
TMR0		EQU	0X01	; timer0
TMR1L		EQU	0X0E	; timer1 младший байт
TMR1H		EQU	0X0F	; timer1 старший байт     
T1CON		EQU	0X10	; timer1 control register
PCL		EQU	0X02	; программный счетчик
STATUS		EQU	0X03	; регистр status
FSR		EQU	0X04	; указатель адреса в памяти данных
PORTA		EQU	0X05	; порт A
PORTC		EQU	0X07	; порт C
PCLATH		EQU	0X0A	; верхние 5 бит программного счетчика
INTCON		EQU	0X0B	; регистр контроля прерываний
TRISA		EQU	0X85	; управляющий регистр порта A
TRISC		EQU	0X87	; управляющий регистр порта C 
OPTION_REG	EQU	0X81	; регистр option
EEADR		EQU	0X9B	; адресный регистр EEPROM
EECON1		EQU	0X9C	; содержит бит RD
EEDAT		EQU	0X9A	; прочитанные из EEPROM данные
PCON		EQU	0X8E	; регистр power control
PIE1		EQU	0X8C	; регистр контроля периферийных прерываний
PIR1		EQU	0X0C	; регистр флагов прерываний от 
				; периферийных модулей

;
; присвоение значений символьным константам
;
RP0		EQU	0X05	; бит-указатель страницы данных в STATUS
W		EQU	0X00	; file register designator = W
F		EQU	0X01	; file register designator = F 
Z		EQU	0X02	; бит нуля в STATUS 
C		EQU	0X00	; бит преноса в STATUS
RD		EQU	0X00	; инициализация чтения EEPROM
POR		EQU	0X01	; бит POR регистра PCON обнуляется, если был
				; сброс по включению питания
BOR		EQU	0X00	; сброс по снижению питания
TMR1IF		EQU	0X00	; бит переполнения TMR1 in register PIR1
TMR1ON		EQU	0X00	;
GIE		EQU	0X07	;
TMR1IE		EQU	0X00	; бит разрешения прерываний от TMR1
PON		EQU	0X00	; POWER ON IN FLAG
;
;=================================================================
; vector table
;
	ORG 0X000		; стартовый адрес	
	GOTO START		; 

;==================================================================
; TIMER1 INTERRUPT 
;
	ORG 0X004		; адрес	прерывания
	MOVWF TMPW		; сохраняем W
	SWAPF STATUS,W
	MOVWF TMPS		; сохраняем STATUS
	
	BTFSC PIR1,0		; прерывание от TMR1?
	GOTO T1_INT		; да
        NOP			; обработчик левого прерывания
	GOTO END_ISR		; 

T1_INT
	MOVF TX_ALL_CNT,W	; вычитание
	SUBWF TX_OFF,W		; TX_OFF-TX_ALL_CNT
	
	BCF FLAG,0		;
	SKPC			; пропустить, если результат >=0
	BSF FLAG,0		;


	MOVF TX_ALL_CNT,W	; ускоряемся за 10 сек до конца цикла
	SUBLW D'125'		; ставим флаг, по которому во время передачи
	SKPNZ			; меняем скорость
	BSF FLAG,4		; только при 5 мин цикле

				; использовать либо верхнее, либо нижнее

	;SUBLW D'250'		; а это костыль для ускорения за 10 сек
	;SKPNZ			; до конца любого цикла, даже если
	;BSF FLAG,4		; работаем непрерывно

	DECFSZ TX_ALL_CNT,F	; TX_ALL_CNT-1, пропустить, если 0
	GOTO POP_TX
	MOVF TX_ALL,W		; восстанавливаем
	MOVWF TX_ALL_CNT	;

	BCF FLAG,4		; в конце цикла сбросить флаг ускорения
POP_TX

       	DECFSZ SEC_CNT, F	; SEC_CNT-1
	GOTO POP		; 
	MOVLW D'150'		; 300 секунд = 5 мин
	MOVWF SEC_CNT
	
	BTFSS FLAG,2		; если задержка активирована, то
	BSF FLAG,3		; через 5 мин после запуска поднимаем флаг
				; отмены задержки включения

	DECF MIN_CNT,F		; MIN_CNT-1
	DECFSZ DELAY,F		; DELAY-1, пропустить след, если 0
	GOTO POP
	BSF FLAG,2		; устанавливаем флаг разрешения работы	

POP	
	BCF PIR1,0		; сброс флага переполнения

END_ISR
	SWAPF TMPS,W		; восстанавливаем регистры W and SATUS
	MOVWF STATUS		;
	SWAPF TMPW,F		;
	SWAPF TMPW,W		;
	RETFIE			; возврат из прерывания

;==================================================================
;  Начало основной программы 
;==================================================================
START	
	MOVLW B'10001110'       ;
	BSF STATUS, RP0		; bank 1
	MOVWF OPTION_REG	; инициализация регистра option
	BCF STATUS, RP0		; bank 0	
			
	CLRF PORTA		; очистка порта A 
	CLRF PORTC		; очистка порта C

	MOVLW B'00000111'	; 
	MOVWF CMCON		; запрещаем работу компаратора

	BSF STATUS, RP0		; bank 1
	MOVLW B'00000000'	; 
	MOVWF TRISA		; порт A - все выходы
	MOVLW B'11111111'	; 
	MOVWF TRISC		; порт C - все входы
	BCF STATUS, RP0		; bank 0	

	CLRF TMR0		; на всякий случай. Говорят, надо...
	CLRWDT			; сбрасываем WDT

	BSF PORTA,2		; на 11 ноге висят подтягивающие резисторы,
				; подключенные к переключателю
				; после считывания напряжение с переключателя
				; снимается для экономии энергии

;==================================================================
; инициализация TMR1
;
	CLRF T1CON		; очистить TIMER1 control register
	CLRF TMR1H		; очистить верхний байт TMR1
	CLRF TMR1L		; очистить нижний байт TMR1
	CLRF INTCON		; запретить прерывания
	BSF STATUS,RP0		; bank 1
	CLRF PIE1		; очистить рег контроля периферийных прерываний
	BCF STATUS, RP0		; bank 0	
	CLRF PIR1		; очистить рег флагов периферийных прерываний
	MOVLW B'00001110'	; инициализация TIMER1 control register
	MOVWF T1CON		; с этого момента генератор 32.768 включен


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

	MOVLW D'150'		; инициализация счетчика пар секунд
	MOVWF SEC_CNT		; 150 пар = 300 сек = 5 мин
        DECF SEC_CNT,F		; имитируем прерывание

	;MOVLW D'2'		; сколько пятиминуток будем работать	
	MOVLW D'96'		; сколько пятиминуток будем работать
	MOVWF MIN_CNT		; 96х5=8 час

;	MOVLW D'2'		; сколько пятиминуток задержка включения
	MOVLW D'12'		; сколько пятиминуток задержка включения
	MOVWF DELAY		; 12х5=60 мин

	MOVLW D'178'		; тон звука, 178 ~ 1000 Гц
	MOVWF SET_TONE		; чем больше, тем ниже частота

	BSF FLAG,0		; поднимаем флаг

	BCF FLAG,4


;==================================================================
; если это включение питания, то выполняется задержка для
; гарантированного запуска генератора 32768 и его инициализация
; если другой сброс, то инициализация и задержка пропускаются
;
	BSF STATUS, RP0		; bank 1
	MOVF PCON,W		; PCON -> W
	BCF STATUS, RP0		; bank 0

	MOVWF TMPW		; W -> TMPW
	BTFSS TMPW,POR		; проверяем состояние POR, если 0, то был сброс
	GOTO DELAY_START	; по включению - задержка однозначно нужна
	BTFSC TMPW,BOR          ; а это был сброс по снижению напр питания
        GOTO SKIP_DELAY         ; или не был...
	
DELAY_START

	BCF FLAG,3		; при первом включении очистить FLAG,3

	; задержка 
	MOVLW D'255'		; скорость передачи 
	MOVWF CW_SPEED		; чем больше, тем медленней
	 
 	MOVLW 0X80	
	MOVWF CW_CHAR		; 
        CALL SEND_ONE_CHAR	; в качестве задержки предаем 7 точек

	BSF STATUS, RP0		; bank 1
	BSF PCON,POR		; устанавливаем POR=1
	BSF PCON,BOR		; устанавливаем BOR=1
	BCF STATUS, RP0		; bank 0

	SLEEP			; ожидаем запуск

SKIP_DELAY


;==================================================================
; читаем переключатель
;
        MOVF PORTC,W		; читаем порт C
	ANDLW B'00011100'	; маска 
	MOVWF SWITCH		; сохраняем состояние переключателя

        MOVF PORTC,W		; читаем порт C
	ANDLW B'00000011'	; маска двух младших бит

	BCF FLAG,2		; обнуляем флаг задержки
	BTFSC PORTC,5		; если перекл. on (на землю, 0) пропуск. след.
	BSF FLAG,2		; устанавливаем флаг, можно работать

	BCF PORTA,2		; отключаем подтягивающие резисторы

	ADDWF PCL,F		; таблица
	GOTO SW00
	GOTO SW01
	GOTO SW10
	GOTO SW11
SW00			; непрерывно
	MOVLW D'0'		; молчим последние 0 с
	MOVWF TX_OFF		;
	MOVLW D'30'		; цикл 60 сек
	GOTO END_SW
SW01			; цикл 30сек/120сек
	MOVLW D'60'		; молчим последние 120 с
	MOVWF TX_OFF		;
	MOVLW D'75'		; цикл 150 сек
	GOTO END_SW
SW10			; цикл 1 мин/1 мин
	MOVLW D'30'		; молчим последние 60 с
	MOVWF TX_OFF		;
	MOVLW D'60'		; цикл 120 сек
	GOTO END_SW
SW11			; цикл 1 мин/4 мин
	MOVLW D'120'		; молчим последние 4 m
	MOVWF TX_OFF		;
	MOVLW D'150'		; цикл 5 m

END_SW
	MOVWF TX_ALL		;
	MOVWF TX_ALL_CNT	; инициализация	
        DECF TX_ALL_CNT,F	; считаем, что 1 прерывание уже случилось

;==================================================================
; Окончание инициализации TIMER1
;

	MOVLW B'11000000'	; разрешить прерывания от периферийных модулей
	MOVWF INTCON

	BSF STATUS,RP0		; bank 1
	BSF PIE1,TMR1IE		; разрешить прерывания от TMR1
	BCF STATUS, RP0		; bank 0	
	BSF T1CON,TMR1ON        ; TMR1 ON


;==================================================================
; Если с момента запуска прошло 5 мин, то при сбросе задержку 
; включения игнорируем

	BTFSC FLAG,3		; FLAG,3 поднимается через 5 м после начала
				; работы
	BSF FLAG,2		; задержка включения не нужна

;==================================================================
; MAIN
; передача последовательности символов
; можно предавать любое количество, 0XFF означает конец последовательности,
; после чего формируется пауза и передача циклически повторяется
;
SEND_MSG
                                ; если автоотключение не нужно, то три 
				; нижеследующих строчки надо закомментировать
	MOVF MIN_CNT,F		; проверяем, не обнулился ли 
	SKPNZ			; счетчик пятиминуток
	GOTO POWER_OFF		; если да, то выключаемся

	BTFSS FLAG,2		; пропустить след, если задержка включения
				; кончилась (1-разрешение работы)
	GOTO FLASH		; мигнуть и sleep

        BTFSS FLAG,0		; если флаг сброшен, то идем спать
	GOTO TO_SLEEP
	
	MOVF SWITCH,W
	MOVWF CHAR_INDEX	; SWITCH -> CHAR_INDEX

GET_MSG
	MOVF CHAR_INDEX,W		
	BCF INTCON,GIE		; запрещаем прерывания
	BSF STATUS, RP0		; bank 1
	MOVWF EEADR		; значение CHAR_INDEX = адресу кода в EEPROM
	BSF EECON1,RD		; разрешаем чтение EEPROM
	MOVF EEDAT,W		; значение ячейки -> регистр W
	BCF STATUS, RP0		; bank 0	 
	BSF INTCON,GIE		; разрешаем прерывания
	;MOVLW 0x06
	MOVWF CW_CHAR		; W -> CW_CHAR	

	MOVLW 0XFF		; конец сообщения?
	SUBWF CW_CHAR,W		;
	SKPNZ
	GOTO END_MSG		; да, перейти к END_MSG

	MOVLW D'60'		; скорость передачи быстро
	BTFSS FLAG,4		; устанавливается за 10 с до конца цикла
	MOVLW D'160'		; скорость передачи медленно
	MOVWF CW_SPEED		; чем больше, тем медленней

	CALL SEND_CHAR		; передаем букву и паузу в 3 точки
                                ; или паузу 6 точек, если SPACE
	INCF CHAR_INDEX		; CHAR_INDEX+1	
	GOTO GET_MSG

END_MSG
	CALL WORD_SPACE         ; пауза 6 точек 
	GOTO SEND_MSG		;	

				; время работы закончилось
POWER_OFF			; отсюда выход только через RESET
	CLRF T1CON		; очистить TIMER1 control register, выключаем
				; генератор 32768
	;BCF T1CON,TMR1ON       ; TMR1 OFF
	CLRF INTCON		; запретить прерывания

				; после сброса считаем, что это сброс по питанию
	BSF STATUS, RP0		; bank 1
	BCF PCON,POR		; устанавливаем POR=0
	BCF PCON,BOR		; устанавливаем BOR=0
	BCF STATUS, RP0		; bank 0

TO_SLEEP			;
	CLRF PORTA
	SLEEP
	NOP
	GOTO SEND_MSG
;========================================================================
; индикатор включенной задержки
; мигаем порт A.1
FLASH
	MOVLW D'60'		; скорость передачи 
	MOVWF CW_SPEED		; чем больше, тем медленней
	BSF PORTA,1
	MOVLW 0X01		;
	MOVWF NBR_SPACE		; пауза в 1 точку
	CALL SEND_SPACE		;
	BCF PORTA,1
	GOTO TO_SLEEP
;========================================================================
; SEND_CHAR
; Подпрограмма получает код символа в регистре CW_CHAR, побитно перебирает 
; его, и, в зависимости от состояния бита, передает: тире, если бит = 1;
; точку, если бит = 0.
; Знак передается, пока в слове есть хоть одна единица. Последняя единица
; "съедается", она означает конец слова. 
;
SEND_CHAR
	MOVLW 0X00		; пауза?
	SUBWF CW_CHAR,W		;
	SKPNZ			; 
	GOTO WORD_SPACE

SEND_ONE_CHAR 
        BTFSS FLAG,0		; обрываем передачу, если флаг сброшен
	RETURN

	CLRC			; очистить бит переноса
	RRF CW_CHAR, F		; сдвиг вправо через перенос
				; 
	MOVF CW_CHAR, F         ; проверяем содержимое CW_CHAR, если все "0"
	SKPNZ                   ; то Z=1, выполняем RETURN, иначе пропускаем
	GOTO PAUSE2		; конец буквы
	SKPC			; проверить бит переноса, пропустить, если=1
	GOTO SEND_A_DIT		; перейти к SEND_A_DIT

SEND_A_DAH			; передаем тире 
	MOVLW 0X03		; 1 тире = 3 точки
	MOVWF NBR_DIT
	MOVLW 0X01		;
	MOVWF NBR_SPACE		; после тире - пауза в 1 точку
	BSF PORTA,0		; включаем PORT A.2
	CALL SEND_TONE		; генериуем звук, оно же - пауза
	BCF PORTA,0		; выключаем PORT A.2
	CALL SEND_SPACE
	GOTO SEND_ONE_CHAR

SEND_A_DIT 
	MOVLW 0X01		; передаем точку
	MOVWF NBR_DIT
	MOVWF NBR_SPACE		; после точки - пауза в 1 точку
	BSF PORTA,0		; включаем PORT A.2
	CALL SEND_TONE          ; генерируем звук, оно же - пауза
	BCF PORTA,0		; выключаем PORT A.2
	CALL SEND_SPACE
	GOTO SEND_ONE_CHAR

PAUSE2
	MOVLW D'2'		; пауза в 2 точки после буквы	
	MOVWF NBR_SPACE		; 
	CALL SEND_SPACE         ;
	RETURN

WORD_SPACE
	MOVLW D'6'		; пауза в 6 точек между словами	
	MOVWF NBR_SPACE		; 
	CALL SEND_SPACE         ;
	RETURN

;==================================================================
; SEND_TONE
; Подпрограмма осуществляет задержку и одновременно формирует сигнал
; звуковой частоты (порт A.1)
;

SEND_TONE
 
	MOVF NBR_DIT, W		; NBR_DIT кол-во пропускаемых точек 
	MOVWF CTR_NBR		; 

DIT_LENGTH 
	MOVF CW_SPEED, W	; CW_SPEED скорость передачи
	MOVWF CTR_DIT		;

START_CYCLE 
	BSF PORTA,1		; A.1=1 в начале цикла
	MOVF SET_TONE,W		; 
	MOVWF TONE		; заносим значение в счетчик цикла задержки

HIGH_HALF 
	DECFSZ TONE, F		; считаем до нуля
	GOTO HIGH_HALF
	BCF PORTA,1		; A.1=0 в конце цикла

	MOVF SET_TONE,W		;
	MOVWF TONE

LOW_HALF 
	DECFSZ TONE, F		; 
	GOTO LOW_HALF
	DECFSZ CTR_DIT, F	;
	GOTO START_CYCLE
	DECFSZ CTR_NBR, F
	GOTO DIT_LENGTH		; 
	RETURN			; 

;================================================================
; SEND_SPACE
; Делает тоже самое, что и SEND_TONE, только вместо команд управления
; портами стоит команда NOP
;

SEND_SPACE
 
	MOVF NBR_SPACE, W	; 
	MOVWF CTR_NBR

DIT_LENGTH_SP 
	MOVF CW_SPEED, W	; 
	MOVWF CTR_DIT

START_CYCLE_SP
	NOP
	MOVF SET_TONE,W
	MOVWF TONE		; 

HIGH_HALF_SP 
	DECFSZ TONE, F		; 
	GOTO HIGH_HALF_SP
	NOP
	MOVF SET_TONE,W
	MOVWF TONE

LOW_HALF_SP 
	DECFSZ TONE, F		; 
	GOTO LOW_HALF_SP
	DECFSZ CTR_DIT, F	;
	GOTO START_CYCLE_SP
	DECFSZ CTR_NBR, F
	GOTO DIT_LENGTH_SP	; 
	RETURN			; 

;==================================================================
;==================================================================
; Идентификатор
	ORG  0x2000	; стартовый адрес

        DATA 0x0000
        DATA 0x0000
        DATA 0x0000
        DATA 0x0000

;==================================================================
; Слово конфигурации
	ORG  0x2007	; стартовый адрес

	DATA 0x31E4

;==================================================================
; Запись в EEPROM при программировании
; Переключателем адресуется номер ячейки, кратный 4. Соответственно, маяк
; может передавать последовательно три символа Морзе, четвертым обязательно
; должен быть EOM
; В последнюю адресуемую ячейку можно записать большее количество символов

	ORG  0X2100	; стартовый адрес

	DATA 0x07	; M --    00000111
	DATA 0x0F	; O ---   00001111
        DATA 0xFF	; EOM     11111111
        DATA 0xFF	; EOM     11111111

	DATA 0x07	; M --    00000111
	DATA 0x0F	; O ---   00001111
        DATA 0x02	; E .     00000010  	
        DATA 0xFF	; EOM     11111111

	DATA 0x07	; M --    00000111
	DATA 0x0F	; O ---   00001111
	DATA 0x04	; I ..    00000100
        DATA 0xFF	; EOM     11111111

	DATA 0x07	; M --    00000111
	DATA 0x0F	; O ---   00001111
	DATA 0x08	; S ...   00001000
        DATA 0xFF	; EOM     11111111

	DATA 0x07	; M --    00000111
	DATA 0x0F	; O ---   00001111
	DATA 0x10	; H ....  00010000
        DATA 0xFF	; EOM     11111111

	DATA 0x07	; M --    00000111
	DATA 0x0F	; O ---   00001111
	DATA 0x20	; 5 ..... 00100000
        DATA 0xFF	; EOM     11111111

	DATA 0x07	; M --    00000111
	DATA 0x0F	; O ---   00001111
	DATA 0x03	; T -     00000011
        DATA 0xFF	; EOM     11111111

	DATA 0x03	; T -     00000011
        DATA 0xFF	; EOM     11111111
        DATA 0xFF	; EOM     11111111
        DATA 0xFF	; EOM     11111111

	END

Версия прошивки 3.2, циклы 30с/120с; 60с/60с; 1м/4м


;-Передает в режиме лисы код Морзе (MO, MOE, MOI, MOS, MOH, MO5, RA1AMO). Вариант кода задается переключателем.
;-Может работать непрерывно или циклом: 30с/120с; 60с/60с; 1м/4м.
;-Есть выход 1000 Гц для модуляции маяка на 144 МГц.
;-Автоотключение через 8 часов, без учета ОС.
;-Потребление в выключенном состоянии менее 0.08 ма, во время работы, при передаче позывного, 0.5 ма.
;-Уход часов определяется кварцем.
;-Код с переключателя считывается один раз после сброса.
;-Режим отложенного старта (ОС), задержка 120 минут
;-Питание от 3 до 5 вольт 
;
; PIC16F630
; WDT off, intLC, MCLR on, BOR on, PWRTE on
;
	list	P=16F630
	radix	HEX

;====================================================================
; именование пользовательских регистров
;	
 	CBLOCK	0X20	; начальный адрес пользовательских регистров
        TMPW		; временный регистр для хранения W во время прерывания
	TMPS		; временный регистр для хранения STATUS                                                    
	SEC_CNT		; счетчик пар секунд
	MIN_CNT 	; счетчик минут (пятиминуток, автовыключение)
	FLAG		; регистр флагов:
			; FLAG,0 разрешает передачу позывного в свое время
			; FLAG,2 флаг задержки включения (1-можно работать)
                        ; FLAG,3 флаг взводится через 5 мин после начала работы
			; и отменяет задержку включения при сбросе
			; FLAG,4 флаг устанавливается за 10 сек до конца цикла


	DELAY		; счетчик пятиминуток, задержка включения
	TX_ALL_CNT	; счетчик пар секунд в цикле
	TX_OFF		; с какой секунды пауза
	TX_ALL		; сколько пар секунд в цикле

	SWITCH		; состояние переключателя
	CHAR_INDEX	; номер передаваемого символа

	CW_SPEED	; скорость передачи

; процедура SEND_TONE
	NBR_DIT		; NBR_DIT кол-во пропускаемых точек
	CTR_NBR		; счетчик пропускаемых точек
	TONE		; счетчик частоты
	SET_TONE	; установка тона передаваемого сигнала
; процедура SEND_SPACE
	NBR_SPACE	; колво пропускаемых точек
	CTR_DIT		; счетчик пропускаемых точек
; процедура SEND_ONE_CHAR
	CW_CHAR		; передаваемый символ
	ENDC


;
; Именование регистров микроконтроллера
;
CMCON		EQU	0X19	; регистр контроля компаратора
TMR0		EQU	0X01	; timer0
TMR1L		EQU	0X0E	; timer1 младший байт
TMR1H		EQU	0X0F	; timer1 старший байт     
T1CON		EQU	0X10	; timer1 control register
PCL		EQU	0X02	; программный счетчик
STATUS		EQU	0X03	; регистр status
FSR		EQU	0X04	; указатель адреса в памяти данных
PORTA		EQU	0X05	; порт A
PORTC		EQU	0X07	; порт C
PCLATH		EQU	0X0A	; верхние 5 бит программного счетчика
INTCON		EQU	0X0B	; регистр контроля прерываний
TRISA		EQU	0X85	; управляющий регистр порта A
TRISC		EQU	0X87	; управляющий регистр порта C 
OPTION_REG	EQU	0X81	; регистр option
EEADR		EQU	0X9B	; адресный регистр EEPROM
EECON1		EQU	0X9C	; содержит бит RD
EEDAT		EQU	0X9A	; прочитанные из EEPROM данные
PCON		EQU	0X8E	; регистр power control
PIE1		EQU	0X8C	; регистр контроля периферийных прерываний
PIR1		EQU	0X0C	; регистр флагов прерываний от 
				; периферийных модулей

;
; присвоение значений символьным константам
;
RP0		EQU	0X05	; бит-указатель страницы данных в STATUS
W		EQU	0X00	; file register designator = W
F		EQU	0X01	; file register designator = F 
Z		EQU	0X02	; бит нуля в STATUS 
C		EQU	0X00	; бит преноса в STATUS
RD		EQU	0X00	; инициализация чтения EEPROM
POR		EQU	0X01	; бит POR регистра PCON обнуляется, если был
				; сброс по включению питания
BOR		EQU	0X00	; сброс по снижению питания
TMR1IF		EQU	0X00	; бит переполнения TMR1 in register PIR1
TMR1ON		EQU	0X00	;
GIE		EQU	0X07	;
TMR1IE		EQU	0X00	; бит разрешения прерываний от TMR1
PON		EQU	0X00	; POWER ON IN FLAG
;
;=================================================================
; vector table
;
	ORG 0X000		; стартовый адрес	
	GOTO START		; 

;==================================================================
; TIMER1 INTERRUPT 
;
	ORG 0X004		; адрес	прерывания
	MOVWF TMPW		; сохраняем W
	SWAPF STATUS,W
	MOVWF TMPS		; сохраняем STATUS
	
	BTFSC PIR1,0		; прерывание от TMR1?
	GOTO T1_INT		; да
        NOP			; обработчик левого прерывания
	GOTO END_ISR		; 

T1_INT
	MOVF TX_ALL_CNT,W	; вычитание
	SUBWF TX_OFF,W		; TX_OFF-TX_ALL_CNT
	
	BCF FLAG,0		;
	SKPC			; пропустить, если результат >=0
	BSF FLAG,0		;


;	MOVF TX_ALL_CNT,W	; ускоряемся за 10 сек до конца цикла
;	SUBLW D'125'		; ставим флаг, по которому во время передачи
;	SKPNZ			; меняем скорость
;	BSF FLAG,4		; только при 5 мин цикле

				; использовать либо верхнее, либо нижнее

	;SUBLW D'250'		; а это костыль для ускорения за 10 сек
	;SKPNZ			; до конца любого цикла, даже если
	;BSF FLAG,4		; работаем непрерывно

	DECFSZ TX_ALL_CNT,F	; TX_ALL_CNT-1, пропустить, если 0
	GOTO POP_TX
	MOVF TX_ALL,W		; восстанавливаем
	MOVWF TX_ALL_CNT	;

;	BCF FLAG,4		; в конце цикла сбросить флаг ускорения
POP_TX

       	DECFSZ SEC_CNT, F	; SEC_CNT-1
	GOTO POP		; 
	MOVLW D'150'		; 300 секунд = 5 мин
	MOVWF SEC_CNT
	
	BTFSS FLAG,2		; если задержка активирована, то
	BSF FLAG,3		; через 5 мин после запуска поднимаем флаг
				; отмены задержки включения

	BTFSC FLAG,2		; если флаг разрешения работы установлен, начинаем отсчет 
				; задержки отключения
	DECF MIN_CNT,F		; MIN_CNT-1 минуты работы считаем после 
				; окончании задержки включения


	DECFSZ DELAY,F		; DELAY-1, пропустить след, если 0
	GOTO POP		; задержка окончилась
	BSF FLAG,2		; устанавливаем флаг разрешения работы	


POP	
	BCF PIR1,0		; сброс флага переполнения

END_ISR
	SWAPF TMPS,W		; восстанавливаем регистры W and SATUS
	MOVWF STATUS		;
	SWAPF TMPW,F		;
	SWAPF TMPW,W		;
	RETFIE			; возврат из прерывания

;==================================================================
;  Начало основной программы 
;==================================================================
START	
	MOVLW B'10001110'       ;
	BSF STATUS, RP0		; bank 1
	MOVWF OPTION_REG	; инициализация регистра option
	BCF STATUS, RP0		; bank 0	
			
	CLRF PORTA		; очистка порта A 
	CLRF PORTC		; очистка порта C

	MOVLW B'00000111'	; 
	MOVWF CMCON		; запрещаем работу компаратора

	BSF STATUS, RP0		; bank 1
	MOVLW B'00000000'	; 
	MOVWF TRISA		; порт A - все выходы
	MOVLW B'11111111'	; 
	MOVWF TRISC		; порт C - все входы
	BCF STATUS, RP0		; bank 0	

	CLRF TMR0		; на всякий случай. Говорят, надо...
	CLRWDT			; сбрасываем WDT

	BSF PORTA,2		; на 11 ноге висят подтягивающие резисторы,
				; подключенные к переключателю
				; после считывания напряжение с переключателя
				; снимается для экономии энергии

;==================================================================
; инициализация TMR1
;
	CLRF T1CON		; очистить TIMER1 control register
	CLRF TMR1H		; очистить верхний байт TMR1
	CLRF TMR1L		; очистить нижний байт TMR1
	CLRF INTCON		; запретить прерывания
	BSF STATUS,RP0		; bank 1
	CLRF PIE1		; очистить рег контроля периферийных прерываний
	BCF STATUS, RP0		; bank 0	
	CLRF PIR1		; очистить рег флагов периферийных прерываний
	MOVLW B'00001110'	; инициализация TIMER1 control register
	MOVWF T1CON		; с этого момента генератор 32.768 включен


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

	MOVLW D'150'		; инициализация счетчика пар секунд
	MOVWF SEC_CNT		; 150 пар = 300 сек = 5 мин
        DECF SEC_CNT,F		; имитируем прерывание

	;MOVLW D'2'		; сколько пятиминуток будем работать	
	MOVLW D'96'		; сколько пятиминуток будем работать
	MOVWF MIN_CNT		; 96х5=8 час

;	MOVLW D'2'		; сколько пятиминуток задержка включения
	MOVLW D'24'		; сколько пятиминуток задержка включения
	MOVWF DELAY		; 24х5=120 мин

	MOVLW D'178'		; тон звука, 178 ~ 1000 Гц
	MOVWF SET_TONE		; чем больше, тем ниже частота

	BSF FLAG,0		; поднимаем флаг

;	BCF FLAG,4


;==================================================================
; если это включение питания, то выполняется задержка для
; гарантированного запуска генератора 32768 и его инициализация
; если другой сброс, то инициализация и задержка пропускаются
;
	BSF STATUS, RP0		; bank 1
	MOVF PCON,W		; PCON -> W
	BCF STATUS, RP0		; bank 0

	MOVWF TMPW		; W -> TMPW
	BTFSS TMPW,POR		; проверяем состояние POR, если 0, то был сброс
	GOTO DELAY_START	; по включению - задержка однозначно нужна
	BTFSC TMPW,BOR          ; а это был сброс по снижению напр питания
        GOTO SKIP_DELAY         ; или не был...
	
DELAY_START

	BCF FLAG,3		; при первом включении очистить FLAG,3

	; задержка 
	MOVLW D'255'		; скорость передачи 
	MOVWF CW_SPEED		; чем больше, тем медленней
	 
 	MOVLW 0X80	
	MOVWF CW_CHAR		; 
        CALL SEND_ONE_CHAR	; в качестве задержки предаем 7 точек

	BSF STATUS, RP0		; bank 1
	BSF PCON,POR		; устанавливаем POR=1
	BSF PCON,BOR		; устанавливаем BOR=1
	BCF STATUS, RP0		; bank 0

	SLEEP			; ожидаем запуск

SKIP_DELAY


;==================================================================
; читаем переключатель
;
        MOVF PORTC,W		; читаем порт C
	ANDLW B'00011100'	; маска 
	MOVWF SWITCH		; сохраняем состояние переключателя

        MOVF PORTC,W		; читаем порт C
	ANDLW B'00000011'	; маска двух младших бит

	BCF FLAG,2		; обнуляем флаг задержки
	BTFSC PORTC,5		; если перекл. on (на землю, 0) пропуск. след.
	BSF FLAG,2		; устанавливаем флаг, можно работать

	BCF PORTA,2		; отключаем подтягивающие резисторы

	ADDWF PCL,F		; таблица
	GOTO SW00
	GOTO SW01
	GOTO SW10
	GOTO SW11
SW00			; непрерывно
	MOVLW D'0'		; молчим последние 0 с
	MOVWF TX_OFF		;
	MOVLW D'30'		; цикл 60 сек
	GOTO END_SW
SW01			; цикл 30сек/120сек
	MOVLW D'60'		; молчим последние 120 с
	MOVWF TX_OFF		;
	MOVLW D'75'		; цикл 150 сек
	GOTO END_SW
SW10			; цикл 1 мин/1 мин
	MOVLW D'30'		; молчим последние 60 с
	MOVWF TX_OFF		;
	MOVLW D'60'		; цикл 120 сек
	GOTO END_SW
SW11			; цикл 1 мин/4 мин
	MOVLW D'120'		; молчим последние 4 m
	MOVWF TX_OFF		;
	MOVLW D'150'		; цикл 5 m

END_SW
	MOVWF TX_ALL		;
	MOVWF TX_ALL_CNT	; инициализация	
        DECF TX_ALL_CNT,F	; считаем, что 1 прерывание уже случилось

;==================================================================
; Окончание инициализации TIMER1
;

	MOVLW B'11000000'	; разрешить прерывания от периферийных модулей
	MOVWF INTCON

	BSF STATUS,RP0		; bank 1
	BSF PIE1,TMR1IE		; разрешить прерывания от TMR1
	BCF STATUS, RP0		; bank 0	
	BSF T1CON,TMR1ON        ; TMR1 ON


;==================================================================
; Если с момента запуска прошло 5 мин, то при сбросе задержку 
; включения игнорируем

	BTFSC FLAG,3		; FLAG,3 поднимается через 5 м после начала
				; работы
	BSF FLAG,2		; задержка включения не нужна

;==================================================================
; MAIN
; передача последовательности символов
; можно предавать любое количество, 0XFF означает конец последовательности,
; после чего формируется пауза и передача циклически повторяется
;
SEND_MSG
                                ; если автоотключение не нужно, то три 
				; нижеследующих строчки надо закомментировать
	MOVF MIN_CNT,F		; проверяем, не обнулился ли 
	SKPNZ			; счетчик пятиминуток
	GOTO POWER_OFF		; если да, то выключаемся

	BTFSS FLAG,2		; пропустить след, если задержка включения
				; кончилась (1-разрешение работы)
	GOTO FLASH		; мигнуть и sleep

        BTFSS FLAG,0		; если флаг сброшен, то идем спать
	GOTO TO_SLEEP
	
	MOVF SWITCH,W
	MOVWF CHAR_INDEX	; SWITCH -> CHAR_INDEX

GET_MSG
	MOVF CHAR_INDEX,W		
	BCF INTCON,GIE		; запрещаем прерывания
	BSF STATUS, RP0		; bank 1
	MOVWF EEADR		; значение CHAR_INDEX = адресу кода в EEPROM
	BSF EECON1,RD		; разрешаем чтение EEPROM
	MOVF EEDAT,W		; значение ячейки -> регистр W
	BCF STATUS, RP0		; bank 0	 
	BSF INTCON,GIE		; разрешаем прерывания
	;MOVLW 0x06
	MOVWF CW_CHAR		; W -> CW_CHAR	

	MOVLW 0XFF		; конец сообщения?
	SUBWF CW_CHAR,W		;
	SKPNZ
	GOTO END_MSG		; да, перейти к END_MSG

;	MOVLW D'60'		; скорость передачи быстро
;	BTFSS FLAG,4		; устанавливается за 10 с до конца цикла
	MOVLW D'160'		; скорость передачи медленно
	MOVWF CW_SPEED		; чем больше, тем медленней

	CALL SEND_CHAR		; передаем букву и паузу в 3 точки
                                ; или паузу 6 точек, если SPACE
	INCF CHAR_INDEX		; CHAR_INDEX+1	
	GOTO GET_MSG

END_MSG
	CALL WORD_SPACE         ; пауза 6 точек 
	GOTO SEND_MSG		;	

				; время работы закончилось
POWER_OFF			; отсюда выход только через RESET

	CLRF FLAG		; очистка регистра флагов
	CLRF T1CON		; очистить TIMER1 control register, выключаем
				; генератор 32768
	;BCF T1CON,TMR1ON       ; TMR1 OFF
	CLRF INTCON		; запретить прерывания

				; после сброса считаем, что это сброс по питанию
	BSF STATUS, RP0		; bank 1
	BCF PCON,POR		; устанавливаем POR=0
	BCF PCON,BOR		; устанавливаем BOR=0
	BCF STATUS, RP0		; bank 0

TO_SLEEP			;
	CLRF PORTA
	SLEEP
	NOP
	GOTO SEND_MSG
;========================================================================
; индикатор включенной задержки
; мигаем порт A.1
FLASH
	MOVLW D'60'		; скорость передачи 
	MOVWF CW_SPEED		; чем больше, тем медленней
	BSF PORTA,1
	MOVLW 0X01		;
	MOVWF NBR_SPACE		; пауза в 1 точку
	CALL SEND_SPACE		;
	BCF PORTA,1
	GOTO TO_SLEEP
;========================================================================
; SEND_CHAR
; Подпрограмма получает код символа в регистре CW_CHAR, побитно перебирает 
; его, и, в зависимости от состояния бита, передает: тире, если бит = 1;
; точку, если бит = 0.
; Знак передается, пока в слове есть хоть одна единица. Последняя единица
; "съедается", она означает конец слова. 
;
SEND_CHAR
	MOVLW 0X00		; пауза?
	SUBWF CW_CHAR,W		;
	SKPNZ			; 
	GOTO WORD_SPACE

SEND_ONE_CHAR 
        BTFSS FLAG,0		; обрываем передачу, если флаг сброшен
	RETURN

	CLRC			; очистить бит переноса
	RRF CW_CHAR, F		; сдвиг вправо через перенос
				; 
	MOVF CW_CHAR, F         ; проверяем содержимое CW_CHAR, если все "0"
	SKPNZ                   ; то Z=1, выполняем RETURN, иначе пропускаем
	GOTO PAUSE2		; конец буквы
	SKPC			; проверить бит переноса, пропустить, если=1
	GOTO SEND_A_DIT		; перейти к SEND_A_DIT

SEND_A_DAH			; передаем тире 
	MOVLW 0X03		; 1 тире = 3 точки
	MOVWF NBR_DIT
	MOVLW 0X01		;
	MOVWF NBR_SPACE		; после тире - пауза в 1 точку
	BSF PORTA,0		; включаем PORT A.2
	CALL SEND_TONE		; генериуем звук, оно же - пауза
	BCF PORTA,0		; выключаем PORT A.2
	CALL SEND_SPACE
	GOTO SEND_ONE_CHAR

SEND_A_DIT 
	MOVLW 0X01		; передаем точку
	MOVWF NBR_DIT
	MOVWF NBR_SPACE		; после точки - пауза в 1 точку
	BSF PORTA,0		; включаем PORT A.2
	CALL SEND_TONE          ; генерируем звук, оно же - пауза
	BCF PORTA,0		; выключаем PORT A.2
	CALL SEND_SPACE
	GOTO SEND_ONE_CHAR

PAUSE2
	MOVLW D'2'		; пауза в 2 точки после буквы	
	MOVWF NBR_SPACE		; 
	CALL SEND_SPACE         ;
	RETURN

WORD_SPACE
	MOVLW D'6'		; пауза в 6 точек между словами	
	MOVWF NBR_SPACE		; 
	CALL SEND_SPACE         ;
	RETURN

;==================================================================
; SEND_TONE
; Подпрограмма осуществляет задержку и одновременно формирует сигнал
; звуковой частоты (порт A.1)
;

SEND_TONE
 
	MOVF NBR_DIT, W		; NBR_DIT кол-во пропускаемых точек 
	MOVWF CTR_NBR		; 

DIT_LENGTH 
	MOVF CW_SPEED, W	; CW_SPEED скорость передачи
	MOVWF CTR_DIT		;

START_CYCLE 
	BSF PORTA,1		; A.1=1 в начале цикла
	MOVF SET_TONE,W		; 
	MOVWF TONE		; заносим значение в счетчик цикла задержки

HIGH_HALF 
	DECFSZ TONE, F		; считаем до нуля
	GOTO HIGH_HALF
	BCF PORTA,1		; A.1=0 в конце цикла

	MOVF SET_TONE,W		;
	MOVWF TONE

LOW_HALF 
	DECFSZ TONE, F		; 
	GOTO LOW_HALF
	DECFSZ CTR_DIT, F	;
	GOTO START_CYCLE
	DECFSZ CTR_NBR, F
	GOTO DIT_LENGTH		; 
	RETURN			; 

;================================================================
; SEND_SPACE
; Делает тоже самое, что и SEND_TONE, только вместо команд управления
; портами стоит команда NOP
;

SEND_SPACE
 
	MOVF NBR_SPACE, W	; 
	MOVWF CTR_NBR

DIT_LENGTH_SP 
	MOVF CW_SPEED, W	; 
	MOVWF CTR_DIT

START_CYCLE_SP
	NOP
	MOVF SET_TONE,W
	MOVWF TONE		; 

HIGH_HALF_SP 
	DECFSZ TONE, F		; 
	GOTO HIGH_HALF_SP
	NOP
	MOVF SET_TONE,W
	MOVWF TONE

LOW_HALF_SP 
	DECFSZ TONE, F		; 
	GOTO LOW_HALF_SP
	DECFSZ CTR_DIT, F	;
	GOTO START_CYCLE_SP
	DECFSZ CTR_NBR, F
	GOTO DIT_LENGTH_SP	; 
	RETURN			; 

;==================================================================
;==================================================================
; Идентификатор
	ORG  0x2000	; стартовый адрес

        DATA 0x0132
        DATA 0xF321
        DATA 0x0000
        DATA 0x0000

;==================================================================
; Слово конфигурации
	ORG  0x2007	; стартовый адрес

;	DATA 0x31E4
	DATA 0x1024	; вкл защиту данных
;	DATA 0x11A4
;==================================================================
; Запись в EEPROM при программировании
; Переключателем адресуется номер ячейки, кратный 4. Соответственно, маяк
; может передавать последовательно три символа Морзе, четвертым обязательно
; должен быть EOM
; В последнюю адресуемую ячейку можно записать большее количество символов

	ORG  0X2100	; стартовый адрес

	DATA 0x07	; M --    00000111
	DATA 0x0F	; O ---   00001111
        DATA 0xFF	; EOM     11111111
        DATA 0xFF	; EOM     11111111

	DATA 0x07	; M --    00000111
	DATA 0x0F	; O ---   00001111
        DATA 0x02	; E .     00000010  	
        DATA 0xFF	; EOM     11111111

	DATA 0x07	; M --    00000111
	DATA 0x0F	; O ---   00001111
	DATA 0x04	; I ..    00000100
        DATA 0xFF	; EOM     11111111

	DATA 0x07	; M --    00000111
	DATA 0x0F	; O ---   00001111
	DATA 0x08	; S ...   00001000
        DATA 0xFF	; EOM     11111111

	DATA 0x07	; M --    00000111
	DATA 0x0F	; O ---   00001111
	DATA 0x10	; H ....  00010000
        DATA 0xFF	; EOM     11111111

	DATA 0x07	; M --    00000111
	DATA 0x0F	; O ---   00001111
	DATA 0x20	; 5 ..... 00100000
        DATA 0xFF	; EOM     11111111

	DATA 0x07	; M --    00000111
	DATA 0x0F	; O ---   00001111
	DATA 0x03	; T -     00000011
        DATA 0xFF	; EOM     11111111

	DATA 0x0A	; R .-.   
        DATA 0x06	; A .-
        DATA 0x3E	; 1 .----
        DATA 0x06	; A .-
        DATA 0x07	; M --
        DATA 0x0F	; O ---
        DATA 0xFF	; EOM     11111111

	END

Вариант для управления радиостанцией, 30с/120с; 60с/60с; 1м/4м, передача позывного

Контроллер маяка на PIC16F630 в корпусе
Схема для управления маяком для городской охоты, возможно подключение обычной радиостанции
; на 11 ногу можно повесить управление TX (высокий уровень при передаче)

; PIC16F630
; WDT off, intLC, MCLR on, BOR on, PWRTE on
;
	list	P=16F630
	radix	HEX

;====================================================================
; именование пользовательских регистров
;	
 	CBLOCK	0X20	; начальный адрес пользовательских регистров
        TMPW		; временный регистр для хранения W во время прерывания
	TMPS		; временный регистр для хранения STATUS                                                    
	SEC_CNT		; счетчик пар секунд
	MIN_CNT 	; счетчик минут (пятиминуток, автовыключение)
	FLAG		; регистр флагов:
			; FLAG,0 разрешает передачу позывного в свое время
			; FLAG,2 флаг задержки включения (1-можно работать)
                        ; FLAG,3 флаг взводится через 5 мин после начала работы
			; и отменяет задержку включения при сбросе
			; FLAG,4 флаг устанавливается за 10 сек до конца цикла


	DELAY		; счетчик пятиминуток, задержка включения
	TX_ALL_CNT	; счетчик пар секунд в цикле
	TX_OFF		; с какой секунды пауза
	TX_ALL		; сколько пар секунд в цикле

	SWITCH		; состояние переключателя
	CHAR_INDEX	; номер передаваемого символа

	CW_SPEED	; скорость передачи

; процедура SEND_TONE
	NBR_DIT		; NBR_DIT кол-во пропускаемых точек
	CTR_NBR		; счетчик пропускаемых точек
	TONE		; счетчик частоты
	SET_TONE	; установка тона передаваемого сигнала
; процедура SEND_SPACE
	NBR_SPACE	; колво пропускаемых точек
	CTR_DIT		; счетчик пропускаемых точек
; процедура SEND_ONE_CHAR
	CW_CHAR		; передаваемый символ
	ENDC


;
; Именование регистров микроконтроллера
;
CMCON		EQU	0X19	; регистр контроля компаратора
TMR0		EQU	0X01	; timer0
TMR1L		EQU	0X0E	; timer1 младший байт
TMR1H		EQU	0X0F	; timer1 старший байт     
T1CON		EQU	0X10	; timer1 control register
PCL		EQU	0X02	; программный счетчик
STATUS		EQU	0X03	; регистр status
FSR		EQU	0X04	; указатель адреса в памяти данных
PORTA		EQU	0X05	; порт A
PORTC		EQU	0X07	; порт C
PCLATH		EQU	0X0A	; верхние 5 бит программного счетчика
INTCON		EQU	0X0B	; регистр контроля прерываний
TRISA		EQU	0X85	; управляющий регистр порта A
TRISC		EQU	0X87	; управляющий регистр порта C 
OPTION_REG	EQU	0X81	; регистр option
EEADR		EQU	0X9B	; адресный регистр EEPROM
EECON1		EQU	0X9C	; содержит бит RD
EEDAT		EQU	0X9A	; прочитанные из EEPROM данные
PCON		EQU	0X8E	; регистр power control
PIE1		EQU	0X8C	; регистр контроля периферийных прерываний
PIR1		EQU	0X0C	; регистр флагов прерываний от 
				; периферийных модулей

;
; присвоение значений символьным константам
;
RP0		EQU	0X05	; бит-указатель страницы данных в STATUS
W		EQU	0X00	; file register designator = W
F		EQU	0X01	; file register designator = F 
Z		EQU	0X02	; бит нуля в STATUS 
C		EQU	0X00	; бит преноса в STATUS
RD		EQU	0X00	; инициализация чтения EEPROM
POR		EQU	0X01	; бит POR регистра PCON обнуляется, если был
				; сброс по включению питания
BOR		EQU	0X00	; сброс по снижению питания
TMR1IF		EQU	0X00	; бит переполнения TMR1 in register PIR1
TMR1ON		EQU	0X00	;
GIE		EQU	0X07	;
TMR1IE		EQU	0X00	; бит разрешения прерываний от TMR1
PON		EQU	0X00	; POWER ON IN FLAG
;
;=================================================================
; vector table
;
	ORG 0X000		; стартовый адрес	
	GOTO START		; 

;==================================================================
; TIMER1 INTERRUPT 
;
	ORG 0X004		; адрес	прерывания
	MOVWF TMPW		; сохраняем W
	SWAPF STATUS,W
	MOVWF TMPS		; сохраняем STATUS
	
	BTFSC PIR1,0		; прерывание от TMR1?
	GOTO T1_INT		; да
        NOP			; обработчик левого прерывания
	GOTO END_ISR		; 

T1_INT
	MOVF TX_ALL_CNT,W	; вычитание
	SUBWF TX_OFF,W		; TX_OFF-TX_ALL_CNT
	
	BCF FLAG,0		;
	SKPC			; пропустить, если результат >=0
	BSF FLAG,0		;


	





;	MOVF TX_ALL_CNT,W	; ускоряемся за 10 сек до конца цикла
;	SUBLW D'125'		; ставим флаг, по которому во время передачи
;	SKPNZ			; меняем скорость
;	BSF FLAG,4		; только при 5 мин цикле

				; использовать либо верхнее, либо нижнее

	;SUBLW D'250'		; а это костыль для ускорения за 10 сек
	;SKPNZ			; до конца любого цикла, даже если
	;BSF FLAG,4		; работаем непрерывно

	DECFSZ TX_ALL_CNT,F	; TX_ALL_CNT-1, пропустить, если 0
	GOTO POP_TX
	MOVF TX_ALL,W		; восстанавливаем
	MOVWF TX_ALL_CNT	;

;	BCF FLAG,4		; в конце цикла сбросить флаг ускорения
POP_TX

       	DECFSZ SEC_CNT, F	; SEC_CNT-1
	GOTO POP		; 
	MOVLW D'150'		; 300 секунд = 5 мин
	MOVWF SEC_CNT
	
	BTFSS FLAG,2		; если задержка активирована, то
	BSF FLAG,3		; через 5 мин после запуска поднимаем флаг
				; отмены задержки включения

	BTFSC FLAG,2		; если флаг разрешения работы установлен, начинаем отсчет 
				; задержки отключения
	DECF MIN_CNT,F		; MIN_CNT-1 минуты работы считаем после 
				; окончании задержки включения


	DECFSZ DELAY,F		; DELAY-1, пропустить след, если 0
	GOTO POP		; задержка окончилась
	BSF FLAG,2		; устанавливаем флаг разрешения работы	


POP	
	BCF PIR1,0		; сброс флага переполнения

END_ISR
	SWAPF TMPS,W		; восстанавливаем регистры W and SATUS
	MOVWF STATUS		;
	SWAPF TMPW,F		;
	SWAPF TMPW,W		;
	RETFIE			; возврат из прерывания

;==================================================================
;  Начало основной программы 
;==================================================================
START	
	MOVLW B'10001110'       ;
	BSF STATUS, RP0		; bank 1
	MOVWF OPTION_REG	; инициализация регистра option
	BCF STATUS, RP0		; bank 0	
			
	CLRF PORTA		; очистка порта A 
	CLRF PORTC		; очистка порта C

	MOVLW B'00000111'	; 
	MOVWF CMCON		; запрещаем работу компаратора

	BSF STATUS, RP0		; bank 1
	MOVLW B'00000000'	; 
	MOVWF TRISA		; порт A - все выходы
	MOVLW B'11111111'	; 
	MOVWF TRISC		; порт C - все входы
	BCF STATUS, RP0		; bank 0	

	CLRF TMR0		; на всякий случай. Говорят, надо...
	CLRWDT			; сбрасываем WDT


;==================================================================
; инициализация TMR1
;
	CLRF T1CON		; очистить TIMER1 control register
	CLRF TMR1H		; очистить верхний байт TMR1
	CLRF TMR1L		; очистить нижний байт TMR1
	CLRF INTCON		; запретить прерывания
	BSF STATUS,RP0		; bank 1
	CLRF PIE1		; очистить рег контроля периферийных прерываний
	BCF STATUS, RP0		; bank 0	
	CLRF PIR1		; очистить рег флагов периферийных прерываний
	MOVLW B'00001110'	; инициализация TIMER1 control register
	MOVWF T1CON		; с этого момента генератор 32.768 включен


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

	MOVLW D'150'		; инициализация счетчика пар секунд
	MOVWF SEC_CNT		; 150 пар = 300 сек = 5 мин
        DECF SEC_CNT,F		; имитируем прерывание

	;MOVLW D'2'		; сколько пятиминуток будем работать	
	MOVLW D'96'		; сколько пятиминуток будем работать
	MOVWF MIN_CNT		; 96х5=8 час

;	MOVLW D'2'		; сколько пятиминуток задержка включения
	MOVLW D'24'		; сколько пятиминуток задержка включения
	MOVWF DELAY		; 24х5=120 мин

	MOVLW D'178'		; тон звука, 178 ~ 1000 Гц
	MOVWF SET_TONE		; чем больше, тем ниже частота

	BSF FLAG,0		; поднимаем флаг

;	BCF FLAG,4


;==================================================================
; если это включение питания, то выполняется задержка для
; гарантированного запуска генератора 32768 и его инициализация
; если другой сброс, то инициализация и задержка пропускаются
;
	BSF STATUS, RP0		; bank 1
	MOVF PCON,W		; PCON -> W
	BCF STATUS, RP0		; bank 0

	MOVWF TMPW		; W -> TMPW
	BTFSS TMPW,POR		; проверяем состояние POR, если 0, то был сброс
	GOTO DELAY_START	; по включению - задержка однозначно нужна
	BTFSC TMPW,BOR          ; а это был сброс по снижению напр питания
        GOTO SKIP_DELAY         ; или не был...
	
DELAY_START

	BCF FLAG,3		; при первом включении очистить FLAG,3

	; задержка 
	MOVLW D'255'		; скорость передачи 
	MOVWF CW_SPEED		; чем больше, тем медленней
	 
 	MOVLW 0X80	
	MOVWF CW_CHAR		; 
        CALL SEND_ONE_CHAR	; в качестве задержки предаем 7 точек

	BSF STATUS, RP0		; bank 1
	BSF PCON,POR		; устанавливаем POR=1
	BSF PCON,BOR		; устанавливаем BOR=1
	BCF STATUS, RP0		; bank 0

	SLEEP			; ожидаем запуск

SKIP_DELAY


;==================================================================
; читаем переключатель
;

	BSF PORTA,2		; на 11 ноге висят подтягивающие резисторы,
				; подключенные к переключателю
				; после считывания напряжение с переключателя
				; снимается для экономии энергии


        MOVF PORTC,W		; читаем порт C
	ANDLW B'00011100'	; маска 
	MOVWF SWITCH		; сохраняем состояние переключателя

        MOVF PORTC,W		; читаем порт C
	ANDLW B'00000011'	; маска двух младших бит

	BCF FLAG,2		; обнуляем флаг задержки
	BTFSC PORTC,5		; если перекл. on (на землю, 0) пропуск. след.
	BSF FLAG,2		; устанавливаем флаг, можно работать

	BCF PORTA,2		; отключаем подтягивающие резисторы

	ADDWF PCL,F		; таблица
	GOTO SW00
	GOTO SW01
	GOTO SW10
	GOTO SW11
SW00			; непрерывно
	MOVLW D'0'		; молчим последние 0 с
	MOVWF TX_OFF		;
	MOVLW D'30'		; цикл 60 сек
	GOTO END_SW
SW01			; цикл 30сек/120сек
	MOVLW D'60'		; молчим последние 120 с
	MOVWF TX_OFF		;
	MOVLW D'75'		; цикл 150 сек
	GOTO END_SW
SW10			; цикл 1 мин/1 мин
	MOVLW D'30'		; молчим последние 60 с
	MOVWF TX_OFF		;
	MOVLW D'60'		; цикл 120 сек
	GOTO END_SW
SW11			; цикл 1 мин/4 мин
	MOVLW D'120'		; молчим последние 4 m
	MOVWF TX_OFF		;
	MOVLW D'150'		; цикл 5 m

END_SW
	MOVWF TX_ALL		;
	MOVWF TX_ALL_CNT	; инициализация	
        DECF TX_ALL_CNT,F	; считаем, что 1 прерывание уже случилось

;==================================================================
; Окончание инициализации TIMER1
;

	MOVLW B'11000000'	; разрешить прерывания от периферийных модулей
	MOVWF INTCON

	BSF STATUS,RP0		; bank 1
	BSF PIE1,TMR1IE		; разрешить прерывания от TMR1
	BCF STATUS, RP0		; bank 0	
	BSF T1CON,TMR1ON        ; TMR1 ON


;==================================================================
; Если с момента запуска прошло 5 мин, то при сбросе задержку 
; включения игнорируем

	BTFSC FLAG,3		; FLAG,3 поднимается через 5 м после начала
				; работы
	BSF FLAG,2		; задержка включения не нужна

;==================================================================
; MAIN
; передача последовательности символов
; можно предавать любое количество, 0XFF означает конец последовательности,
; после чего формируется пауза и передача циклически повторяется
;
SEND_MSG
                                ; если автоотключение не нужно, то три 
				; нижеследующих строчки надо закомментировать
	MOVF MIN_CNT,F		; проверяем, не обнулился ли 
	SKPNZ			; счетчик пятиминуток
	GOTO POWER_OFF		; если да, то выключаемся

	BTFSS FLAG,2		; пропустить след, если задержка включения
				; кончилась (1-разрешение работы)
	GOTO FLASH		; мигнуть и sleep

        BTFSS FLAG,0		; если флаг сброшен
	BSF PORTA,2		; TX выключаем

        BTFSS FLAG,0		; если флаг сброшен, то идем спать
	GOTO TO_SLEEP
	

	BSF PORTA,2		; на 11 ногу можно повесить управление TX 


	MOVF SWITCH,W
	MOVWF CHAR_INDEX	; SWITCH -> CHAR_INDEX

GET_MSG
	MOVF CHAR_INDEX,W		
	BCF INTCON,GIE		; запрещаем прерывания
	BSF STATUS, RP0		; bank 1
	MOVWF EEADR		; значение CHAR_INDEX = адресу кода в EEPROM
	BSF EECON1,RD		; разрешаем чтение EEPROM
	MOVF EEDAT,W		; значение ячейки -> регистр W
	BCF STATUS, RP0		; bank 0	 
	BSF INTCON,GIE		; разрешаем прерывания
	;MOVLW 0x06
	MOVWF CW_CHAR		; W -> CW_CHAR	

	MOVLW 0XFF		; конец сообщения?
	SUBWF CW_CHAR,W		;
	SKPNZ
	GOTO END_MSG		; да, перейти к END_MSG

;	MOVLW D'60'		; скорость передачи быстро
;	BTFSS FLAG,4		; устанавливается за 10 с до конца цикла
;
	MOVLW D'80'		; скорость передачи медленно
	MOVWF CW_SPEED		; чем больше, тем медленней

	CALL SEND_CHAR		; передаем букву и паузу в 3 точки
                                ; или паузу 6 точек, если SPACE
	INCF CHAR_INDEX		; CHAR_INDEX+1	
	GOTO GET_MSG

END_MSG
	CALL WORD_SPACE         ; пауза 6 точек 
	GOTO SEND_MSG		;	

				; время работы закончилось
POWER_OFF			; отсюда выход только через RESET

	CLRF FLAG		; очистка регистра флагов
	CLRF T1CON		; очистить TIMER1 control register, выключаем
				; генератор 32768
	;BCF T1CON,TMR1ON       ; TMR1 OFF
	CLRF INTCON		; запретить прерывания

				; после сброса считаем, что это сброс по питанию
	BSF STATUS, RP0		; bank 1
	BCF PCON,POR		; устанавливаем POR=0
	BCF PCON,BOR		; устанавливаем BOR=0
	BCF STATUS, RP0		; bank 0

TO_SLEEP			;
	CLRF PORTA
	SLEEP
	NOP
	GOTO SEND_MSG
;========================================================================
; индикатор включенной задержки
; мигаем порт A.1
FLASH
	MOVLW D'60'		; скорость передачи 
	MOVWF CW_SPEED		; чем больше, тем медленней
	BSF PORTA,1
	MOVLW 0X01		;
	MOVWF NBR_SPACE		; пауза в 1 точку
	CALL SEND_SPACE		;
	BCF PORTA,1
	GOTO TO_SLEEP
;========================================================================
; SEND_CHAR
; Подпрограмма получает код символа в регистре CW_CHAR, побитно перебирает 
; его, и, в зависимости от состояния бита, передает: тире, если бит = 1;
; точку, если бит = 0.
; Знак передается, пока в слове есть хоть одна единица. Последняя единица
; "съедается", она означает конец слова. 
;
SEND_CHAR
	MOVLW 0X00		; пауза?
	SUBWF CW_CHAR,W		;
	SKPNZ			; 
	GOTO WORD_SPACE

SEND_ONE_CHAR 
        BTFSS FLAG,0		; обрываем передачу, если флаг сброшен
	RETURN

	CLRC			; очистить бит переноса
	RRF CW_CHAR, F		; сдвиг вправо через перенос
				; 
	MOVF CW_CHAR, F         ; проверяем содержимое CW_CHAR, если все "0"
	SKPNZ                   ; то Z=1, выполняем RETURN, иначе пропускаем
	GOTO PAUSE2		; конец буквы
	SKPC			; проверить бит переноса, пропустить, если=1
	GOTO SEND_A_DIT		; перейти к SEND_A_DIT

SEND_A_DAH			; передаем тире 
	MOVLW 0X03		; 1 тире = 3 точки
	MOVWF NBR_DIT
	MOVLW 0X01		;
	MOVWF NBR_SPACE		; после тире - пауза в 1 точку
	BSF PORTA,0		; включаем PORT A.2
	CALL SEND_TONE		; генериуем звук, оно же - пауза
	BCF PORTA,0		; выключаем PORT A.2
	CALL SEND_SPACE
	GOTO SEND_ONE_CHAR

SEND_A_DIT 
	MOVLW 0X01		; передаем точку
	MOVWF NBR_DIT
	MOVWF NBR_SPACE		; после точки - пауза в 1 точку
	BSF PORTA,0		; включаем PORT A.2
	CALL SEND_TONE          ; генерируем звук, оно же - пауза
	BCF PORTA,0		; выключаем PORT A.2
	CALL SEND_SPACE
	GOTO SEND_ONE_CHAR

PAUSE2
	MOVLW D'2'		; пауза в 2 точки после буквы	
	MOVWF NBR_SPACE		; 
	CALL SEND_SPACE         ;
	RETURN

WORD_SPACE
	MOVLW D'6'		; пауза в 6 точек между словами	
	MOVWF NBR_SPACE		; 
	CALL SEND_SPACE         ;
	RETURN

;==================================================================
; SEND_TONE
; Подпрограмма осуществляет задержку и одновременно формирует сигнал
; звуковой частоты (порт A.1)
;

SEND_TONE
 
	MOVF NBR_DIT, W		; NBR_DIT кол-во пропускаемых точек 
	MOVWF CTR_NBR		; 

DIT_LENGTH 
	MOVF CW_SPEED, W	; CW_SPEED скорость передачи
	MOVWF CTR_DIT		;

START_CYCLE 
	BSF PORTA,1		; A.1=1 в начале цикла
	MOVF SET_TONE,W		; 
	MOVWF TONE		; заносим значение в счетчик цикла задержки

HIGH_HALF 
	DECFSZ TONE, F		; считаем до нуля
	GOTO HIGH_HALF
	BCF PORTA,1		; A.1=0 в конце цикла

	MOVF SET_TONE,W		;
	MOVWF TONE

LOW_HALF 
	DECFSZ TONE, F		; 
	GOTO LOW_HALF
	DECFSZ CTR_DIT, F	;
	GOTO START_CYCLE
	DECFSZ CTR_NBR, F
	GOTO DIT_LENGTH		; 
	RETURN			; 

;================================================================
; SEND_SPACE
; Делает тоже самое, что и SEND_TONE, только вместо команд управления
; портами стоит команда NOP
;

SEND_SPACE
 
	MOVF NBR_SPACE, W	; 
	MOVWF CTR_NBR

DIT_LENGTH_SP 
	MOVF CW_SPEED, W	; 
	MOVWF CTR_DIT

START_CYCLE_SP
	NOP
	MOVF SET_TONE,W
	MOVWF TONE		; 

HIGH_HALF_SP 
	DECFSZ TONE, F		; 
	GOTO HIGH_HALF_SP
	NOP
	MOVF SET_TONE,W
	MOVWF TONE

LOW_HALF_SP 
	DECFSZ TONE, F		; 
	GOTO LOW_HALF_SP
	DECFSZ CTR_DIT, F	;
	GOTO START_CYCLE_SP
	DECFSZ CTR_NBR, F
	GOTO DIT_LENGTH_SP	; 
	RETURN			; 

;==================================================================
;==================================================================
; Идентификатор
	ORG  0x2000	; стартовый адрес

        DATA 0x0132
        DATA 0xF321
        DATA 0x0000
        DATA 0x0000

;==================================================================
; Слово конфигурации
	ORG  0x2007	; стартовый адрес

;	DATA 0x31E4
	DATA 0x1024	; вкл защиту данных
;	DATA 0x11A4
;==================================================================
; Запись в EEPROM при программировании
; Переключателем адресуется номер ячейки, кратный 4. Соответственно, маяк
; может передавать последовательно три символа Морзе, четвертым обязательно
; должен быть EOM
; В последнюю адресуемую ячейку можно записать большее количество символов

	ORG  0X2100	; стартовый адрес

	DATA 0x07	; M --    00000111
	DATA 0x0F	; O ---   00001111
        DATA 0xFF	; EOM     11111111
        DATA 0xFF	; EOM     11111111

	DATA 0x07	; M --    00000111
	DATA 0x0F	; O ---   00001111
        DATA 0x02	; E .     00000010  	
        DATA 0xFF	; EOM     11111111

	DATA 0x07	; M --    00000111
	DATA 0x0F	; O ---   00001111
	DATA 0x04	; I ..    00000100
        DATA 0xFF	; EOM     11111111

	DATA 0x07	; M --    00000111
	DATA 0x0F	; O ---   00001111
	DATA 0x08	; S ...   00001000
        DATA 0xFF	; EOM     11111111

	DATA 0x07	; M --    00000111
	DATA 0x0F	; O ---   00001111
	DATA 0x10	; H ....  00010000
        DATA 0xFF	; EOM     11111111

	DATA 0x07	; M --    00000111
	DATA 0x0F	; O ---   00001111
	DATA 0x20	; 5 ..... 00100000
        DATA 0xFF	; EOM     11111111

	DATA 0x07	; M --    00000111
	DATA 0x0F	; O ---   00001111
	DATA 0x03	; T -     00000011
        DATA 0xFF	; EOM     11111111

	DATA 0x09	; D
	DATA 0x02	; E
	DATA 0x00	; PAUSE
	DATA 0x0A	; R .-.   
        DATA 0x06	; A .-
        DATA 0x3E	; 1 .----
        DATA 0x06	; A .-
        DATA 0x07	; M --
        DATA 0x0E	; W ---
	DATA 0x00	; PAUSE
	DATA 0x11	; B	
	DATA 0x02	; E
	DATA 0x06	; A
	DATA 0x15	; C	
	DATA 0x0F	; O ---   00001111
	DATA 0x05	; N	
        DATA 0xFF	; EOM     11111111

	END

Программирование кодов Морзе

DATA 0x3F	; 0 ----- 00111111
DATA 0x3E	; 1 .---- 00111110  	
DATA 0x3C	; 2 ..--- 00111100
DATA 0x38	; 3 ...-- 00111000	
DATA 0x30	; 4 ....- 00110000
DATA 0x20	; 5 ..... 00100000
DATA 0x21	; 6 -.... 00100001
DATA 0x23	; 7 --... 00100011
DATA 0x27	; 8 ---.. 00100111
DATA 0x2F	; 9 ----. 00101111

DATA 0x06	; A .-    00000110	
DATA 0x11	; B -...  00010001
DATA 0x15	; C -.-.  00010101
DATA 0x09	; D -..   00001001
DATA 0x02	; E .     00000010	
DATA 0X14	; F ..-.  00010100
DATA 0X0B	; G --.   00001011
DATA 0x10	; H ....  00010000
DATA 0x04	; I ..    00000100
DATA 0x1E	; J .---  00011110
DATA 0x0D	; K -.-   00001101	
DATA 0x12	; L .-..  00010010
DATA 0x07	; M --    00000111
DATA 0x05	; N -.    00000101
DATA 0x0F	; O ---   00001111
DATA 0x16	; P .--.  00010110
DATA 0x1B	; Q --.-  00011011
DATA 0x0A	; R .-.   00001010
DATA 0x08	; S ...   00001000
DATA 0x03	; T -     00000011
DATA 0x0C	; U ..-   00001100	
DATA 0x18	; V ...-  00011000
DATA 0x0E	; W .--   00001110
DATA 0X19	; X -..-  00011001
DATA 0X1D	; Y -.--  00011101
DATA 0X13	; Z --..  00010011
DATA 0x29	; / -..-. 00101001	
DATA 0x00	; PAUSE   00000000
DATA 0xFF	; EOM     11111111