//............................................................................................................. // 2 канальный цифровой термометр // на PIC16F628 и DS18S20 // Freq = 4МГц. // Разработал vnnik71 (http://www.vnnik71.narod.ru) //............................................................................................................. #include 62 0x02, 0x01, 0x51, 0x09, 0x06, // ? 63 0x32, 0x49, 0x79, 0x41, 0x3E, // @ 64 0x7E, 0x11, 0x11, 0x11, 0x7E, // A 65 0x7F, 0x49, 0x49, 0x49, 0x36, // B 66 0x3E, 0x41, 0x41, 0x41, 0x22, // C 67 0x7F, 0x41, 0x41, 0x22, 0x1C, // D 68 0x7F, 0x49, 0x49, 0x49, 0x41, // E 69 0x7F, 0x09, 0x09, 0x01, 0x01, // F 70 0x3E, 0x41, 0x41, 0x51, 0x32, // G 71 0x7F, 0x08, 0x08, 0x08, 0x7F, // H 72 0x00, 0x41, 0x7F, 0x41, 0x00, // I 73 0x20, 0x40, 0x41, 0x3F, 0x01, // J 74 0x7F, 0x08, 0x14, 0x22, 0x41, // K 75 0x7F, 0x40, 0x40, 0x40, 0x40, // L 76 0x7F, 0x02, 0x04, 0x02, 0x7F, // M 77 0x7F, 0x04, 0x08, 0x10, 0x7F, // N 78 0x3E, 0x41, 0x41, 0x41, 0x3E, // O 79 0x7F, 0x09, 0x09, 0x09, 0x06, // P 80 0x3E, 0x41, 0x51, 0x21, 0x5E, // Q 81 0x7F, 0x09, 0x19, 0x29, 0x46, // R 82 0x46, 0x49, 0x49, 0x49, 0x31, // S 83 0x01, 0x01, 0x7F, 0x01, 0x01, // T 84 0x3F, 0x40, 0x40, 0x40, 0x3F, // U 85 0x1F, 0x20, 0x40, 0x20, 0x1F, // V 86 0x7F, 0x20, 0x18, 0x20, 0x7F, // W 87 0x63, 0x14, 0x08, 0x14, 0x63, // X 88 0x03, 0x04, 0x78, 0x04, 0x03, // Y 89 0x61, 0x51, 0x49, 0x45, 0x43, // Z 90 0x7E, 0x11, 0x11, 0x11, 0x7E, // A 192 0x7F, 0x45, 0x45, 0x45, 0x39, // Б 193 0x7F, 0x49, 0x49, 0x49, 0x36, // B 194 0x7F, 0x01, 0x01, 0x01, 0x03, // Г 195 0xC0, 0x7E, 0x41, 0x7F, 0xC0, // Д 196 0x7F, 0x49, 0x49, 0x49, 0x41, // E 197 119,8,127,8,119, // Ж 198 34,73,73,73,54, // З 199 127,32,16,8,127, // И 200 127,32,19,8,127, // Й 201 0x7F, 0x08, 0x14, 0x22, 0x41, // K 202 64,62,1,1,127, // Л 203 0x7F, 0x02, 0x04, 0x02, 0x7F, // M 204 0x7F, 0x08, 0x08, 0x08, 0x7F, // H 205 0x3E, 0x41, 0x41, 0x41, 0x3E, // O 206 127,1,1,1,127, // П 207 0x7F, 0x09, 0x09, 0x09, 0x06, // P 208 0x3E, 0x41, 0x41, 0x41, 0x22, // C 209 0x01, 0x01, 0x7F, 0x01, 0x01, // T 210 39,72,72,72,63, // У 211 30,33,127,33,30, // Ф 212 0x63, 0x14, 0x08, 0x14, 0x63, // X 213 127,64,64,127,192, // Ц 214 15,16,16,16,127, // Ч 215 127,64,124,64,127, // Ш 216 127,64,124,64,255, // Щ 217 1,127,72,72,48, // Ъ 218 127,72,48,0,127, // Ы 219 127,72,72,72,48, // Ь 220 34,73,73,73,62, // Э 221 127,8,62,65,62, // Ю 222 118,9,9,9,127, // Я 223 0x20, 0x54, 0x54, 0x54, 0x78, // a 224 124, 84, 84, 84, 36, // б 225 124, 84, 84, 84, 40, // в 226 124, 4, 4, 4, 12, // г 227 192, 120, 68, 124, 192, // д 228 0x38, 0x54, 0x54, 0x54, 0x18, // e 229 108, 16, 124, 16, 108, // ж 230 40, 68, 84, 84, 40, // з 231 124, 32, 16, 8, 124, // и 232 124, 33, 18, 8, 124, // й 233 124, 16, 16, 40, 68, // к 234 64, 56, 4, 4, 124, // л 235 124, 8, 16, 8, 124, // м 236 124, 16, 16, 16, 124, // н 237 0x38, 0x44, 0x44, 0x44, 0x38, // o 238 124, 4, 4, 4, 124, // п 239 0x7C, 0x14, 0x14, 0x14, 0x08, // p 240 0x38, 0x44, 0x44, 0x44, 0x20, // c 241 4, 4, 124, 4, 4, // т 242 0x0C, 0x50, 0x50, 0x50, 0x3C, // y 243 24, 36, 124, 36, 24, // ф 244 0x44, 0x28, 0x10, 0x28, 0x44, // x 245 124, 64, 64, 124, 192, // ц 246 12, 16, 16, 16, 124, // ч 247 124, 64, 120, 64, 124, // ш 248 124, 64, 120, 64, 252, // щ 249 124, 84, 80, 80, 32, // ъ 250 124,80,32,0,124, // ы 251 124, 80, 80, 80, 32, // ь 252 40, 68, 84, 84, 56, //э 253 124, 16, 56, 68, 56, // ю 254 72, 52, 20, 20, 124 // я 255 }; //................................................................................................................. // Код программы //................................................................................................................. void main (void) { CLRWDT(); init(); initlcd(); while (1) { cursorxy(0,0); putstr("* Термометр! *-------------- Дом Улица "); cursorxy(0,4); putstr("--------------Разраб. VNNIK"); //.................................. Работа с датчиками температуры .............................................................. di(); D_Reset(); // Сброс датчика температуры ei(); //Опрос первого датчика ............................................................................................................ if(D_Error!=1){ // Если флаг замыкания цепи датчика не установлен, то "двигаемся дальше" if(D_Error!=2){ // Если флаг обрыва линии не установлен, то "двигаемся дальше" //................................................................................................................................ di(); D_Write(0xCC); // Пропуск кода устройства ei(); if(convert_t==0){ // Флаг процесса измерения температуры датчиков ведется? di(); // Нет: тогда, D_Write(0x44); // Пошлем команду на запуск процесса измерения температуры в датчике ei(); convert_t=1; // Установим флаг, того что процесс измерения ведется time_read=0; // Сбросим таймер измерения температуры r_time=0; // Сбросим флаг окончания измерения } //.................................................................................................................................. if(convert_t){ // Если преобразование в процессе и флаг окончания // преобразования установлен и вывод DQ в высоком состоянии, то: if((r_time)&(D_PIN)) { di(); D_Write(0xBE); // Послать в датчик команду чтения значения температуры ei(); c_read=1; // Установить флаг готовности чтения данных из датчика } } delay_100ms(); //.................................................................................................................. if(c_read==1){ // Данные датчика готовы для считывания? di(); t_data1=D_Read(); // Да: читаем данные из датчика t_data2=D_Read(); ei(); data_displ(t_data1,t_data2); // Преобразование данных для отображения r_time=0; // Сбросить флаг окончания времени измерения температуры convert_t=0; // Сбросить флаг процесса измерения температуры c_read=0; // Сбросим флаг готовности данных измерений cursorxy(0,3); putstr(ind_data1); putstr(ind_data2); putstr(ind_data3); if((dst==0)&(bsd==0)&(msd==0)&(lsd==0)) { putstr(" ");} else {putstr(",");} putstr(ind_data4); putstr("#C"); } } else { // Выводим на дисплей сообщение "Замыкание в цепи датчика" cursorxy(0,3); // Next line. putstr(" --- "); cursorxy(0,3); // Next line. putstr(" Обрыв "); } } else{ // Выводим на дисплей надпись "Обрыв в цепи датчика" cursorxy(0,3); // Next line. putstr(" --- "); cursorxy(0,3); // Next line. putstr(" К.З. "); } // Опрос второго датчика.................................................................................................. if(D_Error1!=1){ // Если флаг замыкания цепи датчика не установлен, то "двигаемся дальше" if(D_Error1!=2){ // Если флаг обрыва линии не установлен, то "двигаемся дальше" //................................................................................................................................ di(); D_Write1(0xCC); // Пропуск кода устройства ei(); if(convert_t1==0){ // Флаг процесса измерения температуры датчиков ведется? di(); // Нет: тогда, D_Write1(0x44); // Пошлем команду на запуск процесса измерения температуры в датчике ei(); convert_t1=1; // Установим флаг, того что процесс измерения ведется time_read1=0; // Сбросим таймер измерения температуры r_time1=0; // Сбросим флаг окончания измерения } //.................................................................................................................................. if(convert_t1){ // Если преобразование в процессе и флаг окончания // преобразования установлен и вывод DQ в высоком состоянии, то: if((r_time1)&(D_PIN1)) { di(); D_Write1(0xBE); // Послать в датчик команду чтения значения температуры ei(); c_read1=1; // Установить флаг готовности чтения данных из датчика } } delay_100ms(); //.................................................................................................................. if(c_read1==1){ // Данные датчика готовы для считывания? di(); t_data11=D_Read1(); // Да: читаем данные из датчика t_data21=D_Read1(); ei(); data_displ(t_data11,t_data21); // Преобразование данных для отображения r_time1=0; // Сбросить флаг окончания времени измерения температуры convert_t1=0; // Сбросить флаг процесса измерения температуры c_read1=0; // Сбросим флаг готовности данных измерений //................................................................................................................................ // Здесь осуществить вывод на дисплей информации. cursorxy(42,3); putstr(ind_data1); putstr(ind_data2); putstr(ind_data3); if((dst==0)&(bsd==0)&(msd==0)&(lsd==0)) { putstr(" ");} else {putstr(",");} putstr(ind_data4); putstr("#C"); } } else { // Выводим на дисплей сообщение "Замыкание в цепи датчика" cursorxy(42,3); // Next line. putstr(" --- "); cursorxy(42,3); // Next line. putstr(" Обрыв "); } } else{ // Выводим на дисплей надпись "Обрыв в цепи датчика" cursorxy(42,3); // Next line. putstr(" --- "); cursorxy(42,3); // Next line. putstr(" К.З. "); } } } //......................................................................................... // Инициализация //......................................................................................... void init(void) { // Инициализация портов контроллера // Все входы цифровые CMCON=0x07; PORTA=PORTB=0b00000000; // CSK=SDIN=RST=D_C=DQ=0 TRISA=0b11111111; TRISB=0b11000100; // DQ2 (RB2) - вход // CSK (RB4) - выход // SDIN(RB0) - выход // RST (RB3) - выход // D_C (RB5) - выход // CS (RB1) - выход // Сброс и запрет всех прерываний кроме TMR0 INTCON= 0b00100000; PIE1=PIR1 = 0b00000000; // Инициализация таймера 0 OPTION =0b00000111; // Предделитель = 256 TMR0=240; // Прерывания таймера будет через 4мс. GIE=1; // //Инициализация переменных convert_t=r_time=c_read=0; convert_t1=r_time1=c_read1=0; } //**************************************************************************************** // Функции работы с LCD Nokia3310 //**************************************************************************************** // Инициализация lCD //........................................................................................ void initlcd(void) { CLRWDT(); RST = 1; // Сброс индикатора не активен CS = 1; // Индикатор не выбран NOP(); RST = 0; // Сформировать сигнал сброса индикатора delay_100ms(); // Ожидаем 100 мс RST = 1; // Снятие сигнала сброса writecom(0x21); // Выбор расширенного набора команд H=1 writecom(0xC2); // Установка напряжения LCD (контрасности) около 7В writecom(0x13); // LCD bias mode 1:48 writecom(0x20); // Использовать основные команды Н=0 writecom(0x09); // Активация всех пикселов clearram(); // Очистка всех пикселов в DDRAM. writecom(0x08); // Очистка дисплея writecom(0x0C); // Display Normal. cursorxy(0,0); // Cursor Home. } //....................................................................................... // Функция записи команд //....................................................................................... void writecom(char command_in) { D_C = 0; // Выбор регистра команд CS = 0; // Выбор чипа clockdata(command_in); // Запись битов команды CS = 1; // Снятие выбора чипа } //....................................................................................... // Функция записи символа //....................................................................................... void writedata(char data_in) { D_C = 1; // Выбор регистра данных CS = 0; // Выбор чипа clockdata(data_in); // Запись битов данных CS = 1; // Снятие выбора чипа } //...................................................................................... // Тактирование данных //...................................................................................... void clockdata(char bits_in) { int bitcnt; CLRWDT(); for (bitcnt=8; bitcnt>0; bitcnt--) { SCK = 0; if ((bits_in&0x80)==0x80) {SDI=1;} // PCD8544 тактируется старшим битом вперед (MSb) else {SDI=0;} SCK = 1; // Данные тактируются передним фронтом SCK bits_in=bits_in<<1; // Логический сдвиг данных на 1 бит влево } } //...................................................................................... // Очистка всех символов в DDRAM //...................................................................................... void clearram(void) { int ddram; cursorxy(0,0); // Курсор в начальную позицию for (ddram=504;ddram>0;ddram--) { CLRWDT(); writedata(0x00); } // 6*84 = 504 DDRAM адресов } //..................................................................................... // Установка курсора в определенную позицию //..................................................................................... void cursorxy(char x, char y){ writecom(0x40|(y&0x07)); // Y ось writecom(0x80|(x&0x7f));} // X ось //..................................................................................... // Запись символа //..................................................................................... void putchar(char character) { int tablept, count, char_column; if ((character>31)&(character<126)) { tablept = ((5*character) - 160);} else { if ((character>191)&(character<255)) { tablept = ((5*character) - 665);} else { if (character==255){ tablept = ((5*character) - 960);} else {return;} } } for (count=5;count>0;count--) // Изьятие из колонки таблицы для печати символа { char_column = table[tablept]; writedata(char_column); tablept++; } writedata(0x00); // 1 пиксел пробела на символ } //..................................................................................... // Запись строки символов //..................................................................................... void putstr(const char *s) { while(*s) { putchar(*s++); CLRWDT(); } // Точки одного ASCII могут быть записаны за один раз } //*************************************************************************************** // Функция вызова прерывания //*************************************************************************************** // Прерывания //....................................................................................... void interrupt time (void) { if((T0IE==1) && (T0IF == 1)) { T0IF=0; // Сброс флага прерывания TMR0=240; // Прерывания через 4мс. time_delay++; if(convert_t==1) // Если измерение запущено, то { time_read++; // Ститаем время измерения if(time_read==0){r_time=1;} } if(convert_t1==1) // Если измерение запущено, то { time_read1++; // Считаем время измерения if(time_read1==0){r_time1=1;} } } } //...................................................................................... // Преобразование данных с датчика в данные индикатора //...................................................................................... void data_displ(unsigned char displ_d1,unsigned char displ_d2) { static bit znak; temper=displ_d2; temper<<=8; temper|=displ_d1; if(temper<0) { znak=1; temper=~temper+1; } else {znak=0; } displ_d=temper*5; msd=bsd=dst=0; lsd=displ_d; while (lsd>=10) { if((lsd-10)>=0) { msd++; lsd-=10; } if((msd-10)>=0) { bsd++; msd-=10; } if((bsd-10)>=0) { dst++; bsd-=10; } } ind_data4=bcd_lcd(lsd); ind_data3=bcd_lcd(msd); ind_data2=bcd_lcd(bsd); ind_data1=bcd_lcd(dst); if (znak) {ind_data1="-";} if(dst==0){if (bsd==0) { if(msd==0) { if (lsd==0){ind_data1=ind_data2=ind_data3=" "; ind_data4="0";} else { if(znak) {ind_data2="-";} else {ind_data2=" ";} ind_data1=" "; ind_data3="0"; } } else { if(znak) {ind_data2="-";} else {ind_data2=" ";} ind_data1=" "; } } else { if(znak) {ind_data1="-";} else {ind_data1=" ";} } } } //................................................................................................ // Фунции интерфейса цифрового датчика bit D_Presence; // Сигнал присутствия на линии bit D_ShortCircuit; // Сигнал короткого замыкания на линии bit D_Data; // Данные bit D_Presence1; // Сигнал присутствия на линии bit D_ShortCircuit1; // Сигнал короткого замыкания на линии bit D_Data1; // Данные //D_Reset -- Сброс 1-wire шины и проверка сигнала присутствия на шине и короткого замыкания void D_Reset(void) { CLRWDT(); D_Error=D_Error1=0; // Проверка правильности установки порта D_TRIS= D_TRIS1=1; D_PIN=D_PIN1=0; // Старт сигнала Сброса D_TRIS=D_TRIS1=0; // Формирование низкого уровня для Старта сигнала Сброса delay_480(); // 480uS задержка D_TRIS=D_TRIS1=1; // Освобождение линии delay_60(); // Задержка к середине импульса присутствия D_Presence=D_PIN; // Установка состояния присутствия: 1=нет, 0=Что-то есть D_Presence1=D_PIN1; delay_420(); // (480-60)uS задерка до конца D_ShortCircuit=D_PIN; // Проверка короткого замыкания на линии. D_ShortCircuit1=D_PIN1; if(D_ShortCircuit==0) // если короткое замыкание тогда индикация ошибки { D_Error=1; } if(D_ShortCircuit1==0) // если короткое замыкание тогда индикация ошибки { D_Error1=1; } if(D_Presence==1) // Если устройство на линии не обнаружено тогда индикация ошибки { D_Error+=2; } if(D_Presence1==1) // Если устройство на линии не обнаружено тогда индикация ошибки { D_Error1+=2; } delay_10(); // Задержка на время фронта импульса } // D_Write -Передача данных в линию void D_Write(unsigned char Data) // Передача данных { char count=8; for(;count>0;count--) { D_Data= Data & 0x01; // Передача LSB D_PIN=0; // Передача бита в порт D_TRIS=0; // Низкий уровень на порту NOP(); // длительность старта времени передачи сигнала NOP(); NOP(); NOP(); D_TRIS=D_Data; // Выдача данных в порт delay_60(); // Окончание времени передачи сигнала D_TRIS=1; // Проверка освобождения вывода порта // Задержка между битами delay_10(); ; // Время востановления между выводами // Передача следующего бита Data=Data>>1; // Сдвиг следующего бита на место } delay_10(); // Задержка на время фронтов } void D_Write1(unsigned char Data1) // Передача данных { char count=8; for(;count>0;count--) { D_Data1= Data1 & 0x01; // Передача LSB D_PIN1=0; // Передача бита в порт D_TRIS1=0; // Низкий уровень на порту NOP(); // длительность старта времени передачи сигнала NOP(); NOP(); NOP(); // Выдача данных в порт D_TRIS1=D_Data1; delay_60(); // Окончание времени передачи сигнала D_TRIS1=1; // Проверка освобождения вывода порта // Задержка между битами delay_10(); ; // Время востановления между выводами // Передача следующего бита // Сдвиг следующего бита на место Data1=Data1>>1; } delay_10(); // Задержка на время фронтов } // D_Read - Чтение(прием) данных с линии char D_Read(void) { char count=8,data=0; for(;count>0;count--) { CLRWDT(); // Запись бита начала времени приема в порт D_PIN=0; D_TRIS=0; // Низкий уровень на выводе порта NOP(); // длительность старта времени передачи сигнала NOP(); NOP(); D_TRIS=1; // освобождение порта для чтения delay_10(); // ожидание середины периода общения D_Data=D_PIN; // Чтение бита данных с линии delay_60(); // Окончание периода общения // Положить данные в байт data = data >> 1; // сдвиг предыдущего бита if(D_Data==1) // если данные являются высоким уровнем тогда добавить еденицу в байт данных { data +=0x80; } // Задержка между битами delay_10(); // задержка на время востановления между битами } delay_10(); // Задержка на время фронтов return(data); } // D_Read - Чтение(прием) данных с линии char D_Read1(void) { char count=8,data1=0; for(;count>0;count--) { CLRWDT(); // Запись бита начала времени приема в порт D_PIN1=0; D_TRIS1=0; // Низкий уровень на выводе порта NOP(); // длительность старта времени передачи сигнала NOP(); NOP(); D_TRIS1=1; // освобождение порта для чтения delay_10(); // ожидание середины периода общения D_Data1=D_PIN1; // Чтение бита данных с линии delay_60(); // Окончание периода общения // Положить данные в байт data1 = data1 >> 1; // сдвиг предыдущего бита if(D_Data1==1) // если данные являются высоким уровнем тогда добавить еденицу в байт данных { data1 +=0x80; } // Задержка между битами delay_10(); // задержка на время востановления между битами } delay_10(); // Задержка на время фронтов return(data1); } //................................................................................. // Програмные задержки void delay_10(void) { char i=2; while (--i!=0){} } void delay_60(void) {char i=18; while (--i!=0){} } void delay_420(void) {char i=138; while (--i!=0){} } void delay_480(void) {char i=158; while (--i!=0){} } //....................................................................... // Задержка 100мс //....................................................................... void delay_100ms(void) { unsigned char i,k; i=time_delay; i=i+25; metka1: k=i-time_delay; if(k!=0){ CLRWDT(); goto metka1; } } //............................................................................ int bcd_lcd(char d_lcd) { switch(d_lcd) { case 0: return "0"; case 1: return "1"; case 2: return "2"; case 3: return "3"; case 4: return "4"; case 5: return "5"; case 6: return "6"; case 7: return "7"; case 8: return "8"; case 9: return "9"; } }