9zip.ru - технологии для людей
9zip.ru Инструкции Интерфейсный процессор PIC16C65

Программа для периферийного процессора на базе PIC16C65, который планировалось использовать в новой модификации одного из приборов.

;2345678901234567890123456789012345678901234567890123456789012345678901234567890
; 1 2 3 4 5 6 7 8
; Программа для периферийного процессора на базе PIC16C65 в новой модификации
; прибора СК2301. Версия от 25 июня 1997.
;
; (C)1997 Alexander Trush
; Date: 6 Jule 1997

LIST P=16C65

INCLUDE "C:\PROGRA~1\MPLAB\P16C65.INC"
INCLUDE "DATAMEM.H"

ORG 0
GOTO Main
Main CALL PortINI ; Инициализация портов и включение +5В
GOTO OFF ; И СРАЗУ В РЕЖИМ СНА (по просьбе Ан.Скакуна)
; =============================================================================
; Обработчик прерываний общий для всех типов прерываний
; =============================================================================
ORG 4
MOVWF W_TEMP ; Сохранение W(TEMP_W должен быть в обоих банках)
SWAPF STATUS,W ; Сохранение статуса в W
BCF STATUS,RP0 ; Установка нулевого банка
MOVWF STATUS_TEMP ; Сохранение статуса в нулевом банке
; ==============================
; Возможны следующие причины прерываний:
; - прерывание паралельного порта
; - прерывание TMR1IF от ТМК1 (~2..14 Гц)
; ==============================
MOVF Ident,W ; Сохраним содержимое Ident при входе
XORLW 0xFF ; предварительно инвертировав его
MOVWF temp_Ident

;---------
BTFSS PIR1,TMR2IF ; Есть ли прерывание от таймера ╧2? (100 Гц)
GOTO noTMR2int
BCF PIR1,TMR2IF

CALL TestKeyOFF ; Работа с клавишей "ВКЛ", проверка батареи
CALL KeyScan ; Сканирование клавиатуры
; =============================================================================
; Работа с таймерами
; =============================================================================
Timers BTFSS MyFlags,ProgTimerOn; Включен ли програм. таймера?
GOTO TMR_L1
DECFSZ ProgramTimer,F ; Истёк ли заданный интервал?
GOTO TMR_L1

BTFSC MyFlags,PushedOFF ; Если таймер запущен из-за нажатия клавиши
GOTO OFF ; "ВКЛ", то после выдержки отключение

BSF Ident,TimerEvent ; Установка прерывания по прогр. таймеру
BCF MyFlags,ProgTimerOn; Останов программного таймера

TMR_L1 BTFSS MyFlags,SoundTimerOn ; Активизирован таймер звукового сигнала?
GOTO TMR_L2
DECFSZ SoundCounter,F ;Истёк ли заданный интервал?
GOTO TMR_L2

BTFSS MyFlags,SoundOn ; Если включил звук хост - нельзя убрать
BSF Key_MaskB,O_SND ; Снять звуковой сигнал
BCF MyFlags,SoundTimerOn ; Останов таймера звукового сигнала

TMR_L2 DECFSZ TimerFiftienth,F ; Обновление счетчика реального времени
GOTO TMR_Exit ; каждые 2 Герца

MOVLW .50
MOVWF TimerFiftienth

; BTFSS MyFlags,Inhibit2HzInt ;Если разрешено, то...
BSF Ident,Tick2HzEvent; ..установка прерывания по "тику 2Гц"

INCF Timer2HzLow,F ; Инкремент счетчика реального времени (16 бит)
SKPNZ
INCF Timer2HzHigh,F
TMR_Exit
noTMR2int
; -----------------------------------------------------------------------------
;%%%%%%%%%%%%%%%%%%%%%%%%%%%% EXIT INT %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
MOVF temp_Ident,W ;Если необходимо, сформировать прерывание хосту
ANDWF Ident,W
ANDLW 0x0F
SKPZ
BCF PORTC,5 ; ----_-- ~1 us
BSF PORTC,5 ; ----_-- ~1 us

SWAPF STATUS_TEMP,W ; Восстановление статусного регистра
MOVWF STATUS
SWAPF W_TEMP,F ; Восстановление аккумулятора
SWAPF W_TEMP,W ; Выход с разрешением прерывания
RETFIE

SwitchTable ; Переход на соответствующую подпрограмму обработки
; обращения к регистрам периферийного процессора
BCF PORTC,EW ; EW=0 ---___ (клавиатура при этом недоступна)
CLRF PCLATH
MOVF PORTA,W
ANDLW 7 ; ;;;; Пока не различаем старший бит адреса (0x0F
BTFSC PORTE,1 ; сигнал RE1/WR==0?
ADDLW 0x10 ; если нет, значит чтение (+16)
ADDWF PCL,F

GOTO WR3E0
GOTO WR3E2
GOTO WR3E4
GOTO WR3E6
GOTO WR3E8
GOTO WR3EA
GOTO WR3EC
GOTO WR3EE

GOTO WR3F0
GOTO WR3F2
GOTO WR3F4
GOTO WR3F6
GOTO WR3F8
GOTO WR3FA
GOTO WR3FC
GOTO WR3FE

GOTO RD3E0
GOTO RD3E2
GOTO RD3E4
GOTO RD3E6
GOTO RD3E8
GOTO RD3EA
GOTO RD3EC
GOTO RD3EE

GOTO RD3F0
GOTO RD3F2
GOTO RD3F4
GOTO RD3F6
GOTO RD3F8
GOTO RD3FA
GOTO RD3FC
GOTO RD3FB
SwitchTable_end
if (SwitchTable & 0xFF00) != (SwitchTable_end &0xFF00)
error "Таблица находится в двух страницах (256 байт)"
endif
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Start CLRF State ; Начинаем с терминального режима
CLRF ControlReg ; разрешение формирования звука

BSF STATUS,RP0 ; Выбор банка 1
MOVLW .192 ; Настройка TMR2 на генерацию 100 Гц
MOVWF PR2
BCF STATUS,RP0 ; Выбор банка 0

CLRF TMR2
MOVLW b'00010110' ; Постскаллер 1:3, прескаллер 1:16 и запуск
MOVWF T2CON

MOVLW b'00111000' ; Таймер от Fosc/4 , с предделителем 1:8
MOVWF T1CON ; остановлен, осциллятор на 32768 Гц работает

MOVLW 0x55 ; Необходимо для тестирования (нач. значение)
MOVWF CaptureLow
CLRF CaptureHigh

CALL BEEP ; Включаемся с "писком"

BSF STATUS,RP0 ; Выбор банка 1
MOVLW 1<<<
GOTO $-2

CALL SwitchTable ; От туда должны вернуться с установленным EW!
BSF INTCON,GIE ; -----> разрешение прерывания
noPSP
; =========================
CLRF PCLATH

MOVFW State
ANDLW 7
StateTable
ADDWF PCL,F
GOTO TERM ; 0
GOTO DELY ; 1
GOTO OFF ; 2
GOTO ADC ; 3
GOTO DELT ; 4
GOTO TAX ; 5
GOTO TRX ; 6 В этом режиме прерывания от таймера не формируются!
GOTO TERM ; 7
StateTable_end
if (StateTable_end & 0xFF00) != (StateTable &0xFF00)
error "Таблица находится в двух страницах (256 байт)"
endif
;-----------------------------------------------------------------------------
; Работа в терминала и связи (без формирования NMI каждые 0.5 сек)
;
TRX BSF STATUS,RP0 ; Выбор банка 1
BSF TRISC,CLKP ; Линию на ввод...
BCF STATUS,RP0 ; Выбор банка 0
BSF RCSTA,SPEN ; теперь можем передавать по RS
BSF PORTC,TX ; Отключить индикатор "МЕТКА"

BCF MyFlags,ModeChaged ; Сбрасываем признак изменения режима
BTFSC MyFlags,SoundTimerOn ; Активизирован таймер звукового сигнала?
GOTO $-1 ; Если работает, то ждать эго окончания...

BCF INTCON,GIE ; Запрет прерывания на время обработки
BTFSC INTCON,GIE ; обращения хоста ----->
GOTO $-2

BTFSC RCSTA,OERR ; При перезагрузке приёмника сброс последнего,
BCF RCSTA,CREN ; чтобы не заблокировался дальнейший приём
BSF RCSTA,CREN ; данных по каналу RS-232
MOVF RCREG,W ; Очищаем FIFO приёмника
MOVF RCREG,W

TRX_Loop
BTFSC PORTE,2 ; Ждём обращение хоста...
GOTO $-1

CALL SwitchTable ; От туда должны вернуться с установленным EW!

BTFSC PIR1,TMR2IF ; Есть ли прерывание от таймера ╧2? (100 Гц)
CALL TRX_UpdateTimers

BTFSS MyFlags,ModeChaged; Режим был изменён?
GOTO TRX_Loop ; Если нет, то продолжить, иначе

BSF INTCON,GIE ; ----> разрешение прерывания
GOTO MainLoop ; выход из режима!
;------
TRX_UpdateTimers
BCF PIR1,TMR2IF ; Снять флаг прерывания от таймера 100 Гц

CALL TestKeyOFF ; Работа с клавишей "ВКЛ"
BTFSC MyFlags,PushedOFF; Если обнаружено нажатие "ВКЛ", то выход
BSF MyFlags,ModeChaged; (делаем вид, что изменён режим)

DECFSZ TimerFiftienth,F; Реализация делителя на 50 (100Гц/2Гц)
RETURN

MOVLW .50
MOVWF TimerFiftienth
INCF Timer2HzLow,F ;Инкремент счетчика реального времени
SKPNZ ;(16 бит)
INCF Timer2HzHigh,F
RETURN
;-----------------------------------------------------------------------------
; Работа в терминальном режиме
;
TERM GOTO MainLoop

;-----------------------------------------------------------------------------
; Выключение прибора и переход в режим сна...
;
OFF
BCF INTCON,GIE ; Запрет прерывания
BTFSC INTCON,GIE
GOTO $-2

; Разрешение пробуждения по таймеру и нажатию клавиши "ВКЛ"
; не нужно устранение дребезга клавиши "ВКЛ" при включении
; прерывания должны быть запрещены, чтобы не запускался обработчик прерываний

BCF PORTB,O_OFF ; *** Отключаем питание прибора, +5В
BCF T2CON,TMR2ON ; Останов таймера 2

MOVLW b'00111110' ; таймера 1 от осциллятора 32768, с
MOVWF T1CON ; предделителем 1:8
CLRF TMR1L ; Сброс таймера...
CLRF TMR1H
BSF T1CON,TMR1ON ; Начинаем отсчет времени....

BSF STATUS,RP0 ; Выбор банка 1
MOVLW b'101111' ; Всё, что можно, на ввод с целью
MOVWF TRISA ; уменьшения потребления
MOVLW b'11111101' ; На вывод только сигналы O_OFF и ZU/PS ???
MOVWF TRISB
MOVLW b'11111111'
MOVWF TRISC
MOVLW b'00000111' ; Простой порт В/В, чтобы не было TTL буферов
MOVWF TRISE
BCF STATUS,RP0 ; Выбор банка 0

MOVLW 1<<<< С=0
DECFSZ i,F
GOTO roll

MOVLW .25 ; Учесть разряд с точностью 0.25 сек
RLF m,F
SKPC
MOVLW .50
MOVWF TimerFiftienth

; Переключить EW на ввод и ожидать, когда там будет 1 - это сигнал супервизора,
; что питание хоста в норме...
BSF STATUS,RP0 ; Выбор банка 1
BSF TRISC,EW ; EW на ввод
BCF STATUS,RP0 ; Выбор банка 0

CALL KeyINI ; Инициализация клавиатуры (это еще и задержка)
BTFSS PORTC,EW ; Ждём-с когда же будет там 1
GOTO $-1

BSF STATUS,RP0 ; Выбор банка 1
BCF TRISC,EW ; EW на вывод
BCF STATUS,RP0 ; Выбор банка 0
; Здесь необходимо установить задержку порядка 100 мс для того,
; чтобы сигнал прерывания NMI формировался не раньше 100 мс

MOVLW .50
MOVWF j
CLRF i

delay_10ms
GOTO $+1
GOTO $+1
DECFSZ i,F
GOTO delay_10ms
DECFSZ j,F
GOTO delay_10ms

GOTO Start
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

;-----------------------------------------------------------------------------
; Задержка перед выключением прибора в 2.56 секунды
;
DELY ; Выдать звуковой сигнал и сформировать прерывание от клавиатуры со
; скан-кодом клавиши "ВЫКЛ" - 0x3C
CALL BEEP
DELT
CLRF TimeOutCounter ; Устанавливаем паузу перед выключением 2.56 с
BSF MyFlags,ProgTimerOn; Под это дело запускаем программный таймер.
BSF MyFlags,PushedOFF; еще раз указываем что нажали кл. "ВКЛ", если
; в этот режим перешел сам хост.
CLRF State
GOTO MainLoop ; И переходим в терминальный режим...
;-----------------------------------------------------------------------------
; Работа в режиме тахометра
;
TAX BTFSC thresholdOFF,7 ; Не входить в режим, если держат кл. "ВКЛ"
GOTO MainLoop ; (так разве можно работать)
BTFSC MyFlags,SoundTimerOn ; Активизирован таймер звукового сигнала?
GOTO $-1 ; Если работает, то ждать эго окончания...

BCF INTCON,GIE ; Запрет прерывания на время обработки
BTFSC INTCON,GIE ; обращения хоста ----->
GOTO $-2
BSF PORTB,S4 ; Убрать сигнал TEST

BCF MyFlags,ModeChaged ; Сбрасываем признак изменения режима

BCF RCSTA,SPEN ; не можем передавать по RS, -> индикатор метки
BSF STATUS,RP0 ; Выбор банка 1
BCF TRISC,TX ; Линию TX как вывод индикатора метки...
BCF STATUS,RP0 ; Выбор банка 0

TAX_Loop
BTFSC MyFlags,Capture ; Получено разрешение измерения периода метки?
GOTO TAX_Begin

BTFSC PIR1,TMR2IF ; Есть ли прерывание от таймера ╧2? (100 Гц)
CALL TAX_UpdateTimers

BTFSC MyFlags,ModeChaged; Режим был изменён (или выключили) ?
GOTO TAX_Exit ; если да, то выход

BTFSS PORTE,2 ; Ждём обращение хоста...
CALL SwitchTable ; От туда должны вернуться с установленным EW!
GOTO TAX_Loop ; Если нет, то продолжить, иначе

TAX_Exit
BCF MyFlags,Capture ; Запрет измерения периода метки
BSF INTCON,GIE ; ----> разрешение прерывания
GOTO MainLoop ; выход из режима!
;------
TAX_Begin
MOVLW b'00111000' ; Останов таймера
MOVWF T1CON ;
CLRF TMR1L ; Сброс таймера (прескалер также сбрасывается в 1)
CLRF TMR1H ; Прескалер сбрасывается.
MOVLW b'00111001' ; Таймер от Fosc/4 , с предделителем 1:8
MOVWF T1CON ; запускаем, осциллятор на 32768 Гц работает

CLRF CCP1CON ; Отключение блока захвата
MOVLW b'00000100' ; Capture mode, every falling edge
MOVWF CCP1CON
BCF PIR1,CCP1IF ; Снять флаг от блока захвата 1

MOVLW .75 ; Таймаут .75 сек
MOVWF i

TAX_WaitFirst ; Ожидание первого импульса от фотоотметчика
BTFSC PIR1,TMR2IF ; Есть ли прерывание от таймера ╧2? (100 Гц)
CALL TAX_Up_I_Timers

BTFSC MyFlags,ModeChaged; Режим был изменён (или выключили) ?
GOTO TAX_Exit ; если да, то выход

BTFSS PORTE,2 ; Ждём обращение хоста...
CALL SwitchTable ; От туда должны вернуться с установленным EW!

MOVF i,W ; Время истекло?
SKPNZ
GOTO TAX_overflow

BTFSS PIR1,CCP1IF ; Получен сигнал с фотоотметчика?
GOTO TAX_WaitFirst ; Если нет, то продолжить, иначе

BCF PIR1,CCP1IF ; Снять флаг от блока захвата 1
MOVF CCPR1L,W ; Сохраняем время обнаружения первого импульса
MOVWF j
MOVF CCPR1H,W
MOVWF k
BCF PIR1,TMR1IF ; Сброс флага переполнения таймера

MOVLW -2 ; Дважды допускаем переполнение таймера
MOVWF i
GOTO TAX_TestTMR1
;--
TAX_LowLoop
BTFSC PIR1,CCP1IF ; Получен сигнал с фотоотметчика?
GOTO TAX_LowFound
BTFSC PIR1,TMR2IF ; Есть ли прерывание от таймера ╧2? (100 Гц)
CALL TAX_UpdateTimers
TAX_TestTMR1
BTFSS TMR1H,7 ; Цикл, пока таймер не досчитал до половины
GOTO TAX_LowLoop

TAX_HighLoop
BTFSC PIR1,CCP1IF ; Получен сигнал с фотоотметчика?
GOTO TAX_HighFound
BTFSC PIR1,TMR2IF ; Есть ли прерывание от таймера ╧2? (100 Гц)
CALL TAX_UpdateTimers
BTFSS PIR1,TMR1IF ; Цикл, пока не переполнится таймер...
GOTO TAX_HighLoop

BCF PIR1,TMR1IF ; Сброс переполнения таймера
INCFSZ i,F
GOTO TAX_LowLoop ; Переполнение таймера, что делать?...

TAX_overflow
CLRF CCP1CON ; Отключение блока захвата
BCF T1CON,TMR1ON ; Останов таймера 1
BSF PORTC,TX ; Отключить индикатор "МЕТКА"
CLRF CaptureLow ; Результат == 0
CLRF CaptureHigh
GOTO TAX_noTick
;-----------
TAX_LowFound ; Обнаружен сигнал фотоотметчика при TMR1 0x0000..0x8100
BCF T1CON,TMR1ON ; Останов таймера 1

MOVF CCPR1H,W
MOVWF CaptureHigh
MOVF CCPR1L,W
MOVWF CaptureLow

GOTO TAX_Tick

TAX_HighFound ; Обнаружен сигнал фотоотметчика при TMR1 0x8000..0xFFFF..0x0100
BCF T1CON,TMR1ON ; Останов таймера 1
BTFSS CCPR1H,7 ; Захватили значение после переполнения?
INCF i,F ; обновить i, (FE->FF, FF->00)

MOVF CCPR1H,W
MOVWF CaptureHigh
MOVF CCPR1L,W
MOVWF CaptureLow
GOTO TAX_Tick

TAX_Up_I_Timers
DECF i,F
TAX_UpdateTimers
BCF PIR1,TMR2IF ; Снять флаг прерывания от таймера 100 Гц

CALL TestKeyOFF ; Работа с клавишей "ВКЛ"
BTFSC MyFlags,PushedOFF; Если обнаружено нажатие "ВКЛ", то выход
BSF MyFlags,ModeChaged; (делаем вид, что изменён режим)

DECFSZ TimerFiftienth,F; Реализация делителя на 50 (100Гц/2Гц)
RETURN

MOVLW .50
MOVWF TimerFiftienth
INCF Timer2HzLow,F ; Инкремент счетчика реального времени
SKPNZ
INCF Timer2HzHigh,F
RETURN
;------
TAX_Tick
BCF PORTC,TX ; Включить индикатор "МЕТКА"

; Коррекция времени начала измерения, j (не плохо бы "погонять" с генератором)
MOVF i,W
ADDLW 2 ; т.к. i начиналось с -2
MOVWF i ; 17 бит измеренного значения

MOVF j,W
SUBWF CaptureLow,F
MOVLW 1
SKPC
SUBWF CaptureHigh,F
SKPC
DECF i,F

MOVF k,W
SUBWF CaptureHigh,F
SKPC
DECF i,F

MOVF i,F ; Если i != 0, то считаем что переполнение
SKPZ
GOTO TAX_overflow

TAX_noTick
CLRF CCP1CON ; Отключение блока захвата
BCF PIR1,CCP1IF ; Снять флаг от блока захвата 1

BCF MyFlags,Capture ; Запрет измерения периода метки
MOVLW .3 ; Переходим в режим сбора данных
MOVWF State
GOTO ADC_NoPreambul ; Пропуск проверки таймеров и запрета прерывания
;-----------------------------------------------------------------------------
; Работа в режиме сбора данных
;
ADC BTFSC MyFlags,SoundTimerOn ; Активизирован таймер звукового сигнала?
GOTO $-1 ; Если работает, то ждать эго окончания...
BTFSC thresholdOFF,7 ; Не входить в режим сбора, если держат кл. "ВКЛ"
GOTO MainLoop ; (так разве можно собирать данные)

BCF INTCON,GIE ; Запрет прерывания на время сбора данных
BTFSC INTCON,GIE
GOTO $-2

ADC_NoPreambul
BCF MyFlags,ModeChaged ; Сбрасываем признак изменения режима
MOVF ProgPeriod,W ; Переход от констант принятых в 8051 к удобным
SKPNZ ; мне : 0 1
ADDLW -(5+1) ; -8 3
SUBLW -5 ; -12 7
MOVWF j ; -16 11
GOTO ADC_Loop ; j =(ProgPeriod != 0) ? (-5 - ProgPeriod):(1)

ADC_M1 BTFSS PORTB,0 ; 1 Нажата ли кл. "ВКЛ"?
GOTO ADC_TestKeyOFF ; 1 (2) (не проверяем только 1 из 50 раза)
GOTO ADC_M3 ; 2

ADC_UpdateTime
BCF PIR1,TMR2IF ; 1 Снять флаг прерывания от таймера 100 Гц
DECFSZ TimerFiftienth,F; 1 Реализация делителя на 50 (100Гц/2Гц)
GOTO ADC_M1 ; 1 (2)

MOVLW .50 ; 1
MOVWF TimerFiftienth ; 1

INCF Timer2HzLow,F ; 1 Инкремент счетчика реального времени
SKPNZ ; 1 (16 бит)
INCF Timer2HzHigh,F ; 1

ADC_M3 NOP ; 1
;--------------------------------------
ADC_Loop
BSF PORTB,S4 ; 1 Убрать сигнал TEST
MOVF j,W ; 1 Загрузка периода в счетчик...
MOVWF i ; 1
;
DECFSZ i,F ; i*1 Выдержка заданного периода
GOTO $-1 ; i*2
; -1 т.к. последний раз GOTO $-1 не выполняется
BCF PORTB,S4 ; 1 сформировать сигнал TEST и разрешение ряда S4
;
BTFSC PIR1,TMR2IF ; 1 Есть ли прерывание от таймера (100Гц)
GOTO ADC_UpdateTime ; 1 (2) Обновить таймер реального времени

BTFSS PORTA,LB ; 1 Анализ состояния аккумулятора
GOTO ADC_LowBat ; 1 (конечно часто, но по другому не выходит)

BTFSS PORTE,2 ; 1 Есть ли обращение от хоста
GOTO ADC_HostAppeal ; 1 (2)
MOVF PORTA,W ; 1 Проверка возвратных линий клавиатуры
ANDLW 0x7 ; 1
XORLW 0x7 ; 1
SKPNZ ; 1 Если нет нажатых клавиш, то повтор...
GOTO ADC_Loop ;__2_(1)_
;15 + i*3

CALL KeyScan ; Здесь определяем код нажатой клавиши...
CALL KeyScan ; Пять раз, чтобы перебрать все сканирующие
CALL KeyScan ; линии
CALL KeyScan
CALL KeyScan
CLRF State ; Переходим в терминальный режим
GOTO ADC_CryANDexit

ADC_LowBat
CALL TKO_LowBat
GOTO ADC_CryANDexit

ADC_TestKeyOFF
CALL TestKeyOFF ; 2 Работаем с клавишей "ВКЛ"
BTFSS MyFlags,PushedOFF; 1
GOTO ADC_Loop ; 2 Пока не устранили дребезг продолжаем
; Выдать хосту сообщение о выключении
ADC_CryANDexit
BCF PORTC,5 ; ----_-- ~1 us
BSF PORTC,5 ; ----_-- ~1 us
BSF INTCON,GIE ; -----> разрешение прерывания
GOTO MainLoop

ADC_HostAppeal ; Чё те надо, чё ты хошш...
CALL SwitchTable ; От туда должны вернуться с установленным EW!
BTFSS MyFlags,ModeChaged ; Режим был изменён?
GOTO ADC_Loop ; Если нет, то продолжить, иначе
BSF INTCON,GIE ; ----> разрешение прерывания
GOTO MainLoop ; переход на новый режим

; =============================================================================
; =============================================================================
WR3E0 ; Передать байт через адаптер на принтер с формированием строба
MOVLW 8
MOVWF i
MOVF PORTD,W
MOVWF temp
OFFREADY ; Отпускаем хост...

BCF RCSTA,SPEN ; Если печатаем, то не можем передавать по RS
BSF STATUS,RP0 ; Выбор банка 1
BCF TRISC,CLKP ; Линию на вывод...
BCF STATUS,RP0 ; Выбор банка 0
;------
L_WR3E0 RLF temp,F ; По битику, по битику, да в сдвиговый регистр
SKPNC
BSF PORTB,DATP
SKPC
BCF PORTB,DATP

BCF PORTC,CLKP
BSF PORTC,CLKP ; Записать следующий бит в сдвиговый регистр
DECFSZ i,F
GOTO L_WR3E0

BCF PORTC,STB ; Сформировать строб для принтера
BSF PORTC,STB
BSF PORTB,DATP ; Сделать DATP неактивным

BSF STATUS,RP0 ; Выбор банка 1
BSF TRISC,CLKP ; Линию на ввод...
BCF STATUS,RP0 ; Выбор банка 0
BSF RCSTA,SPEN ; отпечатали, теперь можем передавать по RS
RETURN
;-----------------------------------------------------------------------------
WR3E2 ; Передать байт через канал RS-232
MOVF PORTD,W
OFFREADY

BTFSS PIR1,TXIF ; Ожидание готовности буфера передатчика
GOTO $-1

MOVWF TXREG ; Запись байта запускает передачу
RETURN
;-----------------------------------------------------------------------------
WR3E8 MOVF PORTD,W
OFFREADY
MOVWF temp

XORWF State,W ; Режим работы изменяется? (три младших бита)
ANDLW 7
SKPNZ
GOTO WR3E8_NoChange
BTFSC MyFlags,PushedOFF; Если собрались отключать питание,
GOTO WR3E8_NoChange ; то игнорируем изменение режима...

MOVF temp,W ; Записать новое состояние (код режима)
MOVWF State
BSF MyFlags,ModeChaged ; Режим изменён

WR3E8_NoChange
MOVLW HIGH ChoiceTable
MOVWF PCLATH
SWAPF temp,W ; Разбор 4..6 битов
XORLW 0x08 ; SWAP 0x80 == 8, Старт программного таймера?
SKPNZ ; (младшие три бита (бывшие 4..6) не инвертируются)
GOTO WR3E8_0x80
ANDLW 7
ChoiceTable
ADDWF PCL,F
RETURN ; 0
GOTO OFF ; 1
GOTO WR3E8_010; 2
GOTO WR3E8_011; 3
RETURN ; 4
RETURN ; 5
GOTO WR3E8_110; 6
RETURN ; 7
ChoiceTable_end
if (ChoiceTable_end & 0xFF00) != (ChoiceTable &0xFF00)
error "Таблица находится в двух страницах (256 байт)"
endif

WR3E8_010
BCF PORTA,ZU_PS ; Включаем зарядное устройство
RETURN
WR3E8_011
BSF PORTA,ZU_PS ; Отключаем зарядное устройство
RETURN
WR3E8_110
MOVLW .50
MOVWF TimerFiftienth
CLRF Timer2HzLow ; сброс счетчика реального времени
CLRF Timer2HzHigh
RETURN
WR3E8_0x80
MOVF ProgPeriod,W ; Копирование периода в счетчик, если только
BTFSS MyFlags,PushedOFF ; мы не отрабатываем паузу перед "ВКЛ"
MOVWF ProgramTimer
BSF MyFlags,ProgTimerOn; Запуск программного таймера
RETURN
;-----------------------------------------------------------------------------
WR3EA MOVF PORTD,W
OFFREADY
MOVWF temp

MOVLW HIGH GetDiv
MOVWF PCLATH
SWAPF temp,W
ANDLW 0xF ; Получить скорость работы по RS-232
; здесь наверное надо дождаться когда все операции с RS'ом будут закончены?
CALL GetDiv
BSF STATUS,RP0 ; Выбор банка 1

ADDLW 0x80 ; Проверить старший бит W -> Carry
SKPC
BCF TXSTA,BRGH ; Low speed режим - будем надеяться
SKPNC
BSF TXSTA,BRGH ; жаль, что high speed режим
SKPC
ANDLW 0x7F
MOVWF SPBRG ; Задать новый коэф. деления

BCF STATUS,RP0 ; Выбор банка 0

BTFSC temp,3 ; Должен ли быть звук включен?..
GOTO WR3EA_L1 ; Переход если нет...

BSF MyFlags,SoundOn ; если да - установка флага звукового сигнала
BTFSS ControlReg,DisSound ; Можно ли включать сигнал?
BCF Key_MaskB,O_SND ; Включить звуковой сигнал
RETURN

WR3EA_L1
BCF MyFlags,SoundOn ; Сброс флага звукового сигнала
BTFSS MyFlags,SoundTimerOn; Активизирован таймер звукового сигнала?
BSF Key_MaskB,O_SND ; сразу снять звуковой сигнал если нет!
RETURN ; иначе всё таки отработать beep

; Таблица для получения коэф. дел. на генератора скорости RS'канала
; Старший бит == 1 готорит о том, что необходимо использовать
; high speed режим
GetDiv ADDWF PCL,F ; Выполнить косвенный переход по W
DT .-1
DT .-1
DT .-1
DT .0 ; 57.6 кБод
DT .-1
DT .-1
DT .-1
DT .1 | 0x80; 115.2 кБод, только при BRGH=1 (High Speed mode)
DT .23 ; 2.4 кБод
DT .5 | 0x80; 38.4 кБод
DT .11 ; 4.8 кБод
DT .5 ; 9.6 кБод
DT .-1
DT .-1
DT .-1
DT .2 ; 19.2 кБод
GetDiv_end
if (GetDiv_end & 0xFF00) != (GetDiv &0xFF00)
error "Таблица находится в двух страницах (256 байт)"
endif

WR3EC MOVF PORTD,W ; Запись в регистр периода программного таймера
OFFREADY ; или же частоты дискретизации
MOVWF ProgPeriod
RETURN

WR3EE MOVF PORTD,W ; Запись в контрольный регистр
OFFREADY
MOVWF ControlReg

; Если блокировка выдачи звука, то убрать звук сразу же !!!
BTFSC ControlReg,DisSound ; Можно ли включать сигнал?
BSF Key_MaskB,O_SND ; Отключить звуковой сигнал
BTFSC ControlReg,DisSound
BSF PORTB,O_SND
RETURN
;_____________________________________________________________________________
;-----------------------------------------------------------------------------
RD3E0 ; Считывание скан-кода
MOVF Key_Code,W
MOVWF PORTD
BCF Ident,KeyBEvent ; Прерывания по нажатию клавиши нет
GOTO $+1
OFFREADY
RETURN
;-----------------------------------------------------------------------------
RD3E2 ; Считывание состояние блока питания и готовности принтера
BSF STATUS,RP0 ; Выбор банка 1
BSF TRISA,ZU_PS ; Настройка линии ZU_PS на ввод
BCF STATUS,RP0 ; Выбор банка 0
; Здесь проверяем не сразу, а ждем,
; пока значение на входе ZU_PS установится...
MOVLW 0xF0 ; биты 2,3 - всегда 0,а биты 6,7 - всегда 1
BTFSC PORTC,BUSY ; Анализ состояния сигнала готовности принтера
IORLW (1<<1)
BTFSS PORTA,LB ; Анализ состояния аккумулятора
ANDLW ~(1<<5)

BTFSC PORTA,ZU_PS ; ...анализ ЗУ подключено/отключено через 6.5 мкс
IORLW (1<<0)

BSF STATUS,RP0 ; Выбор банка 1
BCF TRISA,ZU_PS ; Настройка линии ZU_PS на вывод
BCF STATUS,RP0 ; Выбор банка 0

BTFSS PORTA,ZU_PS ; Анализ состояния триггера включения ЗУ
ANDLW ~(1<<4)
MOVWF PORTD

GOTO $+1
OFFREADY
RETURN
;-----------------------------------------------------------------------------
RD3E4 ; Считывание счетчика реального времени (мл. байта)
; Здесь не плохо было бы обеспечить фиксацию старшего байта счетчика реального
; времени в отдельной переменой, чтобы обезопасить себя от ситуации когда
; при значении 0x??FF между считыванием младшего и старшего байта производится
; инкремент счетчика реального времени и как следствие значение старшего байта
; будет искажено...
MOVF Timer2HzLow,W
MOVWF PORTD

GOTO $+1
OFFREADY
RETURN
;-----------------------------------------------------------------------------
RD3E6 ; Считывание счетчика реального времени (ст. байта)
MOVF Timer2HzHigh,W
MOVWF PORTD
BCF Ident,Tick2HzEvent; Сброс прерывания по "тику 2Гц"

GOTO $+1
OFFREADY
RETURN
;-----------------------------------------------------------------------------
RD3E8 ; Считывание регистра-идентификатора прерываний
MOVF Ident,W
BTFSS PORTA,LB ; Анализ состояния аккумулятора
ANDLW ~(1<<5)
BTFSS PORTA,ZU_PS ; Анализ состояния триггера включения ЗУ
ANDLW ~(1<<4)
MOVWF PORTD

BCF Ident,TimeOutEvent ; Прерывания по таймауту сбрасываем
BCF Ident,TimerEvent ; Сброс прерывания по прогр. таймеру
OFFREADY
RETURN
;-----------------------------------------------------------------------------
RD3EA ; Мл. байт периода сигнала с фотоотметчика
MOVF CaptureLow,W
MOVWF PORTD

BCF MyFlags,Capture ; Запрет измерения периода метки
GOTO $+1
OFFREADY
RETURN
;-----------------------------------------------------------------------------
RD3EC ; Ст. байт периода сигнала с фотоотметчика
MOVF CaptureHigh,W
MOVWF PORTD

BSF MyFlags,Capture ; Разрешение измерения периода метки
GOTO $+1
OFFREADY
RETURN
;-----------------------------------------------------------------------------
RD3EE ; Принять байт из канала RS-232
MOVLW b'00000110' ; Проверка бит FERR и OERR...
ANDWF RCSTA,W ; А нет ли перегрузки приёмника и ошибки кадра?
SKPZ
GOTO RD3EE_OERR
BTFSC PIR1,RCIF ; Первая проверка вне цикла - приёмник готов?
GOTO RD3EE_OK ; Чтобы меньше времени занимало на 115200 бодах

MOVLW .88 ; Таймаут 0.88 сек
MOVWF TimeOutCounter

; Здесь я не могу проверять клавиатуру, т.к. EW=0. При таймуте будем выходить
; и надеюсь прерывание от таймера 100 Гц обеспечит тогда проверку клавиатуры
RD3EE_wait
BTFSC PIR1,RCIF ; Приёмник готов?
GOTO RD3EE_OK

BTFSS PIR1,TMR2IF ; Есть ли прерывание от таймера ╧2? (100 Гц)
GOTO RD3EE_noTMR2int
BCF PIR1,TMR2IF ; Снять флаг прерывания от таймера 100 Гц
DECFSZ TimerFiftienth,F; Реализация делителя на 50 (100Гц/2Гц)
GOTO RD3EE_M1

MOVLW .50
MOVWF TimerFiftienth
INCF Timer2HzLow,F ;Инкремент счетчика реального времени
SKPNZ ;(16 бит)
INCF Timer2HzHigh,F
RD3EE_M1
DECF TimeOutCounter,F ; Истёк ли заданный интервал?
SKPNZ
BSF Ident,TimeOutEvent; Установка прерывания из-за таймаута

CALL TestKeyOFF ; Работа с клавишей "ВКЛ"
BTFSC MyFlags,PushedOFF; Если обнаружено нажатие "ВКЛ", то выход
GOTO RD3EE_OFF

RD3EE_noTMR2int

BTFSS Ident,TimeOutEvent; Ну сколько можно ждать?..
GOTO RD3EE_wait ; Таймаут -> выход с генерацией прерывания

RD3EE_OFF
CLRF PORTD ; В связном режиме прерывания могут быть только
BCF PORTC,5 ; из-за таймаута или по нажатию клавиши
BSF PORTC,5 ; ----_-- ~1 us
OFFREADY
RETURN
RD3EE_OK
MOVF RCREG,W ; Считать принятый по RS-232 байт
MOVWF PORTD
GOTO $+1
OFFREADY
RETURN
RD3EE_OERR ; При перезагрузке приёмника сброс последнего,
BCF RCSTA,CREN ; чтобы не заблокировался дальнейший приём
BSF RCSTA,CREN ; данных по каналу RS-232
MOVF RCREG,W ; Очистить буфер приёмника
BSF Ident,TimeOutEvent; Для нас ошибка, что таймаут - всё едино
GOTO RD3EE_OFF
; =============================================================================
; Фрагмент реакции на обращение к незадействованному порту
; =============================================================================
WR3E4 ; Теперь запись в этот порт обрабатывает только XILINX
WR3E6 ; Теперь запись в этот порт обрабатывает только XILINX

WR3F0 ; Назначение этих восьми портов еще определено
WR3F2
WR3F4
WR3F6
WR3F8
WR3FA
WR3FC
WR3FE

RD3F0 ; Назначение этих восьми портов еще определено
RD3F2
RD3F4
RD3F6
RD3F8
RD3FA
RD3FC
RD3FB
CLRF PORTD
GOTO $+1
OFFREADY
RETURN
; =============================================================================
; Подпрограмма включения звукового сигнала на 100 мс
; =============================================================================
BEEP MOVLW .10 ; 10*10мс = 100 мс
MOVWF SoundCounter

BTFSS ControlReg,DisSound ; Можно ли включать сигнал?
BCF Key_MaskB,O_SND ; Включить звуковой сигнал
BSF MyFlags,SoundTimerOn; Активизировать таймер звукового сигнала
RETURN
; =============================================================================
; --------- Работа с клавишей "ВКЛ"
TestKeyOFF
BTFSS PORTA,LB ; Анализ состояния аккумулятора
GOTO TKO_LowBat

BTFSS thresholdOFF,7 ;
GOTO TKO_WaitPress ;
; Если отрицательное, то проверяем на отжатие
INCF thresholdOFF,F ; Приближаемся к 0...
BTFSC PORTB,0 ; Проверка того, что кл. "ВКЛ" отжата минимум
RETURN ; более 320 мс.

MOVLW -32 ; Пока нажата будем ждать...
MOVWF thresholdOFF ;
RETURN ;

TKO_WaitPress
BTFSC PORTB,0 ; Проверка того, что кл. "ВКЛ" нажата минимум
CLRF thresholdOFF ; минимум 320 мс.

BTFSC thresholdOFF,4 ; Если досчитали до 32, то установить флаг
TKO_LowBat ; если случился разряд батареи, то надо выключать
BSF MyFlags,PushedOFF

INCF thresholdOFF,F

BTFSS MyFlags,PushedOFF ; Если уже флаг установлен, то надо
RETURN ; выставить код клавиши "ВЫКЛ"

MOVLW .1 ; Переходим в режим паузы перед выключением
MOVWF State
MOVLW -32 ; Теперь приготавливаемся, будем ждать отжатия
MOVWF thresholdOFF
MOVLW 0x3C ; Выставить код клавиши "ВЫКЛ"
MOVWF Key_Code
BSF Ident,KeyBEvent ; Прерывание по отжатию клавиши
BSF temp_Ident,KeyBEvent; Сформировать прерывание даже если еще
RETURN ; не обработали предыдущее нажатие клавиш
; =============================================================================
; Инициализация портов
; =============================================================================
PortINI
BCF STATUS,RP0 ; Выбор банка 0
BCF STATUS,RP1
MOVLW b'111111' ;
MOVWF PORTA
MOVLW b'11111111' ; Питание включаем, звук выключаем
MOVWF PORTB ; SND -> 1, OFF -> 1
MOVLW b'11111000'
MOVWF PORTC

BSF STATUS,RP0 ; Выбор банка 1
MOVLW b'101111'
MOVWF TRISA
MOVLW b'11000111' ; На вывод NMI, STB, EW
MOVWF TRISC
MOVLW b'11111111'
MOVWF TRISD
MOVLW b'00010111' ; Разрешение работы параллельного порта
MOVWF TRISE
MOVLW b'00000001' ; Здесь включится питание...
MOVWF TRISB
MOVLW (1<<<< 1, OFF -> 1

MOVLW 0xF7 ; Начинаем с S4
MOVWF Key_Colum

MOVLW -32 ; Для устранения дребезга клавиши "ВКЛ"
MOVWF thresholdOFF ; Инициализация переменой на интервал 320 мс
BCF MyFlags,PushedOFF; Клавиша "ВКЛ" пока не нажата

RETURN
; =============================================================================
; Сканирование клавиатуры (каждые 10 мс)
KeyScan
MOVF Key_Colum,W ; Возбуждение соответствующего столбца
ANDWF Key_MaskB,W ; с учетом состояний выходных сигналов
MOVWF PORTB ;******** SND и OFF

BTFSC Ident,KeyBEvent ; Клавиша востребована хостом?
GOTO KS_exit ; Выход если не считан буфер клавиатуры

BTFSC Key_Code,7 ; Старший бит - признак нажатия клавиши
GOTO KeyCheck ; проверить состояние уже нажатой клавиши

MOVLW 0xF0
IORWF PORTA,W ;******** Анализируем входы AR0..AR3
XORLW 0xFF
MOVWF Key_Return

SKPZ ; Если в этом столбце есть нажатия,
GOTO KeyAnalyse ; то определить скан-код

MOVF Key_MaskB,W ; Снять сигналы S0..S4, с учетом состояний
MOVWF PORTB ; выходных сигналов SND и OFF

RLF Key_Colum,F ; Подготовка к проверки очередной
BSF Key_Colum,0 ; линии возбуждения при следующем
SKPC ; опросе клавиатуры
BCF Key_Colum,3
GOTO KS_exit
;---------
KeyAnalyse
CLRF Key_Row
MOVLW 0x80+0x18 +8-1 ; Начальное значение скан-кода

KeyS_L1 ADDLW -8 ; Определение строки, где было
INCF Key_Row,F ; произведено нажатие
RRF Key_Return,F
SKPC
GOTO KeyS_L1
MOVWF Key_Code

MOVF Key_Colum,W ; Сохранить Key_Colum
KeyS_L2 INCF Key_Code,F ;<-+ Определение столбца, где было
RLF Key_Colum,F ; | произведено нажатие
SKPNC ; |
GOTO KeyS_L2 ;--+
MOVWF Key_Colum ; Восстановить Key_Colum
BSF Ident,KeyBEvent ; Прерывание по нажатию клавиши
CALL BEEP ; И "писк" в течении 100 мс
GOTO KS_exit
;--------------------------------------
KeyCheck
MOVF PORTA,W ;******** Анализируем входы AR0..AR3
MOVWF Key_Return

MOVF Key_Row,W ; Сохранить Key_Row
KeyS_L3 RRF Key_Return,F; Получить в CARRY состояние ранее нажатой клавиши
DECFSZ Key_Row,F ; Флаг переноса эти две команды не изменяют
GOTO KeyS_L3
MOVWF Key_Row ; Восстановить Key_Row

SKPNC ; Выход если клавиша еще нажата
BCF Key_Code,7 ; --иначе признак того, что клавиша отпущена
SKPNC
BSF Ident,KeyBEvent ; --иначе прерывание по отжатию клавиши
;---------------
KS_exit
MOVF Key_MaskB,W ; Снять сигналы S0..S4, с учетом состояний
MOVWF PORTB ; выходных сигналов SND и OFF
RETURN
; =============================================================================
DT "(C)1997 Alexander Trush "
DT "Date: 6 Jule 1997"
END


7 нравится? 8


01.02.2015 © 9zip.ru
Авторские права охраняет Роскомнадзор

Понравилась статья?
Менделеев говорит:
поделись с друзьями!

Хочешь почитать ещё про инструкции? Вот что наиболее популярно на этой неделе:
Согласование усилителя с аккустической системой
Простой генератор звуковой частоты
Как пользоваться эмулятором ZX-Spectrum



Есть вопросы, комментарии? Напиши:

Имя
Комментарий
Длина текста:
число с картинки
Правила прочитал(а)
Как вставить картинку в свой комментарий?

Пользовательские теги: btfsc pir1 устройства на pic16c65 [ Что это? ]

Дальше в разделе Инструкции: Описание работы схемы центрифуги, Электродвигатель питается от сети переменного тока напряжением 220 В частотой 50 Гц. Под крышкой центрифуги установлен выключатель, блокирующий включение двигателя при открытой крышке. Установкой требуемой выдержки времени подготавливают цепи включения реле и нагревателя. Ozon оснащение переговорных.

Главная 9zip.ru База знаний радиолюбителя Контакты
Девять кучек хлама:

Радиотехника, электроника и схемы своими руками Ремонт домашней электроники Виртуальный музей старых радиодеталей XX века Ламповый звук hi-end и ретро электроника Катушки Теслы Радиодетали и модули с Aliexpress Интернет и сети, компьютеры и программы Категория свободна Инструкции


Дайджест
радиосхем

Новые схемы интернета - в одном месте!

 21.4 Непростой простой микшер
 5.4 Гаражная сигнализация GSM и термостат
 31.3 Миртек - Оправка показаний на Email или SMS

Задай вопрос радиолюбителям!


22.4 В чём разница между управлением мощным IGBT и ...
1
18.4 Что не так делаем или транзисторы не работают ? ...
3
16.4 Правда ли, что колонки 25 АС-416 какие-то чудесные ...
2