;***************************************************************************************;
; Heater_12F675
; Корабельников Александр, Севастополь 02.2013 "Ограничение тока электродной батареи"
; МК Pic 12F675, тактовая 4МГц внутренний
;    (1 нога)- +5V			(8 нога)- масса
; GP5(2 нога)- 			GP0(7 нога)- Вход АЦП
; GP4(3 нога)- 			GP1(6 нога)- Выход на МОС
; GP3(4 нога)- 			GP2(5 нога)- +полуволна
; История:    12.02.2013 -      Файл создан
; ***************************************************************************************

	list      p=12f675
	include <p12f675.inc>

	__CONFIG	_CP_ON & _CPD_ON & _BODEN_OFF & _MCLRE_OFF & _WDT_ON & _PWRTE_OFF & _INTRC_OSC_NOCLKOUT

		radix dec

	errorlevel 0,-302
	errorlevel 0,-202
	errorlevel 0,-203
	errorlevel 0,-205
	errorlevel 0,-206
	errorlevel 0,-207

;*******************************************************************************
;		КОНСТАНТЫ ПОЛЬЗОВАТЕЛЯ (могут меняться в зависимости от режима)
;*******************************************************************************
		TOK			EQU		.181	; Порог тока, 5В - 1024, 0.2В - 41
		TIME		EQU		.50		; Counter - Период регулировки мощности (1 - 20мс)
		P_CYCLE		EQU		.50		; Цикличность мощности 				| СУММА НЕ ДОЛЖНА
		P_STEP		EQU		.1		; Шаг регулировки уровня мощности	| ПРЕВЫШАТЬ .255
;*******************************************************************************
;		ПЕРЕМЕННЫЕ
;*******************************************************************************
				cblock		20h
		P_Err						; Счётчик периодов в цикле
		Temp						; Временный регистр
		Temp_1						; Временный регистр
		Power						; Уровень, 0 - МАКСИМУМ
		Counter						; Переодичность изменения (TIME)
		Summ_L						; Сумма младший разряд
		Summ_H						; Сумма первый старший разряд
		Summ_HH						; Сумма второй старший разряд
		Kontrol_H					; Для контроля АЦП в Протеусе (можно убрать)
		Kontrol_L					; Для контроля АЦП в Протеусе (можно убрать)
		Reg_1						; Регистры задержки
		Reg_2
					endc
;-------------------------------------------------------------------------------
				cblock		50h
		W_temp						; Регистры для сохранения контекста
		STATUS_temp
		PCLATH_temp
		FSR_temp
					endc

;*******************************************************************************
;						ВЕКТОР СБРОСА
;*******************************************************************************
					ORG			000h
					lgoto		Init

;*******************************************************************************
;						ПРЕРЫВАНИЕ
;*******************************************************************************
					ORG			004h
Interrupt:
		movwf		W_temp
		movf		STATUS, W
		movwf		STATUS_temp
		movf		PCLATH, W
		movwf		PCLATH_temp
		movf		FSR, W
		movwf		FSR_temp
		clrf		STATUS
		clrf		PCLATH
	;-------------------------------------------------------------------------
		bcf			INTCON, GIE		; Запрет всех прерываний
		btfss		INTCON, INTF	; Проверка прерывания на входе GP2/INT
		goto		End_int

		movf		GPIO, W			; Чтение портов
		bcf			GPIO, GPIO1		; 0 *** ОТКЛЮЧАЕМ ВЫХОД ***
		bcf			INTCON, INTF	; Сброс флага прерывания на входе GP2/INT

		decfsz		Counter,F		; Считаем периоды
		goto		PWR_OUT			; Не 0, суммируем показания дальше

		movlw		TIME			; Константа переодичности смены мощности
		movwf		Counter			; Переодичность изменения
		call		Chk_Tok			; Проверка тока
		clrf		P_Err			; Очистка счётчика периодов в цикле
		clrf		Summ_L			; Сумма младший разряд
		clrf		Summ_H			; Сумма первый старший разряд
		clrf		Summ_HH			; Сумма второй старший разряд
PWR_OUT
		movf		Power,W			; Вычитаем текущую мощность (количество пропусков)
		subwf		P_Err,F			; из счётчика периодов в цикле
		btfsc		STATUS,C		; С? 
		goto		PWR_ON			; С=1(+)Положительное

		movlw		P_CYCLE			; Если отрицательное
		addwf		P_Err,F			; Суммируем отрицательный остаток и новый цикл
		goto		End_int
PWR_ON
		bsf			GPIO,GPIO1		; 1 *** ВКЛЮЧАЕМ ВЫХОД ***
End_int
		call		Delay
		bsf			GPIO, GPIO5
		call		ADC				; Запускаем АЦП, суммируем
		bcf			GPIO, GPIO5

		call		Delay
		call		Delay
		bcf			GPIO,GPIO1		; 0 *** ОТКЛЮЧАЕМ ВЫХОД ***
	;-------------------------------------------------------------------------
;Int_Exit:
        movf		FSR_temp, W
        movwf		FSR
        movf		PCLATH_temp, W
        movwf		PCLATH
        movf		STATUS_temp, W
        movfw		STATUS
        swapf		W_temp, F
        swapf		W_temp, W
        retfie
;*******************************************************************************
;		ИНИЦИАЛИЗАЦИЯ
;*******************************************************************************
Init
		clrf		STATUS
		clrf		GPIO			; Инициализация защелок GPIO на выход
		movlw		B'00000111'		; Компаратор выключен
		movwf		CMCON			; Регистр компоратора
		bsf			STATUS, RP0
		movlw		B'00000101'		; Каналы GP2,GP0(5,7 нога)- входы, остальные – выходы
		movwf		TRISIO
		movlw		B'00110001'		; AD clock internal rc, выбор АЦП0 (7 нога)
		movwf		ANSEL
		movlw		B'00000000'		; Подтягивающие резисторы выключены
		movwf		WPU
		movlw		B'01001111'		; WDT 1:256, по переднему фронту,INTEDG(OPTION_REG<6>)
		movwf		OPTION_REG
		movlw		B'10010000'		; Разрешить все немаскированные прерывания, на входе GP2/INT
		movwf		INTCON
		bcf 		STATUS, RP0
		movlw		B'10000001'		; Правое выравнивание, Vdd, AN0,АЦП включен
		movwf		ADCON0

;*******************************************************************************
;		ОСНОВНОЙ ЦИКЛ
;*******************************************************************************
	; Подготовка (очистка) регистров
		clrf		P_Err			; Счётчик периодов в цикле
		clrf		Temp			; Временный регистр
		clrf		Temp_1			; Временный регистр
		clrf		Power			; Уровень 
		movlw		TIME
		movwf		Counter			; Переодичность изменения
		clrf		Summ_L			; Сумма младший разряд
		clrf		Summ_H			; Сумма первый старший разряд
		clrf		Summ_HH			; Сумма второй старший разряд
	;-------------------------------------------------------------------------
Main
	;-------------------------------------------------------------------------
		clrwdt
		bsf			INTCON,GIE		; Разрешение всех прерываний
		btfss		INTCON,INTF		; Проверка прерывания на входе GP2/INT
		goto		$-1
		goto		Main

;*******************************************************************************
;       ФУНКЦИИ
;*******************************************************************************
			; Задержка 5 мс.
;-------------------------------------------------------------------------
Delay
		movlw		.91			;|Задержка 5 мсек
		movwf		Reg_1			;|
		movlw		.7				;|
		movwf		Reg_2			;|
		decfsz		Reg_1,F			;|
		goto		$-1				;|
		decfsz		Reg_2,F			;|
		goto		$-3				;|
		return
			; Деление суммы выборок АЦП на их количество (САЗ)
;-------------------------------------------------------------------------
Chk_Tok
		clrf		Temp_1			; Делим суммы на количество замеров
		movlw		.24
		movwf		Temp
LOOPU248
		rlf			Summ_L, W		; ДЕЛЕНИЕ 3 БАЙТА НА 1 БАЙТ
		rlf			Summ_H, F
		rlf			Summ_HH, F
		rlf			Temp_1, F
		rlf			Summ_L, F
		movlw		TIME
		subwf		Temp_1, F        
		btfsc		STATUS, 0
		bsf			Summ_L, 0
		btfss		Summ_L, 0
		addwf		Temp_1, F
		decfsz		Temp, F    
		goto		LOOPU248 
	;-------------------------------------------------------------------------
		movf		Summ_H, W		; Для контроля АЦП в Протеусе
		movwf		Kontrol_H		; Блок  и регистры можно убрать
		movf		Summ_L, W		;
		movwf		Kontrol_L		;
	;-------------------------------------------------------------------------
	; Сравниваем с порогом тока и меняем количество пропусков
	;-------------------------------------------------------------------------
		movlw		HIGH(TOK)		;|Сравниваем с порогом
		movwf		Temp			;|
		movlw		LOW(TOK)		;|
		subwf		Summ_L, F		;|
		movf		Temp,W			;|
		btfss		STATUS, C		;|
		incfsz		Temp,W			;|
		subwf		Summ_H, F		;|
		btfss		STATUS, C		; < порога?
		goto		P_UP			; Меньше, УВЕЛИЧИВАЕМ МОЩНОСТЬ, уменьшая количество пропусков
		movlw		P_STEP			; |Больше.
		addwf		Power, W		; |СНИЖАЕМ МОЩНОСТЬ, увеличиваем количество пропусков, 
		movwf		Temp			; |Запоминаем его
		movlw		P_CYCLE			; |Проверяем на превышение, вычитая максимальное значение
		subwf		Temp, W			; |
		btfsc		STATUS, C		; |С?
		return						; |С=1(+) Используем текущее максимальное значение пропусков
		movf		Temp, W			; |С=0(-) Используем увеличенное количество пропусков
		movwf		Power
		return
P_UP								; ПОДНИМАЕМ МОЩНОСТЬ
		movlw		P_STEP			; >, Проверка на МИНИМУМ пропусков
		subwf		Power, W		; Уменьшаем количество пропусков
		movwf		Temp			; Запоминаем его
		btfss		STATUS, C		; Проверяем, <0?
		return						; Используем текущее
		movf		Temp, W			; Используем уменьшенное
		movwf		Power
		return
	;-------------------------------------------------------------------------
	; Замеряем напряжение с датчика тока и суммируем его за цикл.
	;-------------------------------------------------------------------------
ADC
		bsf			ADCON0, GO
		btfsc		ADCON0, GO
		goto		$-1
		bsf			STATUS, RP0
		movf		ADRESL,W
		bcf			STATUS, RP0
ADD_2b2b
    	addwf		Summ_L, F		; Сложение двух 2b регистров 
   		btfsc		STATUS, C		; Проверка переноса. 
   		incfsz		Summ_H, F		; Если перенос был, то инкремент содержимого регистра  
		goto		$+2
   		incf		Summ_HH, F
		movf		ADRESH, W
    	addwf		Summ_H, F
   		btfss		STATUS, C
		return
   		incf		Summ_HH, F
		return
;*******************************************************************************
; Конец программы Heater_12F675.asm
;*******************************************************************************
			END