        LIST p=16f877, st = OFF
		INCLUDE "p16f877.inc"
		__CONFIG _CP_OFF & _WDT_OFF & _BODEN_OFF & _PWRTE_ON & _XT_OSC & _WRT_ENABLE_ON & _LVP_OFF & _DEBUG_ON & _CPD_OFF
		
;----------------------------------------------------Хоррактеристики-------------------------------------------------------
;----------------------- Кварц=20МГц, подтягивающие резисторы. 1 - когда не нажата кнопка, 0 - когда кнопка нажата---------
;----------------------- Tosc=0.2мкс, время выполнения одной команды 200нс-------------------------------------------------
;----------------------------------------------------Переменные-------------------------------------------------------------	
		cblock 0x20 	  	;Ячейки данных
		Caunt ; счетчик количества измерений для тока
		R10   ;десятки
		R1    ;единицы		
		Temp1
		Temp2
		temp
  		Cnt             ; для АЦП задержка 
		In_L ; младшие разряды номинального тока аккумулятора
		In_H ; старшие разряды номинального тока аккумулятора
		Ia_L ; ток аккомулятора фактический десятичная часть
		Ia_H ; ток аккумулятора фактический целая часть
		Un_H ; напряжение наминальное аккумулатора целая часть
		Un_L ; напряжение наминальное аккумулатора десятичная часть
		Ua_L ;напряжение аккумулятора фактическое десятичная часть
		Ua_H ;напряжение аккумулятора фактическое целая часть часть
		Temp_Ia_H
		Temp_Ia_L			;переменная для хранения ока при измерениях
		dlit_imp
		Temp_In    
		Temp_Ia  ; временные переменные для хранения токов, напряжения и данных LCD
		Temp_In_H
		Temp_Ua
		Temp_Un
		Temp_Un_H
		Temp_Un_L
		Trener_Un_H
		Trener_Un_L
		Temp_LSD
		Vrem_znach
		neg_flag
		res4 ;результат после умножения, делимое, частное 
		res3
		res2
		res1
		a1
		a2
		b1
		b2 ;для умножения
		BCount ; для деления
		shiftH
        shiftM
        shiftL ;
		remainH ; остаток деления 
        remainM ; 
        remainL ; 
		denomH ; делитель
		denomM
		denomL


		
		Start
		Stop
		Razrady
		Ustanovit
		Uvelichit
		Umenshit
		Regim_Trener
		endc
;-----------------------Константы-----------------------
		Init_PA      	EQU   b'00111111' 	;все линии ввод 
		Init_PB      	EQU   b'00000000' 	;все на выход для LCD   
		Init_PC			EQU   b'00010010'   ;2 -вывод, остольные ввод
		Init_AD1    	EQU	  b'10000100'	;включены линии PORTE, результат АЦП вправо
		Init_ACP        EQU   b'10000001'   ;Fosc/32,канал AN0,разрешить A/D
		Init_PD         EQU   b'00001111'   ;0-4 ввод, остольные вывод
		Init_PE 		EQU   b'00000110'   ;0 на вывод,1,2 - ввод
		;Init_TMR0		EQU	  b'00000111'   ; предделитель 1/256
		Init_CCP1 		EQU   b'00010000'	;шим в ССP1CON  4,5 - младшие биты скваженности, 0000 - модуль выключен, 3..0 - включен/выключен 
		Init_PR2        EQU   b'01000000'
		Init_TMR2		EQU   b'00000101'   ;предделитель 1/4, выходной делитель 1/1, 2 бит таймер выключен (0)
		Con_mul_H		EQU	  0x39			;
		Con_mul_L		EQU	  0x39          ; 4883*3 цена деления для U
		Con_cel_H		EQU	  0xF
		Con_cel_M		EQU	  0x42
		Con_cel_L		EQU   0x40			; 1000000
		Con_des_H		EQU	  0x00
		Con_des_M		EQU   0x27
		Con_des_L		EQU   0x10			; 10000
		Con_R_H			EQU   0x00
		Con_R_M			EQU   0x20
		Con_R_L 		EQU   0x48			; Rшунта=8,264мОм		
;------------------ Битовые переменные ----------------------
	    #define	Regim_Rab       PORTC,0     ;режим работы устройства 0-зарядка, 1-тренировка
		;#define Regim_Trener    PORTC,1		;режим тренировки 0-зарядка, 1-тренировка
		;#define Umenshit 	    PORTD,0		;кнопка -
		;#define Uvelichit		PORTD,1		;кнопка +
     	;#define Ustanovit		PORTD,2		;кнопка установка
	;	#define Start			PORTD,3		;кнопка старт
	;	#define Stop			PORTC,4		;кнопка стоп
		#define Lampa_Stop		PORTC,6		;лампа стоп
		#define Lampa_Zaradka	PORTC,7		;лампа зарядка
		#define Lampa_Avar		PORTC,3		;лампа авария
		#define Lampa_Trener	PORTD,4		;лампа тренировка
	;	#define Razrady			PORTE,2		;выбор целой или десятичной части наминальных параметров
		#define A0              PORTD,7     ;адресный сигнал, выбор между передачей данных и команд управления
		#define zap_chten       PORTD,6     ;выбор режима записи или чтения
		#define E               PORTD,5     ;разрешение обращения к индикатору а так же строб данных
        
;--------------------------------------------------------------------
		ORG		0x000			       
		nop
		goto 		Begin
;------------Подпрограмма задержки  (для АЦП 20мкс)--------------????????????????????
Dly	    movwf	    Cnt
Dlp	    decfsz	    Cnt,F
	    goto		Dlp
	    return
;=====================================================================================
;----------Подпрограмма задержки 45мкс для LSD----------------------------------------------
;=====================================================================================
T_15ms				   
		movlw	.7                   
		movwf	Temp2                      
t_15ms 	call	T_500us          
		decfsz	Temp2,1           
		goto	t_15ms                 
		return
;-----------------подпрограмма задержки 500 мкс устранения дребизна контактов---------------------?????????????????????
T_500us          				           
       	movlw 	.8
        movwf 	Temp1
t_500us 	decfsz 	Temp1,1
        goto 	t_500us
        return

;======================================================================================================
;------------------- Подпрограмма задержки 15 мс для устранения дребизна контактов---------------------??????????????
;======================================================================================================
D15ms				   
		movlw	.180                     
		movwf	Temp2                      
_15ms 	call	D500us          
		decfsz	Temp2,1           
		goto	_15ms                    
		return
;-----------------подпрограмма задержки 500 мкс устранения дребизна контактов---------------------?????????????????????
D500us          				           
       	movlw 	.150
        movwf 	Temp1
_500us 	decfsz 	Temp1,1
        goto 	_500us
        return
;----------Опрос кнопок на отжатие-------------------
Release0                          
	    call		D15ms	       			;задержка   		
	;	btfss		Umenshit             		;опрос кнопки 
		btfss		Umenshit,0
        goto	    Release0	        	    ;кнопка не отжата
		call		D15ms	       			;задержка             
		return            	            	;кнопка отжата
;----------Опрос кнопок на отжатие-------------------
Release1                          
	   	call		D15ms	       			;задержка   		
;		btfss		Uvelichit             		;опрос кнопки 
		btfss		Uvelichit,0
        goto	    Release1	        	    ;кнопка не отжата
		call		D15ms	       			;задержка             
		return            	            	;кнопка отжата
;----------Опрос кнопок на отжатие-------------------
Release2                          
	    call		D15ms	       			;задержка   		
		;btfss		Ustanovit             		;опрос кнопки 
		btfss		Ustanovit,0
        goto	    Release2	        	    ;кнопка не отжата
		call		D15ms	       			;задержка             
		return            	            	;кнопка отжата
;----------Опрос кнопок на отжатие-------------------
Release3                          
	   	call		D15ms	       			;задержка   		
	;	btfss		Start             		;опрос кнопки  
		btfss		Start,0
        goto	    Release3	        	;кнопка не отжата
		call		D15ms	       			;задержка             
		return            	            	;кнопка отжата
;----------Опрос кнопок на отжатие-------------------
Release4                          
	    call		D15ms	       			;задержка   		
	;	btfss		Stop             		;опрос кнопки 
		btfss		Stop,0
        goto	    Release4	        	;кнопка не отжата
		call		D15ms	       			;задержка             
		return            	            	;кнопка отжата
;----------Опрос кнопок на отжатие-------------------
Release5                          
	    call		D15ms	       			;задержка   		
	;	btfss		Razrady             	;опрос кнопки 
		btfss		Razrady,0 
        goto	    Release5	        	;кнопка не отжата
		call		D15ms	       			;задержка             
		return            	            	;кнопка отжата
;----------Опрос кнопок на фиксацию-------------------
Release6                          
	    call		D15ms	       			;задержка   		
	;	btfss		Regim_Trener            ;опрос кнопки 
		btfss		Regim_Trener,0
        goto	    Release6	        	;кнопка не зафиксированна
		call		D15ms	       			;задержка             
		return            	            	;кнопка зафиксированна
;----------Опрос кнопок на фиксацию-------------------
Release7                          
	    call		D15ms	       			;задержка   		
	;	btfsc		Regim_Trener            ;опрос кнопки 
		btfsc		Regim_Trener,0
        goto	    Release7	        	;кнопка отлипла
		call		D15ms	       			;задержка             
		return            	            	;кнопка отлипла

;------------Подпрограмма изображения цифр на индикаторе от 0 до 9-----------------       
Table		
		addwf PCL,f
		retlw   	0x03  
		retlw   	0x13
		retlw   	0x23
		retlw   	0x33
		retlw   	0x43
		retlw   	0x53
		retlw   	0x63
		retlw   	0x73
		retlw   	0x83
		retlw   	0x93
;--Подпрограмма преобразования в двоично-десятичный код --------------
B2_BCD
        clrf   R1
		clrf   R10
		bcf    STATUS,C

CON_10	movlw .10		
		subwf Vrem_znach,w
		btfss STATUS,C
		goto CON_1
		incf R10,f
		movwf Vrem_znach
		goto CON_10;

CON_1   movlw .1		
		subwf Vrem_znach,w
		btfss STATUS,C
		goto M1
		incf R1,f
		movwf Vrem_znach
		goto CON_1;
M1      clrf  Vrem_znach
		return
;-----------------------------------------------------------------------------------
;------------------------Вывод информации на дисплей--------------------------------
;------------------------------------------------------------------------------------
Vivod
		movwf    Temp_LSD
        banksel  TRISB   ; выбор банка 1
		movlw    b'11111111'
		movwf    TRISB
		banksel  PORTB
ZAN  	bcf      zap_chten ; для цикличности проверки если R/W до этого был установлен сбросить его и заново установить
		bsf      zap_chten ; R/W:=1
		bcf      E  ;
		bsf      E ; если строб данных бул установлен до этого сбрасываем и сново устанавливаем для приема флага занятости
		btfsc    PORTB,7
		goto     ZAN
		bcf      E
		bcf      zap_chten
		banksel  TRISB
	    movlw    b'00000000'
		movwf    TRISB
		banksel  PORTB   ; возврат в банк 0
		bsf      A0
		bsf      E
		movf     Temp_LSD,w
		movwf    PORTB ; вывод на шину байт данных
		NOP 			;чуть больше повисят данные на порту
		bcf      E
		bcf      A0
		clrf     PORTB
		return
;--------------------------------------------------------------------------------
;-----------------------Подпрограмма прирывания (40мкс)--------------------------
;---------------------------------------------------------------------------------
Indicac
;----------------------------Очистка дисплея------------------------
		banksel     PORTB
		bsf         E
		movlw       b'00000001' ;очистка дисплея и переместить курсор в крайне левое положение
		movwf       PORTB
		NOP         
		bcf         E
		clrf        PORTB
		movlw		0xFF
		call        Dly
		banksel 	TRISB   ; выбор банка 1
		movlw    	b'11111111'
	   	movwf    	TRISB
		banksel  	PORTB
ZAN_2  	bcf      	zap_chten ; для цикличности проверки если R/W до этого был установлен сбросить его и заново установить
		bsf      	zap_chten ; R/W:=1
		bcf     	 E  ;
		bsf     	 E ; если строб данных бул установлен до этого сбрасываем и сново устанавливаем для приема флага занятости
		btfsc   	 PORTB,7
		goto    	 ZAN_2
		bcf     	 E
		bcf      	 zap_chten
	  	banksel 	 TRISB
	    movlw   	 b'00000000'
		movwf   	 TRISB		
;-----------------------------вывод значения In и символа----------------------
		movlw       0x49 ; символ I
		call        Vivod
		movlw       0x6E ; символ n
		call        Vivod
		movlw       0x2D ; символ -
		call        Vivod 
        movf        In_H,w 
		movwf       Vrem_znach
    	call	    B2_BCD; переслали значение старшего байта In во временную переменную
		movf        R10,w ; получив значение выводим на дисплей десятки
		call        Table
		call        Vivod ; вывел значение In_H десятые
		movf        R1,w ; получив значение выводим на дисплей единицы
		call        Table
		call        Vivod ; вывел значение In_H единицы
		movf        In_L,w 
		movwf       Vrem_znach
    	call	    B2_BCD; переслали значение младшего байта In во временную переменную
		movf        R10,w ; получив значение выводим на дисплей десятки
		call        Table
		call        Vivod ; вывел значение In_L десятые
		movf        R1,w ; получив значение выводим на дисплей единицы
		call        Table
		call        Vivod ; вывел значение In_L единицы
;------------------------------вывод символа ;-----------------------------
        movlw       0x3B ; символ ;
		call        Vivod
;------------------------------вывод значения Un и символа------------------
		movlw       0x55 ; символ U
		call        Vivod
		movlw       0x6E ; символ n
		call        Vivod
		movlw       0x2D ; символ -
		call        Vivod 
        movf        Un_H,w 
		movwf       Vrem_znach
    	call	    B2_BCD; переслали значение старшего байта In во временную переменную
		movf        R10,w ; получив значение выводим на дисплей десятки
		call        Table
		call        Vivod ; вывел значение Un_H десятые
		movf        R1,w ; получив значение выводим на дисплей единицы
		call        Table
		call        Vivod ; вывел значение Un_H единицы
		movf        Un_L,w 
		movwf       Vrem_znach
    	call	    B2_BCD; переслали значение младшего байта Un во временную переменную
		movf        R10,w ; получив значение выводим на дисплей десятки
		call        Table
		call        Vivod ; вывел значение Un_L десятые
;==============================================================================
;------------------------------переход на вторую строчку-----------------------
;==============================================================================
		banksel 	TRISB   ; выбор банка 1
		movlw    	b'11111111'
	   	movwf    	TRISB
		banksel  	PORTB
ZAN_3  	bcf      	zap_chten ; для цикличности проверки если R/W до этого был установлен сбросить его и заново установить
		bsf      	zap_chten ; R/W:=1
		bcf     	 E  ;
		bsf     	 E ; если строб данных бул установлен до этого сбрасываем и сново устанавливаем для приема флага занятости
		btfsc   	 PORTB,7
		goto    	 ZAN_3
		bcf     	 E
		bcf      	 zap_chten
	  	banksel 	 TRISB
	    movlw   	 b'00000000'
		movwf   	 TRISB
		banksel     PORTB
		bsf         E 
		movlw       b'11000000' ; передвинуть курсор на адрес 40h
		movwf       PORTB
		NOP
		bcf         E
		clrf        PORTB		
;------------------------------вывод значения Ia и символа---------------------
		movlw       0x49 ; символ I
		call        Vivod
		movlw       0x61 ; символ a
		call        Vivod
		movlw       0x2D ; символ -
		call        Vivod 
        movf        Ia_H,w 
		movwf       Vrem_znach
    	call	    B2_BCD; переслали значение старшего байта Ia во временную переменную
		movf        R10,w ; получив значение выводим на дисплей десятки
		call        Table
		call        Vivod ; вывел значение Ia_H десятые
		movf        R1,w ; получив значение выводим на дисплей единицы
		call        Table
		call        Vivod ; вывел значение Ia_H единицы
		movf        Ia_L,w 
		movwf       Vrem_znach
    	call	    B2_BCD; переслали значение младшего байта In во временную переменную
		movf        R10,w ; получив значение выводим на дисплей десятки
		call        Table
		call        Vivod ; вывел значение Ia_L десятые
		movf        R1,w ; получив значение выводим на дисплей единицы
		call        Table
		call        Vivod ; вывел значение Ia_L единицы
;------------------------------вывод символа ;-----------------------------
        movlw       0x3B ; символ ;
		call        Vivod
;------------------------------вывод значения Ua и символа---------------------------
		movlw       0x55 ; символ U
		call        Vivod
		movlw       0x61 ; символ a
		call        Vivod
		movlw       0x2D ; символ -
		call        Vivod 
        movf        Ua_H,w 
		movwf       Vrem_znach
    	call	    B2_BCD; переслали значение старшего байта In во временную переменную
		movf        R10,w ; получив значение выводим на дисплей десятки
		call        Table
		call        Vivod ; вывел значение Un_H десятые
		movf        R1,w ; получив значение выводим на дисплей единицы
		call        Table
		call        Vivod ; вывел значение Un_H единицы
		movf        Ua_L,w 
		movwf       Vrem_znach
    	call	    B2_BCD; переслали значение младшего байта Un во временную переменную
		movf        R10,w ; получив значение выводим на дисплей десятки
		call        Table
		call        Vivod ; вывел значение Un_L десятые
		return
;-----------------------------------------------------------------------------------
;------------Подпрограмма Установки номинала аккомулятора---------------------------
;-----------------------------------------------------------------------------------
naminal_I
;-------------------------------Установка целой части In(А)-------------------------
celay_I	
	;	btfss    Razrady   ;проверить, пропустить если 0
		btfss    Razrady,0
		goto	 desatichn_I	
	;	BTFSS    Uvelichit ; проверить бит пропустить если 0
		BTFSS    Uvelichit,0
		INCF     In_H ; +
        call     Release1 
		call     Indicac
	;	BTFSS    Umenshit ; проверить бит пропустить если 0
		BTFSS    Umenshit,0
        DECF     In_H ; -
		call     Indicac
        call  	 Release0 
      ;  btfss 	 Ustanovit
		btfss 	 Ustanovit,0
    	goto     VOZVRAT
	;	btfsc    Razrady   ;проверить, пропустить если 0
		btfsc    Razrady,0
        goto   	 celay_I
		call	 Release5
		goto     desatichn_I						
;--------------------------------Установка десятичной части In(А)--------------------
desatichn_I
	;	btfss    Razrady   ;проверить, пропустить если 0
		btfss    Razrady,0
		goto	 celay_I	
;		BTFSS    Uvelichit ; проверить бит пропустить если 0
		BTFSS    Uvelichit,0
		INCF     In_L ; +
        call     Release1 
		call     Indicac
	;	BTFSS   Umenshit ; проверить бит пропустить если 0
		BTFSS    Umenshit,0
        DECF     In_L ; -
        call  	 Release0 
    	call     Indicac
    ;    btfss 	 Ustanovit
		btfss 	 Ustanovit,0
		goto     VOZVRAT
	;	btfsc    Razrady   ;проверить, пропустить если 0
		btfsc    Razrady,0
		goto     desatichn_I
		call	 Release5
		goto     celay_I
;-----------------------------------Выход из подпрограммы--------------------------------
VOZVRAT	
		call     Release2
        return	
;---------------------------------------------------------------------------------------
naminal_U
;-------------------------------Установка целой части Un(B)-------------------------
celay_U		
;			btfss    Razrady   ;проверить, пропустить если 0
			btfss    Razrady,0
			goto	 desatichn_U	
		;	BTFSS   Uvelichit ; проверить бит пропустить если 0
			BTFSS    Uvelichit,0
			INCF     Un_H ; +
            call     Release1
			call     Indicac 
			;BTFSS    Umenshit ; проверить бит пропустить если 0
			BTFSS    Umenshit,0
            DECF     Un_H ; -
            call  	 Release0
			call     Indicac 
          ;  btfss 	 Ustanovit
			btfss 	 Ustanovit,0
			goto     VOZVRAT1
		;	btfsc    Razrady   ;проверить, пропустить если 0
			btfsc    Razrady,0
            goto   	 celay_U
			call	 Release5
			goto     desatichn_U				
;--------------------------------Установка десятичной части Un(B)--------------------
desatichn_U	
;			btfss    Razrady   ;проверить, пропустить если 0
			btfss    Razrady,0
			goto	 celay_U	
	;		BTFSS    Uvelichit ; проверить бит пропустить если 0
			BTFSS    Uvelichit,0
			INCF     Un_L ; +
            call     Release1 
			call     Indicac
	;		BTFSS    Umenshit ; проверить бит пропустить если 0
			BTFSS    Umenshit,0
            DECF     Un_L ; -
            call  	 Release0 
			call     Indicac
      ;      btfss 	 Ustanovit
			btfss 	 Ustanovit,0
			goto     VOZVRAT1
		;	btfsc    Razrady   ;проверить, пропустить если 0
			btfsc    Razrady,0
			goto     desatichn_U
			call	 Release5
			goto     celay_U
;------------------------------------Выход из подпрограммы--------------------------------
VOZVRAT1	call     Release2
            return			

;----------------------------------------------------------------------------------------
;------------Подпрограмма Опрос датчиков -----------------------------------------------
;-----------------------------------------------------------------------------------------
oprdatch
;----------------------------Первый опрос АЦП AN0(Ua)--------------------
			banksel     ADCON1
			movlw       Init_AD1
			movwf		ADCON1
			banksel     ADCON0
			movlw       Init_ACP
			movwf       ADCON0
			movlw		.255  ;напряжение AN0 (Ua)
			call		Dly  ; задержка 26мс для зарядки конденсатора АЦП??????
			bsf		    ADCON0,GO	;Начало A/D преобразования  
Wait0 		btfsc		ADCON0,GO	;Ожидание завершения 
			goto		Wait0		;A/D преобразования
			movf		ADRESH,W	
			movwf		Ua_H
			banksel     ADRESL    
			movf		ADRESL,W	
			movwf		Ua_L
			NOP
;----------------------------Второй опрос АЦП AN1(Ia)-------------------
		    clrf        Temp_Ia_L
			clrf		Temp_Ia_H
			clrf        Caunt
			bcf         STATUS,Z
			bsf         STATUS,RP0
			movlw       .10
			movwf       Caunt
			banksel     ADCON0
			bsf			ADCON0,CHS0 ; выбор канала AN1
    		movlw		.20/.88		;ток AN1 (Ia)
escho		call		Dly ; задержка 26мс для зарядки конденсатора АЦП
			bsf			ADCON0,GO	;Начало A/D преобразования 
Wait1   	btfsc		ADCON0,GO	;Ожидание завершения 
			goto		Wait1		;A/D преобразования
			bcf			ADCON0,CHS1
			bcf         STATUS,C
			BANKSEL     ADRESL					
			movf		ADRESL,W
			addwf       Temp_Ia_L
			btfsc       STATUS,C
			incf        Temp_Ia_H
			BANKSEL     ADRESH
			movf		ADRESH,W
			addwf       Temp_Ia_H
			decfsz      Caunt
			goto        escho
		    movf        Temp_Ia_L,w
			movwf       res1
			movf        Temp_Ia_H,w
			movwf       res2
			movlw       .10
			movwf       denomL
            call        Div ; находим средне аррифметическое после 10 измерений
			movf        res2,w
			movwf       Ia_H
			movf        res1,w
			movwf       Ia_L ; остаток после деления не учитываю
			return
;--------------------------------------------------------------------------
;-----------------------Подпрограмма зарядки------------------------------
;-----------------------Длительность=CCPR1L/CCP1CON<5,4>*Toscx*1----------
;-------------------------------------------------------------------------
zaradca		
			banksel  CCP1CON
			btfss    CCP1CON,CCP1M3
		    goto     Prov_cel
			bsf		 CCP1CON,CCP1M3 
			bsf		 CCP1CON,CCP1M2	; включаем ССР1 в режиме шим (взвод 2 и 3 бита)	
Prov_cel	bcf      STATUS,C ;сравниваем старшую часть числа Ia c In
			clrf     Temp_In
			clrf     Temp_Ia
			movf     In_H,w
			movwf    Temp_In
			movf     Ia_H,w
			movwf    Temp_Ia
			bcf      STATUS,C
			movf     Temp_Ia,W
			subwf	 Temp_In_H,W ; проверяем In(целая часть)-Ia(целая часть) 
			btfss    STATUS,C  ; ток номинальный выше чем ток зарядки 
			goto     Prov_desat ; нет
			decf	 dlit_imp	;да, ; уменьшить длительность импульса		
			goto	 VIHOD			; выход из подпрограммы							
Prov_desat  clrf     Temp_In ;сравниваем младшую часть числа Ia c In
			clrf     Temp_Ia		
			movf     In_L,w
			movwf    Temp_In
			movf     Ia_L,w
			movwf    Temp_Ia
			bcf      STATUS,C
			movf     Temp_Ia,w
			subwf	 Temp_In,w ; проверяем In(десятичная часть)-Ia(десятичная часть) 
			btfss    STATUS,C  ; ток номинальный выше чем ток зарядки 
			goto     Uv_Dlit ; нет
			decf	 dlit_imp	 ;да, уменьшить длительность импульса		
			goto	 VIHOD	;    выход из подпрограммы 
Uv_Dlit     incf    dlit_imp   ;увеличить длительность импульса
;------------------------выйти из подпрограммы----------------------------
VIHOD       movf     dlit_imp,w
			movwf    CCPR1L
			return

;--------------------------------------------------------------------------------
;--------------------------------Подпрограмма умножения--------------------------
;-------------------------------------------------------------------------------- 
Mult   
    	clrf    res4
		clrf	res3
		clrf    res2
		movlw	0x80
		movwf	res1	
		clrf	neg_flag
		btfss   a2,7
		goto    a_pos
		comf    a2,f
		comf	a1,f
		incf	a1,f
		btfsc	STATUS,Z
		incf    a2,f
		incf	neg_flag, f
a_pos
		btfss   b2,7
		goto    nextbit
		comf    b2,f
		comf    b1,f 
		incf    b1,f 
		btfsc   STATUS,Z
		incf    b2,f
		incf	neg_flag, f
nextbit
		rrf		a2,f
		rrf		a1,f
		btfss	STATUS,C
		goto	nobit_l
		movf	b1,w
		addwf	res2,f

		movf	b2, w
		btfsc	STATUS,C
		incfsz	b2, w	
		addwf	res3, f	
		btfsc	STATUS,C
		incf	res4, f
		bcf		STATUS,C	
nobit_l	
		btfss	a1, 7
		goto	nobit_h
		movf	b1,w
		addwf	res3,f
		btfsc	STATUS,C
		incf	res4,f
		movf	b2,w		
		addwf	res4,f
nobit_h
		rrf		res4,f
		rrf		res3,f
		rrf		res2,f
		rrf		res1,f
		btfss   STATUS,C
		goto	nextbit
		btfss   neg_flag, 0
		goto 	no_invert		
		comf    res4,f
		comf    res3,f
		comf    res2,f
		comf	res1,f
		incf    res1,f ; 0 байт
		btfsc   STATUS,Z
		incf	res2,f  ; 1 байт
		btfsc   STATUS,Z
		incf    res3,f  ; 2 байт
		btfsc   STATUS,Z
		incf    res4,f ; 3 байт
no_invert   NOP
			return
;-----------------------------------------------------------------------------
;---------------------------------ДЕЛЕНИЕ------------------------------------
;----------------------------------------------------------------------------
Div
divizn  movlw .24
        movwf BCount
        movf res3,w
        movwf shiftH
        movf res2,w
        movwf shiftM
        movf res1,w
        movwf shiftL
        clrf res3
        clrf res2
        clrf res1
        clrf remainH
        clrf remainM
        clrf remainL
dloop   bcf STATUS,C
        rlf shiftL
        rlf shiftM
        rlf shiftH
        rlf remainL
        rlf remainM
        rlf remainH
        movf denomH,w
        subwf remainH,w
        btfss STATUS,Z
        goto nochk
        movf denomM,w
        subwf remainM,w
        btfss STATUS,Z
        goto nochk
        movf denomL,w
        subwf remainL,w
nochk   btfss STATUS,C
        goto nogo
        movf denomL,w
        subwf remainL
        btfss STATUS,C
        decf remainM
        movf remainM,w
        xorlw 0xff
        btfsc STATUS,Z
        decf remainH
        movf denomM,w
        subwf remainM
        btfss STATUS,C
        decf remainH
        movf denomH,w
        subwf remainH
        bsf STATUS,C
nogo    rlf res1
        rlf res2
        rlf res3
        decfsz BCount
        goto dloop
        return
;-----------------------------------------------------------------------------
;---------------------------Подсчет значения тока и напряжения----------------
;-----------------------------------------------------------------------------
podschet
;================================================================================
;----------------------------Подсчитываем напряжение-----------------------------
;================================================================================
		movf  Ua_H,w
		movwf a2
		movf  Ua_L,w
		movwf a1
		movlw Con_mul_H
		movwf b2
		movlw Con_mul_L
		movwf b1 	    
		call  Mult ; Ua_H,Ua_L*4883*3
		movlw Con_cel_H
		movwf denomH
		movlw Con_cel_M
		movwf denomM
        movlw Con_cel_L
		movwf denomL
		call  Div ; Ua_H,Ua_L/1000000
        movf  res1,w
		movwf Ua_H		
		movf  remainH,w
		movwf res3
		movf  remainM,w
		movwf res2
		movf  remainL,w
		movwf res1 ; остаток деления загружаем в делимое
		movlw Con_des_H
		movwf denomH
		movlw Con_des_M
		movwf denomM
		movlw Con_des_L
		movwf denomL
		call  Div ; остаток от деления / 10000
		movf  res1,w
		movwf Ua_L
;================================================================================
;--------------------------Подсчитываем ток--------------------------------------
;=================================================================================
        movf  Ia_H,w
		movwf a2
		movf  Ia_L,w
		movwf a1 ; переслали среднее значение
		movlw 0x13
		movwf b2
		movlw 0x13
		movwf b1 ; переслали .4883
		call  Mult
		movlw 0x00
		movwf denomH
		movlw 0x00
		movwf denomM
		movlw 0x37
		movwf denomL ;.55
		call  Div ; поделили полученое значение на коэффициент усиления без учета остатка
		movlw Con_cel_H
		movwf denomH
		movlw Con_cel_M
		movwf denomM
		movlw Con_cel_L
		movwf denomL ;.1000000
		call  Div ;
		movf  remainH,w
		movwf res3
		movf  remainM,w
		movwf res2
		movf  remainL,w
		movwf res1 ; перенесли остаток деления в делимое
		movlw Con_R_H
		movwf denomH
		movlw Con_R_M
		movwf denomM
		movlw Con_R_L
		movwf denomL ; переслали коэфициент сопративления шунта
		call  Div ; I=U/R
		movf  res2,w
		movwf Ia_H ; целая часть тока 
        movf  remainH,w
		movwf res3
		movf  remainM,w
		movwf res2
		movf  remainL,w
		movwf res1 ; остаток деления загружаем в делимое
		movlw Con_des_H
		movwf denomH
		movlw Con_des_M
		movwf denomM
		movlw Con_des_L
		movwf denomL
		call  Div ; остаток от деления / 10000
		movf  res1,w
		movwf Ia_L
;------------------------------------------------------------------
;-------------------------------Инсталяция дисплея-----------------
;------------------------------------------------------------------- 
Inst_LSD
		 BANKSEL PORTB ; выбрал банк 0	
		 call   T_15ms
		 bcf    A0
		 bcf    zap_chten
		 bsf    E
	     movlw  b'00110000' ; 1 раз
		 movwf  PORTB
		 NOP
		 bcf    E
		 clrf   PORTB
		 call   T_15ms
		 bsf    E
		 movlw  b'00110000' ; 2 раз
		 movwf  PORTB
		 NOP
		 bcf    E
		 clrf   PORTB
		 call   T_15ms
         bsf    E
		 movlw  b'00110000' ; 3 раз
		 movwf  PORTB
		 NOP
		 bcf    E
		 clrf   PORTB
		 call   T_15ms
         bsf    E
		 movlw  b'00111000' ; установка параметров
		 movwf  PORTB
		 NOP
		 bcf    E
		 clrf   PORTB
		 call   T_15ms
		 bsf    E
		 movlw  b'00001000' ; выключение дисплея
		 movwf  PORTB
		 NOP
		 bcf    E
		 clrf   PORTB
		 call   T_15ms
		 bsf    E
		 movlw  b'00000001' ; очистка дисплея 
		 movwf  PORTB
		 NOP
		 bcf    E
		 clrf   PORTB
		 movlw  0xFF
		 call   Dly 
		 banksel TRISB   ; выбор банка 1
		 movlw    b'11111111'
	   	 movwf    TRISB
		 banksel  PORTB
ZAN_1  	 bcf      zap_chten ; для цикличности проверки если R/W до этого был установлен сбросить его и заново установить
		 bsf      zap_chten ; R/W:=1
		 bcf      E  ;
		 bsf      E ; если строб данных бул установлен до этого сбрасываем и сново устанавливаем для приема флага занятости
		 btfsc    PORTB,7
		 goto     ZAN_1
		 bcf      E
		 bcf      zap_chten
	  	 banksel  TRISB
	     movlw    b'00000000'
		 movwf    TRISB
		 banksel  PORTB   ; возврат в банк 0	
		 bsf    E
		 movlw  b'00000110' ; установка режима ввода данных
		 movwf  PORTB
	 	 NOP
		 bcf    E
		 clrf   PORTB
		 call   T_15ms
		 bsf    E
		 movlw   b'00001111' ; индикатор включить, курсор есть подчеркивание он и мигает
		 movwf  PORTB
		 NOP
		 bcf    E
		 clrf   PORTB
		 call   T_15ms
		 bsf    E
		 movlw  b'00000110' ; сдвиг курсора вправа
		 movwf  PORTB
		 bcf    E
		 clrf   PORTB
		 call   T_15ms
		 bsf    E
		 movlw  b'10000000' ; запись данных в DDRAM
		 movwf  PORTB
		 bcf    E
		 clrf   PORTB
		 call   T_15ms
		 return      ; возврат, LSD в 8 битном режиме, страница знакогениратора 0 и готовый к работе
;-----------------------------------------------------------------
;------------Подпрограмма АВАРИЯ----------------------------------
;-----------------------------------------------------------------
avariy
			banksel  CCP1CON
			bcf		 INTCON,GIE	;запрет всех прерываний
			bcf		 CCP1CON,CCP1M3 
			bcf		 CCP1CON,CCP1M2 ;выключить ШИМ
	        bcf Lampa_Zaradka;гасим начало
			bcf Lampa_Stop;гасим конец
			bsf Lampa_Avar;загорается авария
spim    ;	btfsc Stop ;опрос кнопки стоп
			btfsc Stop,0
			goto  spim
			call  Release4
			banksel    CCP1CON
	        bsf		 INTCON,GIE
			return
;------------------------------------------------------------------
;------------Подпрограмма КОНЕЦ----------------------------------
;--------------------------------------------------------------------
konec
		  banksel    CCP1CON
	      bcf		 INTCON,GIE	;запрет всех прерываний
		  bcf		 CCP1CON,CCP1M3 
		  bcf		 CCP1CON,CCP1M2 ;выключить ШИ
	      bcf Lampa_Zaradka;гасим начало
		  bsf Lampa_Stop;загорается конец	
spi    ;   btfss Stop ;опрос кнопки стоп
		  btfss Stop,0	
		  goto  dalshe
         ; btfss Regim_Trener ; опрос режима работы устройства
		  btfss Regim_Trener,0
		  goto  spi
		  call  Release6 ; опрос кнопки на фиксацию 
		  call  Trenirovka ; режим тренировка аккумулятора
		;  btfsc Stop ;опрос кнопки стоп
		  btfsc Stop,0
		  goto  spi ; кнопка не нажата, остаемся в "СТОП"
dalshe	  call Release4 ; стоп нажат, выход
		  banksel    CCP1CON
	      bsf		 INTCON,GIE
		  return
;----------------------------------------------------------------------------------
;--------------------------------Подпрограмма тренеровка--------------------------
;----------------------------------------------------------------------------------
Trenirovka
;--------------------Сохранили значения Un----------------------------------------
		  movf    Un_H,w
		  movwf   Trener_Un_H
   		  movf    Un_L,w
		  movwf   Trener_Un_L
;--------------------Пересчитали Un для режима тренировки -----------------------
		  movf	  Trener_Un_L,w
		  movwf   Temp_Un
		  movlw   .5
		  bcf     STATUS,C
		  subwf   Temp_Un
		  btfss   STATUS,C
		  goto    tren
		  decf    Trener_Un_H
		  movf    Temp_Un,w
		  movwf   Trener_Un_L		  		  
;--------------------Разряжаем до Ua=Un-0.5----------------------
tren	  
		  banksel CCP1CON
	      bcf	  INTCON,GIE ; запретить прерывания
		  bsf     Regim_Rab ; подали сигнал на подключен нагрузки
tr_1	  
	;	  btfss	  Regim_Trener
		  btfss	  Regim_Trener,0
		  goto    kon
		  call    oprdatch ;опрашиваем АЦП
		  call    podschet ;подсчитываем значение
		  call    Indicac
		  movf    Ua_H,w ; проверяем старший байт
		  movwf   Temp_Ua
		  movf    Trener_Un_H,w
		  bcf     STATUS,C
		  bcf     STATUS,Z
		  subwf   Temp_Ua ; проверяем старший байт Ua-Trener_Un_H
		  btfsc   STATUS,C
		  goto    tr_zar ; напряж на аккумул<напряж тренировки
		  btfsc   STATUS,Z
		  goto    pr_des ;проверяем десятичную часть
		  goto    tr_1 ; продолжаем разряжать
pr_des	  
		  movf    Ua_L,w ; проверяем младший байт
		  movwf   Temp_Ua
		  movf    Trener_Un_L,w
		  bcf     STATUS,C
		  bcf     STATUS,Z
		  subwf   Temp_Ua ; проверяем младший байт Ua-Trener_Un_L
		  btfsc   STATUS,C
		  goto    tr_zar
		  btfsc   STATUS,Z
		  goto    tr_zar ;младшие части ровны, заряжаем
		  goto    tr_1 ; младшие части не равны, разряжаем
;-------------------------------------------------------------------- 		  
tr_zar    
		  banksel CCP1CON
	      bsf	  INTCON,GIE
		  bcf     Regim_Rab; начинаем заряжать
tr_zar_1  
;		  btfss	  Regim_Trener
          btfss	  Regim_Trener,0
		  goto    kon
		  call    oprdatch ;опрашиваем АЦП
		  call    podschet ;подсчитываем значение
		  call    Indicac          
       	  call    zaradca
		  movf    Un_H,w
		  addlw   .2 ;увеличели номинальное напряжение на 2B, проверка повышенного напряжения
	      movwf   Temp_Un
		  movf    Ua_H,w
		  bcf     STATUS,C
		  bcf     STATUS,Z
		  subwf   Temp_Un ; Temp_Un-Ua_H
		  btfsc   STATUS,C ; Ua_H>Un_H+2
		  goto    tren ; да, начинаем разряжать
		  btfss   STATUS,Z
          goto    tr_zar_1  ;результат не ноль, заряжаем
		  goto    tren ; результат ноль, начинаем разряжать
;----------------------------------------------------------------------
kon      
		 call     Release7 ; опрос кнопки на отщелкивание
		 return

;=================================================================================     
;---------------------------Основная програма-------------------------------------   
;==================================================================================                      
;--------------------------Инициализация---------------------------  
Begin   
;------------------------Инициализация ячеек памяти-------------------
			clrf  INTCON		;запретить все прерывания  
			clrf Caunt ; счетчик количества измерений для тока
			clrf R10   ;десятки
			clrf R1    ;единицы		
			clrf Temp1
			clrf Temp2
			clrf temp
  			clrf Cnt             ; для АЦП задержка 
			clrf In_L ; младшие разряды номинального тока аккумулятора
			clrf In_H ; старшие разряды номинального тока аккумулятора
			clrf Ia_L ; ток аккомулятора фактический десятичная часть
			clrf Ia_H ; ток аккумулятора фактический целая часть
			clrf Un_H ; напряжение наминальное аккумулатора целая часть
			clrf Un_L ; напряжение наминальное аккумулатора десятичная часть
			clrf Ua_L ;напряжение аккумулятора фактическое десятичная часть
			clrf Ua_H ;напряжение аккумулятора фактическое целая часть часть
			clrf Temp_Ia_H
			clrf Temp_Ia_L			;переменная для хранения ока при измерениях
			clrf dlit_imp
			clrf Temp_In    
			clrf Temp_Ia  ; временные переменные для хранения токов, напряжения и данных LCD
			clrf Temp_In_H
			clrf Temp_Ua
			clrf Temp_Un
			clrf Temp_Un_H
			clrf Temp_Un_L
			clrf Trener_Un_H
			clrf Trener_Un_L
			clrf Temp_LSD
			clrf Vrem_znach
			clrf neg_flag
			clrf res4 ;результат после умножения, делимое, частное 
			clrf res3
			clrf res2
			clrf res1
			clrf a1
			clrf a2
			clrf b1
			clrf b2 ;для умножения
			clrf BCount ; для деления
			clrf shiftH
     	    		clrf shiftM
     	    		clrf shiftL ;
			clrf remainH ; остаток деления 
    	    		clrf remainM ; 
    	    		clrf remainL ; 
			clrf denomH ; делитель
			clrf denomM
			clrf denomL
			movlw .12
			movwf Un_H
			movlw .10
			movwf In_H
;-------------------------Инициализация перефирии---------------		
			BCF	 	    STATUS,6			
            BCF  	    STATUS,7			;выбрал банк 0 косвенная адресация
			BCF	        STATUS,5
			movlw       Init_TMR2
			movwf       T2CON^00h	;НАСТРОЙКА ТАЙМЕР 2	                           
			movlw		Init_CCP1
			movwf       CCP1CON^00h				
			BSF	        STATUS,RP0                           ; выбрал банк 1
			;movlw       Init_TMR0
			;movwf       OPTION_REG^80h	;НАСТРОЙКА ТАЙМЕР 0	
			movlw		Init_PR2
			movwf       PR2^80h
			movlw		Init_PA
			movwf		TRISA^80h
			movlw		Init_PB
			movwf		TRISB^80h	
			movlw		Init_PC
			movwf		TRISC^80h
			movlw		Init_PD
			movwf		TRISD^80h
			movlw		Init_PE
			movwf		TRISE^80h			
			call   	    Inst_LSD    
			;movlw    	.3
			;movwf   	CntT			;загрузить счетчик переполнений на 40мс
			banksel     INTCON
			bsf		    INTCON,GIE	;разрешить прерывания
			bsf		    INTCON,PEIE	;разрешить прерывания от перефирии
;----------------------------Основной цикл-----------------------
Main 		
;			btfss  Start
			btfss  Start,0
			goto   Main
			call    naminal_I	   ;устанавливаем наминальный ток аккумулятора;			
                        call	naminal_U	   ;устанавливаем наминальное напряжение аккумулятора
ust          ; 	        btfsc   Ustanovit      ; проверяем кнопку установка
		        btfsc   Ustanovit,0
			goto    ACP			   ; кнопка установка не нажата
			call    Release2	   ;кнопка установка нажата
			goto    Main
ACP			call    oprdatch  ;опрашиваем АЦП
			call    podschet  ;подсчитываем значения
			bcf		STATUS,C  ;проверяем напряжение на клеммах не меньше  ли оно 1В
			movf    Ua_H,W
			movwf	Temp_Ua
			movlw   .1
			subwf   Temp_Ua
			btfsc   STATUS,C
			call    avariy   ;если нет то авария
	;		btfsc	Start	 ;опрос кнопки старт
			btfsc	Start,0
			goto    ust      ;если не нажата проверяем кнопку установка
			call    Release3 ;если кнопка нажата то проверяем на отжатие кнопку
Nachaly	
			call    zaradca  ;начинаем заряжать и устанавливаем длительность
			call    oprdatch ;опрашиваем АЦП
			call    podschet
		        call    Indicac
	   		movf    Un_H,w
			addlw   .2 ;увеличели номинальное напряжение на 2B, проверка повышенного напряжения
			movwf   Temp_Un
			movf    Ua_H,w
			bcf     STATUS,C
			bcf     STATUS,Z
			subwf   Temp_Un ; Temp_Un-Ua_H
			btfsc   STATUS,C ; Ua_H>Un_H+2
			goto    konecc ; да
			btfsc   STATUS,Z
                        goto    konecc  ;проверка на ноль
			movf    Ia_H,w
			movwf   Temp_Ia
			movlw   .11  ; максимальный ток
			bcf     STATUS,C
			bcf     STATUS,Z
			subwf   Temp_Ia	
			btfsc   STATUS,C
			goto    avariya  ; целая часть больше			
			btfsc   STATUS,Z
                        goto    avariya  ;проверка на ноль
		;	btfsc	Stop  ;нет, тогда проверяем кнопку стоп
			btfsc	Stop,0
			goto    Nachaly ; стоп не нажат
			call    Release4 
                        konecc      call    konec
			goto    ACP
                        avariya     call    avariy
			goto    ACP
			END		