Материал из EPIRB Wiki
Содержание
Контроллер маяка на 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
Вариант для управления радиостанцией, 30с/120с; 60с/60с; 1м/4м, передача позывного
; на 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