Материал из EPIRB Wiki
RA1AMO (обсуждение | вклад) (→Контроллер маяка на PIC16F630) |
RA1AMO (обсуждение | вклад) (→Версия прошивки 3.2, цикл 30с/120с; 60с/60с; 1м/4м) |
||
| Строка 1269: | Строка 1269: | ||
</pre> | </pre> | ||
| − | ===Версия прошивки 3.2, | + | ===Версия прошивки 3.2, циклы 30с/120с; 60с/60с; 1м/4м=== |
<pre> | <pre> | ||
| Строка 1909: | Строка 1909: | ||
END | END | ||
</pre> | </pre> | ||
| + | |||
| + | |||
| + | |||
| + | Cntrl_spb_amw.gif | ||
Версия 20:02, 15 июня 2016
Содержание
Контроллер маяка на PIC16F630
Версия прошивки 3.0, циклы 30с/30с; 60с/60с; 1м/4м
;-Передает в режиме лисы код Морзе (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м
;-Передает в режиме лисы код Морзе (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
Cntrl_spb_amw.gif

