; простой термометр на 2 датчика и выходом на термостат
; контроллер - PIC16F84 (4.096 MГц), индикация - МТ10Т7, термодатчики - DS18B20
; управление: кнопка включения индикации

 	__CONFIG   _CP_OFF & _WDT_ON & _PWRTE_ON & _XT_OSC
#include p16f84.inc
#define lcd_rs		PORTB,4		;ЖКИ команда/данные (LCD 1)
#define	lcd_e		PORTB,5		;ЖКИ синхро (LCD 3)
#define	THERMO  	PORTA,0		;подключение термометра
#define THERMO2		PORTA,1		;подключение термометра 2
#define SVETODIOD	PORTA,2		;светодиод
#define U_IND		PORTA,3		;
#define POWER		PORTA,4		;наличие питания

#define	CARRY		STATUS,C
#define	ZERO 		STATUS,Z

#define KEY_MODE	flags,6		;нажата кнопка MODE
#define DS_ERR		flags,5		;наличие термометра
#define DS_ERR2		flags,4		;наличие термометра2
#define ZNAK		flags,3		;знак температуры
#define ZNAK2		flags,2		;знак температуры2
#define NUM_TERM	flags,1		;номер термометра
#define ON_IND		flags,0		;включение индикатора

INIT_OPTION	EQU	b'00000100'	;Предделитель включен перед таймером, Кдел=32
INIT_INTCON	EQU	b'10100000'	;Разрешено прерывание при переполнении таймера

	cblock 0x0c
		d0,d1,d2,d3,d4,d5,d6,d7,d8,d9 	;буфер дисплея
		w_temp				;временное хранение W
		status_temp			;---- STATUS
		count				;временные счетчики
		count2		
		seconds
		sec125
		hexdata		;HEX данные для преобразования
		decdata 	;DEC данные после преобразования
		dstemp		;прочитанное значение температуры
		dstemp2		;прочитанное значение температуры2
		sendbyte	;байт команды
		reseivebyte	;принятый байт
		newpress	;нажатая кнопка
		oldpress	;кнопка, нажатая в прошлом цикле
		flags		;байт флагов
		temp		;временный байт
		set_count	;счетчик автоповтора SET
		loop		;для организации циклов
		svetod
	endc

; MACROS
ds_comm		macro		;порт датчика на вывод
		bcf PORTA,0
		bsf STATUS,RP0
		bcf TRISA^80h,0
		bcf STATUS,RP0
		endm

ds_comm2	macro		;порт датчика2 на вывод
		bcf PORTA,1
		bsf STATUS,RP0
		bcf TRISA^80h,1
		bcf STATUS,RP0
		endm

ds_data		macro		;порт датчика на ввод
		bsf STATUS,RP0
		bsf TRISA^80h,0
		bcf STATUS,RP0
		endm

ds_data2	macro		;порт датчика2 на ввод
		bsf STATUS,RP0
		bsf TRISA^80h,1
		bcf STATUS,RP0
		endm

		org 0x000
		goto begin

;прерывание от таймера (125 Гц).
timeint		org 0x004			
		movwf w_temp		;сохранить STATUS, W
		movf STATUS,0
		movwf status_temp
		
;опрос кнопок
		movf newpress,0
		movwf oldpress
		movf PORTB,0
		andlw b'01000000'
		movwf newpress
		subwf oldpress,0
		btfsc  ZERO
		goto no_press

press_mode	clrf set_count
		btfsc newpress,6
		goto no_press
		bsf KEY_MODE
		goto time_inc
no_press	bcf KEY_MODE
		
time_inc	incf sec125
		movf status_temp,0	;восстановить STATUS, W
		movwf STATUS	
		swapf w_temp,1
		swapf w_temp,0
		bcf INTCON,2
		clrwdt	
		
		retfie		;возврат из прерывания

seg7		;преобразование в код 7-сегментов
		addwf PCL
		dt 0EEh, 060h, 02Fh, 06Dh, 0E1h; 0,1,2,3,4
		dt 0CDh, 0CFh, 068h, 0EFh, 0EDh; 5,6,7,8,9


;подпрограммы управления ЖКИ
lcd_dw		;запись данных ЖКИ	
		movwf temp
		movf temp,0	
		andlw 0x0F
		movwf PORTB
		bsf lcd_rs	
		bsf lcd_e
		bcf lcd_e
		swapf temp,0	
		andlw 0x0F
		movwf PORTB
		bsf lcd_rs	
		bsf lcd_e	
		bcf lcd_e
		return

lcd_cw		;запись команды ЖКИ	
		movwf temp
		movf temp,0	
		andlw 0x0F
		movwf PORTB
		bcf lcd_rs
		bsf lcd_e
		bcf lcd_e
		swapf temp,0	
		andlw 0x0F
		movwf PORTB
		bcf lcd_rs
		bsf lcd_e	
		bcf lcd_e
		return

begin					;инициализация PIC
		bsf STATUS,RP0
		movlw b'00010000'
		movwf TRISA^80h
		movlw b'11000000'
		movwf TRISB^80h
		movlw INIT_OPTION
		movwf OPTION_REG^80h
		bcf STATUS,RP0
		movlw INIT_INTCON
		movwf INTCON
		clrf STATUS
					;инициализация ЖКИ
		movlw 0x0F
		call lcd_cw
		movlw 1
		call lcd_dw

					;если был сброс по WDT?
		btfss STATUS,4
		goto main_loop		;исходные параметры не устанавливать

		;исходные параметры
		clrf seconds
		clrf sec125
		clrf flags
		clrf newpress
		clrf oldpress
		bsf	ON_IND

		
;главный цикл
main_loop	
;ход часов	
		movf sec125,0
		sublw .125
		btfss ZERO
		goto end_time
		incf seconds
		clrf sec125
		btfss	ON_IND
		goto	mm1

		call thermometer	;каждую секунду - измерение температуры
		call thermometer2
mm1		movf seconds,0
		sublw .20
		btfss ZERO
		goto end_time
		clrf seconds
		bcf	ON_IND
		
end_time

;обработка кнопок в экран

keymode		btfss KEY_MODE
		goto off_key
		bsf 	ON_IND

off_key		bcf KEY_MODE


;рисование экрана
		btfsc	ON_IND
		goto	screen
		clrf	d0
		clrf	d1
		clrf	d2
		clrf	d3
		clrf	d4
		clrf	d5
		clrf	d6
		clrf	d7
		clrf	d8
		clrf	d9
		goto  end_screen

screen		movlw b'01100111'	;символ "d"
		movwf d0
		btfsc DS_ERR
		goto therm_ok2
		movlw b'00000001'
		movwf d1
		movwf d2
		goto next_scr2
therm_ok2	movf dstemp,0
		call convert
		movf decdata,0
		call seg7		;преобразовать в 7-сегментный код
		movwf d1
		movf hexdata,0
		call seg7		;преобразовать в 7-сегментный код
		movwf d2
next_scr2	movlw b'10101001'	;символ "градус"
		movwf d3
		movlw b'00000000'	;символ "пробел"
		movwf d4
		movlw b'01000110'	;символ "u"
		movwf d5
		btfsc DS_ERR2
		goto therm_ok3
		movlw b'00000001'
		movwf d6
		movwf d7
		movwf d8
		goto next_scr3
therm_ok3	clrf	d6
		btfss	ZNAK2
		goto	plus3
		movlw b'00000001'
		movwf d6		
plus3		movf dstemp2,0
		call convert
		movf decdata,0
		call seg7		;преобразовать в 7-сегментный код
		movwf d7
		movf hexdata,0
		call seg7		;преобразовать в 7-сегментный код
		movwf d8
next_scr3	movlw b'10101001'	;символ "градус"
		movwf d9

end_screen
;вывод на экран
		movlw 0
		call lcd_cw
		movf d0,0
		call lcd_dw
		movf d1,0
		call lcd_dw
		movf d2,0
		call lcd_dw
		movf d3,0
		call lcd_dw
		movf d4,0
		call lcd_dw
		movf d5,0
		call lcd_dw
		movf d6,0
		call lcd_dw
		movf d7,0
		call lcd_dw
		movf d8,0
		call lcd_dw
		movf d9,0
		call lcd_dw

		goto main_loop

thermometer	call init_therm
		btfsc DS_ERR
		goto ds_enable
		movlw 0xFF	
		movwf dstemp
		goto heat_ok
		
ds_enable	movlw 0xCC	;чтение температуры
		call send
		movlw 0xBE
		call send
		call reseive
		movwf dstemp
		call reseive
		movwf temp
		call init_therm ;инициализация термометра
		movlw 0xCC	;старт преобразования
		call send
		movlw 0x44
		call send
		bcf	ZNAK
		movlw	4
		movwf	loop
		bcf	CARRY
metka		rrf	temp
		rrf	dstemp
		decfsz	loop
		goto	metka
		btfss	temp,0
		goto	kon
		bsf	ZNAK
		decf	dstemp
		comf	dstemp
kon		bcf dstemp,7
heat_ok		return	

init_therm	;инициализация термометра
		bsf 	DS_ERR	;считаем, что датчики исправны
		movlw	.20	;время ожидания ответа
		movwf	count2
		ds_comm
		bcf	THERMO	;инициализация
	  	movlw	.170	;задержка 500 мкс
		movwf	count
delinittherm	decfsz	count
		goto	delinittherm
		bsf	THERMO
		ds_data
init_ansv	btfss THERMO	;ожидание ответа
		goto end_ansv
		decfsz count2
		goto init_ansv
		bcf DS_ERR	;если нет ответа > датчик неиправен
		return
end_ansv	btfss THERMO	;ожидание освобождения шины
		goto end_ansv
		return

send		;передача команды
		movwf sendbyte	;данные для отправки
		movlw .8
		movwf count2
sendloop	ds_comm
		rrf sendbyte
		btfsc CARRY
		bsf THERMO
		call wait50
		ds_data
		decfsz count2
		goto sendloop
		return
		
reseive		;прием байта данных		
		movlw .8
		movwf count2
reseiveloop	ds_comm
		ds_data
		bcf CARRY
		btfsc THERMO
		bsf CARRY
		rrf reseivebyte 
		call wait50	
		decfsz count2
		goto reseiveloop
		movf reseivebyte,0
		return

thermometer2	call init_therm2
		btfsc DS_ERR2
		goto ds_enable2
		movlw 0xFF	
		movwf dstemp2
		goto kon2
		
ds_enable2	movlw 0xCC	;чтение температуры
		call send2
		movlw 0xBE
		call send2
		call reseive2
		movwf dstemp2
		call reseive2
		movwf temp
		call init_therm2 ;инициализация термометра
		movlw 0xCC	;старт преобразования
		call send2
		movlw 0x44
		call send2
		bcf	ZNAK2
		movlw	4
		movwf	loop
		bcf	CARRY
metka2		rrf	temp
		rrf	dstemp2
		decfsz	loop
		goto	metka2
		btfss	temp,0
		goto	kon2
		bsf	ZNAK2
		decf	dstemp2
		comf	dstemp2
kon2		bcf dstemp2,7
		return	

init_therm2	;инициализация термометра
		bsf 	DS_ERR2	;считаем, что датчики исправны
		movlw	.20	;время ожидания ответа
		movwf	count2
		ds_comm2
		bcf	THERMO2	;инициализация
	  	movlw	.170	;задержка 500 мкс
		movwf	count
delinittherm2	decfsz	count
		goto	delinittherm2
		bsf	THERMO2
		ds_data2
init_ansv2	btfss THERMO2	;ожидание ответа
		goto end_ansv2
		decfsz count2
		goto init_ansv2
		bcf DS_ERR2	;если нет ответа > датчик неиправен
		return
end_ansv2	btfss THERMO2	;ожидание освобождения шины
		goto end_ansv2
		return

send2		;передача команды
		movwf sendbyte	;данные для отправки
		movlw .8
		movwf count2
sendloop2	ds_comm2
		rrf sendbyte
		btfsc CARRY
		bsf THERMO2
		call wait50
		ds_data2
		decfsz count2
		goto sendloop2
		return
		
reseive2	;прием байта данных		
		movlw .8
		movwf count2
reseiveloop2	ds_comm2
		ds_data2
		bcf CARRY
		btfsc THERMO2
		bsf CARRY
		rrf reseivebyte 
		call wait50	
		decfsz count2
		goto reseiveloop2
		movf reseivebyte,0
		return


wait50		movlw .12	;задержка 50мкс
		movwf count
loop50		nop
		decfsz count
		goto loop50
		return

convert		;преобразование в 2х байтовый ASCII вид	
		movwf hexdata
	        movlw .8 
                movwf count 
                clrf decdata 
                goto start 

adjdec          movlw 0x33 
                addwf decdata 

                movlw 0x03 
                btfss decdata,3 
                subwf decdata 

                movlw 0x30 
                btfss decdata,7 
                subwf decdata 

start           rlf hexdata 
                rlf decdata 
                decfsz count 
                goto adjdec 
		
		movf decdata,0
		andlw 0x0f		
		movwf hexdata	;символ единиц
				
		swapf decdata,0
		andlw 0x0f
		movwf decdata	;символ десятков
		return


	end
