
                                 
                                     ; универсальный вариант,кварц 4 Мгц
                                     ; 2500 имп/км, 4000 имп/км, 6000 имп/км, 8000 имп/км, 10000 имп/км
                                     ; индикаторы с общим катодом
 
           LIST        p= 16f628A  
           include     <p16F628A.inc>
           __config    _CP_OFF & _DATA_CP_OFF & _LVP_OFF & _BODEN_OFF & _MCLRE_OFF & _WDT_OFF & _PWRTE_ON & _HS_OSC

   errorlevel-302
           CBLOCK      20H
; Переменные
count1                               ; переменная для отсчета повторений задержки
count2
SEC                                  ; переменная отсчёта времени звучания сигнала
SB_MEM
CYC_5
SB_5

                                     ; разряды внутренних счетчиков
dig_U                                ; разряд единиц
dig_D                                ; разряд десятков
dig_H                                ; разряд сотен

                                     ; разряды для индикации (маски анодов)
ind_U                                ; разряд единиц
ind_D                                ; разряд десятков
ind_H                                ; разряд сотен
catodNo                            ; бит активного катода 2 1 0
Reg_1
Reg_2
Reg_3
KOD
TIME
SELEKT
S_T
FLAG                                 ; переменная для хранения флагов
                                     ; 0-флаг гашения незначащих нулей
                                     ; 1-флаг опустошения  count1
                                     ; 2-флаг нажатой кнопки
                                     ; 3-флаг обхода
                                     ; 4-флаг кнопки сервис
                                     ; 5-флаг счёта
                                     ; 6-флаг пропуска  
                                     ; 7-флаг  10000                  
           ENDC
; Константы 
SB1        EQU   3
DOOR       EQU   4
S1         EQU   5
                                    
    
           clrf        PORTA
           clrf        PORTB
           clrf        INTCON
           clrf        TMR0
    
           movlw       b'00000111'
           movwf       CMCON
           bsf         STATUS, RP0
           movlw       b'00111000'   ; 
           movwf       TRISA
           movlw       b'00000001'   ; RB0 на ввод, остальные биты порта на вывод
           movwf       TRISB         ; включаем подтягивающие резисторы,
           movlw       b'01000011'   ; TMR0 на внутренний такт с предделителем 16
           movwf       OPTION_REG    ; прерывания запрещены, будем проверять флажки
           bcf         STATUS, RP0
           clrf        KOD
           movlw       .1
           movwf       catodNo
           clrf        FLAG
           clrf        ind_U
           clrf        ind_D
           clrf        ind_H
           clrf        S_T
           movlw       .5
           movwf       CYC_5
           movwf       SB_5
           movwf       TIME
           movlw       .60
           movwf       SEC 
                                     ; макросы
 ;-----------------------------------------------         
DOR        macro       x, y
           clrf        PORTA     
           movlw   x
           movwf       PORTA 
           movlw       y          
           movwf       PORTB
           CALL        DELAY_004  
           endm
             
VIBOR      macro       x, y
           movlw       x            
           movwf       count1             
           movwf       count2 
           movlw   y
           movwf       S_T           
           endm
                                     ; СЧИТЫВАНИЕ параметров из EEPROM
;***********************************************************
           bsf         STATUS, RP0   ; выберем банк1
           bcf         EECON1, WREN 
           clrf        EEADR         ; выберем адрес
           bsf         EECON1, RD    ; чтение
           movf        EEDATA, W     ; получаем данные в аккумуляторе
           bcf         STATUS, RP0   ; выберем банк0
           movwf       SB_MEM        ; скопируем в регистр 
           xorlw       h'ff'
           bnz         EE_
           movlw       .5
           movwf       SB_MEM
      
      
EE_      
           bsf         STATUS, RP0   ; выберем банк1
           bcf         EECON1, WREN 
           movlw       .1
           movwf       EEADR         ; выберем адрес
           bsf         EECON1, RD    ; чтение
           movf        EEDATA, W     ; получаем данные в аккумуляторе
           bcf         STATUS, RP0   ; выберем банк0
           movwf       SELEKT        ; скопируем в регистр 
           xorlw       h'ff'
           bnz         CYCLE
           movlw       .1
           movwf       SELEKT
           goto        CYCLE
       
        
       
                                     ; попрограмма маски катодов для разряда при выводе числа на индикацию
;-----------------------------------------------------------------------------------------------
MASKA:
                      

           sublw       .10             
           bnz         m  
           btfss       FLAG, 0       
           retlw       0  
m
           bsf         FLAG, 0          
           andlw       0x0F     
           addwf       PCL,f
;биты   7  6  5  4  3  2  1  0
;ноги  13 12 11 10  9  8  7
;диод   a  b  c  d  e  f  g

           retlw       b'11111100'   ;  0 
           retlw       b'01100000'   ;  1 
           retlw       b'11011010'   ;  2 
           retlw       b'11110010'   ;  3 
           retlw       b'01100110'   ;  4 
           retlw       b'10110110'   ;  5 
           retlw       b'10111110'   ;  6 
           retlw       b'11100000'   ;  7 
           retlw       b'11111110'   ;  8 
           retlw       b'11110110'   ;  9 
           

;----------------------------------------------------------------------------------------------
  
CYCLE                                ; основной цикл программы

           movfw       SELEKT
           xorlw       .5
           bz          m22
           xorlw       .4^.5
           bz          m23
           xorlw       .3^.4
           bz          m24
           xorlw       .2^.3
           bz          m25
           xorlw       .1^.2
           bz          m26
           goto        m28 
                                     ; цикл подсчета импульсов 
m22                                  ;------------------------------------------------------
         VIBOR  .44, .206            ; 5  вариант = 10000 имп/км
           bsf        FLAG, 7
           goto        m28      
m23                                  ;-------------------------------------------------------
       VIBOR  .56, .207              ; 4 вариант= 8000 имп/км
           goto        m28             
m24                                  ;---------------------------------------------------
       VIBOR  .75, .207              ; 3 вариант= 6000 имп/км
           goto        m28               
m25                                  ;-------------------------------------------------
       VIBOR  .112, .207             ; 2 вариант = 4000 имп/км
           goto        m28             
m26                                  ;-----------------------------------------------
       VIBOR  .90, .207              ; 1 вариант  =2500 имп/км
           bsf         FLAG, 6       ; флаг пропуска          
m28          
           btfss       PORTA, S1     ; перемычка СЕРВИС?
           goto        servis        ; да 
        
                                     ; проверка кнопки яркости
;------------------------------------------------------------------------------------------------
           BTFSC       PORTA, SB1    ; кнопка нажата?
           GOTO        m3
           CALL        DELAY_004     ; дребезг
           CALL        DELAY_004 
           BTFSC       PORTA, SB1
           GOTO        m3
           bsf         FLAG, 2       ; флаг нажатой кнопки
           decfsz      SB_5, F
           goto        m3
           movlw       .5
           movwf       SB_5
           goto        m3
m3                                   ; инициализация счетчиков
           btfss       FLAG, 2
           goto        m0
           bcf         FLAG, 2
           movf        SB_5, W       ; скопируем содержимое регистра в EEDATA
           movwf       SB_MEM
           bcf         PIR1, EEIF  
           bsf         STATUS, RP0   ; выберем банк1 
           movwf       EEDATA
           clrf        EEADR         ; выберем адрес  
           CALL        WR_KEY
m0       
           movlw       .10
           movwf       dig_U         ; инициализируем счетчики разрядов
           movwf       dig_D         ; для уменьшения кода разрядные счетчики
           movwf       dig_H         ; будем изменять в обратном порядке 10,9,...,1
           bcf         INTCON,INTF
ms720
           btfsc       FLAG, 7
           goto        m_1t
m_2t
           movfw       S_T           ; при 4Мгц и предделителе 1:16 получается 1 переполнение таймера 16 мкс
           movwf       TMR0          ; цикл всех переполнений TMR0 (5х48)+ команды управления = 4 мс
           bcf         INTCON,T0IF   ; сбросим флаг прерывания от TMR0
TMR_LOOP          
           btfss       INTCON, INTF  ; если был импульс датчика, то изменяем счетчики
           goto        NoINCR        ; датчик молчит, идем проверять таймер
;-----------------------------------------------------------------------
           btfss       FLAG, 6
           goto        DoINCR
           bsf         STATUS, RP0
           btfss       OPTION_REG, 6
           goto        m19
           bcf         OPTION_REG, 6
           goto        m18
m19
           bsf         OPTION_REG, 6
m18
           bcf         STATUS, RP0
DoINCR
           decfsz      dig_U,f       ; счетчики разрядов нужно менять циклически от 10 до 1
           goto        eoINCR        ; если не ноль, то закончим работу с разрядами
           movlw       .10    
           movwf       dig_U         ; ноль заменяем на 10, и меняем следующий разряд
           decfsz      dig_D,f       ; с десятками то же, что и с единицами
           goto        eoINCR
           movlw       .10
           movwf       dig_D
           decfsz      dig_H,f       ; аналогично с сотнями
           goto        eoINCR
           movlw       .10
           movwf       dig_H
eoINCR
           bcf         INTCON,INTF   ; сбросили флаг внешнего прерывания
NoINCR  
           btfss       INTCON,T0IF   ; повторяем маленький цикл,
           goto        TMR_LOOP      ; пока TMR0 не перепонится 48 раз
           decfsz      CYC_5, F         
           GOTO        m10
           movlw       .5
           movwf       CYC_5
           movf        SB_MEM, W
           movwf       SB_5
           bcf         FLAG, 3
           goto        m12
m10                 
           btfsc       FLAG, 3
           GOTO        ms720
           decfsz      SB_5, F
           GOTO        ms720
           clrf        PORTA
           bsf         FLAG, 3
           GOTO        ms720
                
m_1t
           nop
           nop                       ; корректируем показания
           nop
           nop
           goto        m_2t        

                                     ; закончились 4 мс, нужно переключить разряд индикации
;------------------------------------------------------------------------------------------------
; разряды  сотни десятки единицы
; ноги     1      18     17
; биты RA  2      1      0
m12
           bcf         STATUS,C
           rrf         catodNo,f     ; сдвиг AnodNo получается 4 -> 2 -> 1 -> 0
           btfss       STATUS,C      ; если не дошли до нуля
           goto        Nextcatod     ; то обход
           bsf         catodNo,2     ; если дошли до нуля, то AnodNo=4, получаем цикл битов
           movlw       catodNo       ; адрес, следующий за адр   
           movwf       FSR           ; помещаем в индексный регистр
Nextcatod
           clrf        PORTA         ; Отключили катоды
           decf        FSR,f         ; уменьшаем адрес в индексном регистрe
           movfw       INDF          ; и вытаскиваем из памяти маску анодов следующего разряда
           movwf       PORTB         ; маску анодов выводим в порт
           movfw       catodNo
           movwf       PORTA         ; включили катод следующего разряда
           btfsc       FLAG, 1       ; флаг опустошения  count1 выставлен?
           GOTO        m1            ; да, переход на метку, чтобы опустошать count2
           decfsz      count1,f      ; нет, отсчет 4 мс, нужно повторить в общем N раз, 
           goto        ms720         ; чтобы получился нужный интервал отсчета  
           bsf         FLAG, 1       ; выставить флаг опустошения  count1
m1
           decfsz      count2,f      ; декремент следующих n циклов 
           goto        ms720         ; переход на очередной круг
           bcf         FLAG, 1       ; сбросить флаг опустошения  count1


                                     ; отсчитали N мс, нужно обновить отображаемые цифры      
                                     ; подготовка разрядных масок анодов для индикации
;-------------------------------------------------------------------------------------------

           bcf         FLAG, 0       ; не выводить незначащие нули
                
           movfw       dig_H         ; загружаем внутренний счетчик в W
           call        MASKA         ; попрограмма возвращаетв W маску катодов
           movwf       ind_H         ; запоминаем маску соответствующего разряда

           movfw       dig_D 
           call        MASKA
           movwf       ind_D    

           bsf         FLAG, 0       ; ноль в разряде единиц выводить всегда
           movfw       dig_U 
           call        MASKA
           movwf       ind_U
;************************************************************************************
                                     ; проверка неплотно закрытых дверей
m4 
           btfsc       PORTA, DOOR   ; дверь открыта?
           goto        CYCLE
           movf        ind_D, F      ; машина едет более 9 км/ч?
           btfss       STATUS,Z 
           goto        m6
           movf        ind_H, F                    
           btfsc       STATUS,Z 
           goto        CYCLE
m6
           bcf         PORTA, 3      ; установим выходную защёлку линии порта в 0
           bsf        STATUS,RP0
           bcf         TRISA, 3      ; бит RA3 на вывод - включим сигнал и отключим
           bcf         STATUS,RP0    ; катоды индикаторов
           movlw       .60 
           movwf       SEC

                                     ; выведем слово  "dor"  на индикатор на полную яркость!!!!!!!
;-------------------------------------------------------------------------------------
m5 
        DOR     .1, 0Ah              ;  r 
        DOR     .2, 3Ah              ;  o 
        DOR     .4, 7Ah              ;  d
           decfsz      SEC, F
           goto        m5
           bsf         STATUS,RP0
           bsf         TRISA, 3      ; бит RA3 на ввод - выключим сигнал
           bcf         STATUS,RP0
           bsf         PORTA, 3      ; установим выходную защёлку линии порта в 1
           goto        CYCLE
      
                                     ; сервисный режим
                                     ;---------------------------------------------------- 
servis
           btfsc       PORTA, SB1    ; кнопка нажата?
           goto        m3s
           call        DELAY_004     ; дребезг
           call        DELAY_004 
           call        DELAY_004     
           call        DELAY_004 
           btfsc       PORTA, SB1
           goto        m3s
           bsf         FLAG, 4       ; установим флаг сервисной кнопки
           goto        servis
        
m1s     
           btfsc       FLAG, 5
           goto        m6s
           goto        servis
m3s
           btfss       FLAG, 4
           goto        m1s
           bcf         FLAG, 4
           incf        KOD, F
           movfw       KOD
           xorlw       .6
           bnz         $+3
           movlw       .1
           movwf       KOD
           btfsc       FLAG, 5       ; флаг счёта выставлен?
           goto        m5s
m6s
           call        DELAY_500 
           decfsz      TIME, F
           goto        m7s
           bcf         FLAG, 5 
       
           movfw       KOD
           bcf         PIR1, EEIF  
           bsf         STATUS, RP0   ; выберем банк1 
           movwf       EEDATA
           movlw       .1
           movwf       EEADR         ; выберем адрес  
           call        WR_KEY
      
                                     ; сигналим N раз после удачной записи
m4s                                  ;------------------------------------------------
           call        DELAY_500 
           bcf         PORTA, 3        
           bsf        STATUS,RP0     ; выберем банк1 
           bcf         TRISA, 3      ; RA3 на выход - включим сигнал 
           bcf         STATUS, RP0 
           call        DELAY_500
           bsf         STATUS, RP0
           bsf         TRISA, 3      ; RA3 на ввод - выключим сигнал
           bcf        STATUS,RP0
           bsf         PORTA, 3 
           decfsz      KOD, F
           goto        m4s
           nop
           nop
           goto        $-2           ; зациклим программу
m2s
           call        DELAY_500
           goto        m4s
m5s
           bcf         FLAG, 5
           movlw       .5
           movwf       TIME
           goto        m6s
m7s
             
           bsf         FLAG, 5
           goto        servis 
 
;------------------------------------------------------------------------------------
DELAY_004
           movlw       .48
           movwf       Reg_1
           movlw       .6
           movwf       Reg_2
           decfsz      Reg_1,F       ; 4 mS
           goto        $-1
           decfsz      Reg_2,F
           goto        $-3
           nop                
           return
DELAY_500
           movlw       .85
           movwf       Reg_1
           movlw       .138
           movwf       Reg_2
           movlw       .3
           movwf       Reg_3
           decfsz      Reg_1,F       ; 0,5 S
           goto        $-1
           decfsz      Reg_2,F
           goto        $-3
           decfsz      Reg_3,F
           goto        $-5
           nop
           nop    
           return  
WR_KEY
                                     ; запись в память EEPROM
;***************************************************************************************
                
       
           bsf         EECON1, WREN  ; разрешить запись в EEPROM
        
                                     ; специальная последовательность команд
           movlw       55h
           movwf       EECON2
           movlw       h'AA'
           movwf       EECON2
           bsf         EECON1, WR    ; установить бит начала записи
           bcf         STATUS, RP0     
WR_WAIT:
           btfss       PIR1,EEIF     ; проверяем флаг завершения записи
           goto        WR_WAIT       ; продолжаем ожидать окончание
           bsf         STATUS, RP0   ; запись закончена             
           bcf         EECON1, WREN  ; запрет записи в EEPROM
           bcf         STATUS, RP0   ; выберем банк0
           return
        

 
           end

            