/* Индикатор температуры
 * HI-TECH Software PICC-18 9.80
   MPLABX 8.88
controller PIC18F2550 напряжение питания 5.0 V
Author: Геннадий Чернов, Днепропетровск 2012
Author: Gennady Chernov, Dnepropetrovsk 2012
проект ИЛЛИССИ
 */
#include <htc.h>		// для настройки под выбранный контроллер
#include "indic_4led.h"		// управление индикацией
//----------------------------------------------------
//#pragma jis			// допускает конфигурирование не латинских символов в обработчике строк
// для обработки русских символов
//----------------------------------------------------

// конфигурирование контроллера

__CONFIG(1,
        //FOSC_HS       &   //
        FOSC_INTOSC_HS & // Internal oscillator, HS oscillator used by USB (INTHS)
        FCMEN_OFF & // Отказоустойчивый Монитор Генератора отключен
        IESO_OFF); // режим переключения генарторов отключен

__CONFIG(2,
        PWRT_ON & // таймер задержки влючения по подаче питания включен
        BOR_ON & // сброс по понижению питания влючен
        BORV_3 & // уровень сброса 3
        VREGEN_OFF & // USB voltage regulator disabled
        WDT_ON & // 
        WDTPS_32768); // предделитель сторожевого таймера

__CONFIG(3,
        CCP2MX_ON & // CCP2 подключен к PORTC1
        PBADEN_OFF & // порт PORTB скофигурирован при подаче питания как цифровой
        LPT1OSC_OFF & // Timer1 configured for higher power operation
        MCLRE_ON); // MCLR pin enabled; RE3 input pin disabled


__CONFIG(4,
        STVREN_OFF & // сброс по переполнению стека отключен
        LVP_OFF & // поддержка низковольного программирования отключена
        XINST_OFF & // поддержка расширенных команд отключена
        DEBUG_OFF); // встроенный дебагер отключен

__CONFIG(5,
        CP0_ON & // Block 0 (000800-003FFFh) защищен
        CP1_ON & // Block 1 (004000-007FFFh) защищен
        CP2_ON & // Block 2 (008000-00BFFFh) защищен
        CP3_ON & // Block 3 (00C000-00FFFFh)  защищен
        CPB_ON & // Boot block (000000-0007FFh) защищен
        CPD_ON); // Data EEPROM защищен

__CONFIG(6,
        WRT0_OFF & // Block 0 (000800-003FFFh) запись разрешена
        WRT1_OFF & // Block 1 (004000-007FFFh) запись разрешена
        WRT2_OFF & // Block 2 (008000-00BFFFh) запись разрешена
        WRT3_OFF & // Block 3 (00C000-00FFFFh) запись разрешена
        WRTC_OFF & // Регистр конфигурации - запись разрешена
        WRTB_OFF & // Блок загрузки (000000-0007FFh)- запись разрешена
        WRTD_OFF); // Запись в  EEPROM - запись разрешена

__CONFIG(7,
        EBTR0_OFF & // Block 0 (000800-003FFFh) табличное чтение - разрешено
        EBTR1_OFF & // Block 1 (004000-007FFFh) табличное чтение - разрешено
        EBTR2_OFF & // Block 2 (008000-00BFFFh) табличное чтение - разрешено
        EBTR3_OFF & // Block 3 (00C000-00FFFFh) табличное чтение - разрешено
        EBTRB_OFF); // Boot Block (000000-0007FFh) табличное чтение - разрешено
//-------------------------------------------------------------------------------------------------------
/*
#define _XTAL_FREQ 64000000 // Наша тактовая 64 Mhz
const char *s_text[] =
			{
			"ILLISSI",			// вызвать s_list[0]
			"RLC/ESR-metr",		// вызвать s_list[1]
			"       ",		// вызвать s_list[2]
			"S-4: JOLEY ",
			"S-5: Привет ",
			"S-6: ALTONA ",
			"S-7: MELBOURNE ",		// вызвать s_list[6]
			};
*/
// прототипы функций
void init (void);       // инициализация контроллера
char celsio (void); 

//------------------------------------------------------------------------------------
// определения
#define		TRISDAL	TRISA0		//	; регистр управления порта ДАЛЛАСА
#define		DALLAS	RA0			//	; шина связи с ДАЛЛАСОМ1
#define		chsto	8			// тактовая частота в мГц
#define		mksek	*chsto/4	// коэф. расчета задержек функци мкСек

// переменные 
 char	crc, nomdat, coldachu;
//флаги
volatile static bit CONV; // бит используется в прерываниях

static bit CON,POISKR, NAP; // биты режима конвертирования температуры
int tempertura;
volatile char convert;
//------------------------------------------------------------------------------------

 char	a;


void main(void) {
    CLRWDT();   // сброс сторожевого таймера +++++++++++++++++++++-
    init();   	// 

		

		
    while (1)
    {
        CLRWDT(); // сброс сторожевого таймера +++++++++++++++++++++-

		celsio();
 		bin_dec (tempertura,0,1);
		loading(sotn, dest, edin, 0, 0);


	for ( a = 0; a < 3; a++ )
	{
	_delay(190000);
	}     


    }
   
}//


//----------------------------------------------------------------------
void init(void)// описание функции инициализации контроллера
{
    // конфигурирование аналоговых выводов
	ADCON1 = 0b00001111; // ВСЕ порты цифровые
	CMCON = 0b00000111; // компараторы отключены
	
	UTRDIS=1;
	USBEN=0;
	
	
    // настройка порта А
   // PORTA = 0; // 
    LATA = 0; // или можно PORTA=0;
    TRISA = 0b00000001; // настройка порта: все выводы на выход

    // настройка порта В
    LATB = 0; 			// или можно PORTB=0;
    TRISB = 0b00000000; // настройка порта: 1=input, 0=output RBO=вход, остальные выход

    // настройка порта С
    LATC = 0; 			//
    TRISC = 0b00000000; // RC0-вход для таймера
	


        
    //настройка генератора
    OSCTUNE = 0b00000000; //Oscillator module is running at the factory calibrated frequency.
    OSCCON = 0b01110010; 

    
    //Настройка таймера T0CON: формирования временных интервалов
    // частота разверки 80 герц
    T0CON=0b11000100;
    //		|||||+++---- T0PS<2:0>:111 = 1:32 prescale value
    //		||||+------- PSA:0 = Timer0 prescaler is assigned.
	//		|||+-------- T0SE:
	//		||+--------- T0CS:0 = Internal instruction cycle clock (CLKOUT)
	//		|+---------- T08BIT:0 = Timer0 is configured as a 16-bit timer/counter
	//		+----------- TMR0ON:1 = Enables Timer0
	
	//Настройка прерываний
	INTCON=0b10100000;
    //		 |||||||+---- RBIF:
    //		 ||||||+----- INT0IF:
    //		 |||||+------ TMR0IF:
    //		 ||||+------- RBIE:
	//		 |||+-------- INT0IE:
	//		 ||+--------- TMR0IE:Enables the TMR0 overflow interrupt
	//		 |+---------- PEIE/GIEL: разрешить прерывание от переферии
	//		 +----------- GIE/GIEH:Enables all unmasked interrupts

}//----------------------------------------------------------------------


//=====================================прерывания==================================
void interrupt my_isr(void) 	//
{
	


	
	if (TMR0IF)
	{
		TMR0IF=0;	// сбросить флаг прерывания от таймера TMR0
		//период 	80(240) Hz	start
		indic();		// индикация
		
		if(CONV==1)
		{
			if(convert--==0)
			{
				convert=200;
				CONV=0;
			}
		}	
	}
	
		
//----------------------------------------------------------------------------			

}//===================================end_interrupt=================================





// описание функций работы с DS18B20
//
//============================================================================================
//;DOUT_HIGH: формирование высокого уроня - режим стение данных от DS18B20
// mksek = 8 мГц = 8000 / 7 = 1142
void DOUT_HIGH (void)
	{
		DALLAS=1;				// задежка для длинных линий для  формирования импульса восстановления 
		_delay((7-3)mksek);		// 7
		TRISDAL=1;				// режим чтения
	} 
//
//============================================================================================
// DOUT_LOW: Эта подпрограмма устанавливает линию ДАЛЛАССа  на  вывод и устанавливает на ней "0"
// 8 мГц = 8000 / 4 = 1142
void DOUT_LOW (void)
		{
		DALLAS=0;				//установить низкий уровень на шине			
		TRISDAL=0;				// режим выводв данных
		_delay((5-2)mksek);			// 4
 	}
//
//============================================================================================
// DLIT_WR: Эта подпрограмма используется в ходе работы подпрограмм связи.20 - 60mks
// задержка 60 mks, в которая необходима DS1820 для чтения или записи бита данных.
void DLIT_WR (void)
	{									;
		_delay((54-2)mksek);		// 54 необходима ялительность функции
  	}							// - 4 корретор
//
//============================================================================================
char crc_bits(int data) // crc8 для DS18B20
{
  int i = (data ^ crc) & 0xff;
  crc = 0;
	  if(i & 0b00000001)crc ^= 0x5e;
	  if(i & 0b00000010)crc ^= 0xbc;
	  if(i & 0b00000100)crc ^= 0x61;
	  if(i & 0b00001000)crc ^= 0xc2;
	  if(i & 0b00010000)crc ^= 0x9d;
	  if(i & 0b00100000)crc ^= 0x23;
	  if(i & 0b01000000)crc ^= 0x46;
	  if(i & 0b10000000)crc ^= 0x8c;
  return crc;
}
//
//============================================================================================
//
char RESET_DALLAS (void) 	//	; формирование импульса сброса и тестирование присутствия датчика
// возвращает 	0 - связь с датчиком установлена
//				1 - нет связи постоянно высокий уровень (обрыв)
//				2 - нет связи постоянно низкий уровень  (короткое)
		{
char ERR_LINE; // линния исправна связи датчика иcправна
unsigned int a;
			DOUT_LOW();				//сформировать импульс сброса 480-960 mks
			_delay(548mksek);		//задержка 550 mks
			DOUT_HIGH();			//установить высокий уровень
			_delay(60mksek);		//задержка 60 mks
// контроль импульса присутсвия
			ERR_LINE=0;// инициализация бита ошибки -  линния исправна связи датчика иcправна
		// проверка призода фронта или уровня импульса присутствия
			a=0;
			while (ERR_LINE==0&&(DALLAS==1))
			{
				a++;
				CLRWDT(); 
				if(a==65535)ERR_LINE=1; // нет ответа
			}	 
		// проверка прихода фронта или уровня импульса присутствия	
			a=0;
			while (ERR_LINE==0&&(DALLAS==0))
			{
				a++;
				CLRWDT();
				if(a==65535)ERR_LINE=2; // линия закорочена
			}	 
		_delay(430mksek);		//задержка 550 mks
		return ERR_LINE;
	}
//
//============================================================================================
// DRECEIVE: Эта подпрограмма читает данные из DS18B20
char DRECEIVE (void)
	{
	char COM_REG,a;	
	di();											// запретить прерывания
			COM_REG=0;
			for (a=0; a<8; a++)						// цикл чтение от даласса шины
			{
			DOUT_LOW ();							// старт чтения бита установить низкий уровень)
			DOUT_HIGH ();							// начать чтение
			COM_REG=COM_REG>>1;						// сдвиг + запись в 7 разряд 0
			if (DALLAS==1)COM_REG |= 0b10000000; 	// установка в 7 разряде 1 если DALLAS==1
			DLIT_WR();								//ожидать для окончания формирование далласом бита
  			}
	ei();	// функция включить прерывания
	return COM_REG;
	}
//
//============================================================================================
//; DSEND: Эта подпрограмма посылает команды к DS1820. Данные
//; посылается младшим битом сначала без четности, останова, или битов начала
void DSEND (char COM_REG) 
	{
	char a;
	di();											// запретить прерывания
			for (a=0; a<8; a++)	
				{
				DOUT_LOW ();		
	  			if(COM_REG & 0b00000001) DOUT_HIGH ();
				COM_REG=COM_REG>>1;	
	  			DLIT_WR ();
		  		DOUT_HIGH ();
				}
	ei();	// функция включить прерывания
	}
//
//=================================================================


//
char celsio (void)
{
// модуль проверки и запуска режима конвертирования температуры
// всеми датчиками
volatile char a; // внутреняя переменная цикла

volatile const char con_dro[] = { 0, 1, 1, 2, 3, 3, 4, 4, 5, 6, 6, 7, 8, 8, 9, 9, 00}; 
 // значение от дисретизации     00.06.13.19.25.31.38.44.50.56.63.69.75.81.88.94.100
static bit MINUS;	

// ошибки
//  1; // запущено конвертирование
//  2; // идет конвертирование
//  3; // нет датчика или короткое на шину питания датчика
//  4; // на линии низкий уровень
//  5; // нет ответа от ДТ в режиме чтения
//  0 - нет ошибок
		if(CON==1)
		{
 			if(CONV==0)	CON=0;
	 		else return 2; // идет конвертирование
		}
		else
		{
			a=RESET_DALLAS();
			if (a==0)// формирование импульса сброса
			{
				DSEND (0xCC);// команда для всех устройств
				DSEND (0x44);// конверитирование температуры
				CONV=1;
				CON=1;
			 	return 1; // запущено конвертирование
			}
			else
			{
			if (a==1) return 3; // нет датчика, замыкание на шине высокий уровень)
				else  return 4; // замыкание на чине (низкий уровень)
			}
		}
		
		if (RESET_DALLAS()==0)// формирование импульса сброса с провекой импульса присутствия датчиков
		{
			DSEND (0xCC);// команда для всех устройств
		}
		else
		{
			return 5; // нет ответа от ДТ в режиме чтения
		}						

//	чтение температуры и проверка crc
		DSEND(0xBE); 			//команда чтения памяти
		crc=0; 					// обнулить байт контрольной суммы			
		tempertura=DRECEIVE(); 	// читаем байт 01
		crc_bits(tempertura);
		a=DRECEIVE(); 			// читаем байт 02
		tempertura+=a<<8;		
		crc_bits(a);
		crc_bits(DRECEIVE()); 	// читаем байт 03
		crc_bits(DRECEIVE()); 	// читаем байт 04
		crc_bits(DRECEIVE()); 	// читаем байт 05
		crc_bits(DRECEIVE()); 	// читаем байт 06
		crc_bits(DRECEIVE()); 	// читаем байт 07
		crc_bits(DRECEIVE()); 	// читаем байт 08
		crc_bits(DRECEIVE()); 	// читаем байт 09
			
		if (crc==0) 
		{
			// преобразование кода температуры датчика в двоичное чиcло
				MINUS=0;
			if (tempertura & 0x8000)
			{
				tempertura=~tempertura; // если отрицательна
				tempertura++;	// находим значение по модулю			
				MINUS=1;
			}	
				a=tempertura;		// преобразование долей градуса
				a &= 0b00001111;	// в десятичное значение
				a=con_dro[a];		//
				
				tempertura>>=4;		// формирование значение температуры
				tempertura=(tempertura&0x00ff)*10; // например22,5 как
				tempertura=tempertura+a;		   // 225
			
			if (MINUS==1)
			{
				tempertura=~tempertura; // если отрицательна
				tempertura++;	// находим значение по модулю
			}			
		
			return 0;
		}
		return 6; // ошибка crc	
}
//								
