В данной статье пойдет речь о том, как подключить датчик температуры DS18B20 к ATmega8 и отображать данные на ЖКИ-дисплее 16×1 на базе HD44780. Будут приведены три примеры программ работы с датчиком температуры, а именно: самый простой — подключение одного DS18B20 к ATmega8; подключение нескольких DS18B20 к ATmega8 на разные выводы микроконтроллера; самый сложный — подключение нескольких датчиков температуры DS18B20 к ATmega8 на одну шину. Для проверки работоспособности программ и схем был использован эмулятор Proteus 7 (ISIS 7 Professional). Код программ (проекты в Atmel Studio 7 целиком) вы сможете скачать по ссылке в конце статьи. После оптимизации кода вместо ATmega8 можно использовать более простой микроконтроллер ATtiny2313.
OneWire библиотека
config.h
#ifndef CONFIG_H_ #define CONFIG_H_ #define F_CPU 8000000UL #define ONE_WIRE_PORT PORTB #define ONE_WIRE_DDR DDRB #define ONE_WIRE_PIN PINB #endif /* CONFIG_H_ */
OneWire.h
#ifndef ONEWIRE_H_ #define ONEWIRE_H_ #define CMD_CONVERTTEMP 0x44 #define CMD_RSCRATCHPAD 0xbe #define CMD_WSCRATCHPAD 0x4e #define CMD_CPYSCRATCHPAD 0x48 #define CMD_RECEEPROM 0xb8 #define CMD_RPWRSUPPLY 0xb4 #define CMD_SEARCHROM 0xf0 #define CMD_READROM 0x33 #define CMD_MATCHROM 0x55 #define CMD_SKIPROM 0xcc #define CMD_ALARMSEARCH 0xec void oneWireInit(uint8_t); void writeBit(uint8_t); void writeByte(uint8_t); void setDevice(uint64_t); void searchRom(uint64_t*, uint8_t&); void skipRom(void); uint8_t readByte(void); uint8_t readBit(void); uint8_t reset(void); uint8_t crcCheck(uint64_t, uint8_t); uint64_t readRoom(void); uint64_t searchNextAddress(uint64_t, uint8_t&); extern uint8_t ONE_WIRE_DQ; #endif /* ONEWIRE_H_ */
OneWire.cpp
#define DEVICES_ERROR 1 #include "config.h" #include <avr/io.h> #include <avr/interrupt.h> #include <util/delay.h> #include "OneWire.h" uint8_t ONE_WIRE_DQ = PINB0; void oneWireInit(uint8_t pin) { ONE_WIRE_DQ = pin; ONE_WIRE_PORT |= (1 << ONE_WIRE_DQ); ONE_WIRE_DDR |= (1 << ONE_WIRE_DQ); // выход } /* * сброс */ uint8_t reset() { uint8_t response; // импульс сброса, минимум 480us ONE_WIRE_PORT &= ~(1 << ONE_WIRE_DQ); ONE_WIRE_DDR |= (1 << ONE_WIRE_DQ); // выход _delay_us(480); // Когда ONE WIRE устройство обнаруживает положительный перепад, он ждет от 15us до 60us ONE_WIRE_DDR &= ~(1 << ONE_WIRE_DQ); // вход _delay_us(60); // и затем передает импульс присутствия, перемещая шину в логический «0» на длительность от 60us до 240us. response = (ONE_WIRE_PIN & (1 << ONE_WIRE_DQ)); _delay_us(410); // если 0, значит есть ответ от датчика, если 1 - нет return response; } /* * отправить один бит */ void writeBit(uint8_t bit) { if (bit & 1) { cli(); // логический «0» на 1us ONE_WIRE_PORT &= ~(1 << ONE_WIRE_DQ); ONE_WIRE_DDR |= (1 << ONE_WIRE_DQ); // выход _delay_us(10); sei(); ONE_WIRE_DDR &= ~(1 << ONE_WIRE_DQ); // вход _delay_us(55); } else { cli(); // логический «0» на 1us ONE_WIRE_PORT &= ~(1 << ONE_WIRE_DQ); ONE_WIRE_DDR |= (1 << ONE_WIRE_DQ); // выход _delay_us(65); ONE_WIRE_DDR &= ~(1 << ONE_WIRE_DQ); // вход sei(); _delay_us(5); } } /* * отправить один байт */ void writeByte(uint8_t byte) { uint8_t i = 8; while (i--) { writeBit(byte & 1); byte >>= 1; } } /* * получить один байт */ uint8_t readByte() { uint8_t i = 8, byte = 0; while (i--) { byte >>= 1; byte |= (readBit() << 7); } return byte; } /* * получить один бит */ uint8_t readBit(void) { uint8_t bit = 0; cli(); // логический «0» на 1us ONE_WIRE_PORT &= ~(1 << ONE_WIRE_DQ); ONE_WIRE_DDR |= (1 << ONE_WIRE_DQ); // вход _delay_us(3); // освободить линию и ждать 14us ONE_WIRE_DDR &= ~(1 << ONE_WIRE_DQ); // вход _delay_us(10); // прочитать значение if (ONE_WIRE_PIN & (1 << ONE_WIRE_DQ)) { bit = 1; } // ждать 45us и вернуть значение sei(); _delay_us(45); return bit; } /* * читать ROM подчиненного устройства (код 64 бита) */ uint64_t readRoom(void) { uint64_t oneWireDevice; if(reset() == 0) { writeByte(CMD_READROM); // код семейства oneWireDevice = readByte(); // серийный номер oneWireDevice |= (uint16_t)readByte()<<8 | (uint32_t)readByte()<<16 | (uint32_t)readByte()<<24 | (uint64_t)readByte()<<32 | (uint64_t)readByte()<<40 | (uint64_t)readByte()<<48; // CRC oneWireDevice |= (uint64_t)readByte()<<56; } else { return 1; } return oneWireDevice; } /* * Команда соответствия ROM, сопровождаемая последовательностью * кода ROM на 64 бита позволяет устройству управления шиной * обращаться к определенному подчиненному устройству на шине. */ void setDevice(uint64_t rom) { uint8_t i = 64; reset(); writeByte(CMD_MATCHROM); while (i--) { writeBit(rom & 1); rom >>= 1; } } /* * провеска CRC, возвращает "0", если нет ошибок * и не "0", если есть ошибки */ uint8_t crcCheck(uint64_t data8x8bit, uint8_t len) { uint8_t dat, crc = 0, fb, stByte = 0; do { dat = (uint8_t) (data8x8bit >> (stByte * 8)); for (int i = 0; i < 8; i++) { // счетчик битов в байте fb = crc ^ dat; fb &= 1; crc >>= 1; dat >>= 1; if (fb == 1) { crc ^= 0x8c; // полином } } stByte++; } while (stByte < len); // счетчик байтов в массиве return crc; } /* * поиск устройств */ void searchRom(uint64_t * roms, uint8_t & n) { uint64_t lastAddress = 0; uint8_t lastDiscrepancy = 0; uint8_t err = 0; uint8_t i = 0; do { do { lastAddress = searchNextAddress(lastAddress, lastDiscrepancy); if(lastAddress != DEVICES_ERROR) { uint8_t crc = crcCheck(lastAddress, 8); if (crc == 0) { roms[i++] = lastAddress; err = 0; } else { err++; } } else { err++; } if (err > 3) { return; } } while (err != 0); } while (lastDiscrepancy != 0 && i < n); n = i; } /* * поиск следующего подключенного устройства */ uint64_t searchNextAddress(uint64_t lastAddress, uint8_t & lastDiscrepancy) { uint8_t searchDirection = 0; uint64_t newAddress = 0; uint8_t idBitNumber = 1; uint8_t lastZero = 0; reset(); writeByte(CMD_SEARCHROM); while (idBitNumber < 65) { uint8_t idBit = readBit(); uint8_t cmpIdBit = readBit(); // id_bit = cmp_id_bit = 1 if (idBit == 1 && cmpIdBit == 1) { return DEVICES_ERROR; } else if (idBit == 0 && cmpIdBit == 0) { // id_bit = cmp_id_bit = 0 if (idBitNumber == lastDiscrepancy) { searchDirection = 1; } else if (idBitNumber > lastDiscrepancy) { searchDirection = 0; } else { if ((uint8_t) (lastAddress >> (idBitNumber - 1)) & 1) { searchDirection = 1; } else { searchDirection = 0; } } if (searchDirection == 0) { lastZero = idBitNumber; } } else { // id_bit != cmp_id_bit searchDirection = idBit; } newAddress |= ((uint64_t) searchDirection) << (idBitNumber - 1); writeBit(searchDirection); idBitNumber++; } lastDiscrepancy = lastZero; return newAddress; } /* * пропустить ROM */ void skipRom() { reset(); writeByte(CMD_SKIPROM); }
Подключение одного DS18B20 к ATmega8
Самый простой способ подключения термодатчика DS18B20 к микроконтроллеру, конечно же, подключение одного датчика. В таком случае нет необходимости искать адрес подключённого датчика, а можем напрямую с ним общаться и считывать данные. Всё это возможно благодаря команды SKIP ROM [CCh] — Пропуск ROM [CCh]. Обратите внимание, что команда ЧТЕНИЕ ПАМЯТИ [BEh] может следовать за командой Пропуска ROM, только если на шине присутствует одно подчиненное устройство. Команда Пропуска ROM, сопровождаемая командой ЧТЕНИЕ ПАМЯТИ вызовет конфликт на уровне данных на шине, если на шине более одного подчиненного устройства, так как все устройства будут пытаться одновременно передавать данные.
main.cpp
#include "config.h" #include <avr/io.h> #include <util/delay.h> #include <stdlib.h> #include <string.h> #include <math.h> #include "OneWire.h" #include "LCD.h" // 123.4 // numbers[0] = 123 // numbers[1] = 4 inline void explodeDoubleNumber(int* numbers, double flt) { numbers[0] = abs((int) flt); numbers[1] = abs((int) ((flt - ((int) flt)) * 10)); } inline void printTemp(double d) { char text[17] = "T = "; int fs[2]; char num[5]; explodeDoubleNumber(fs, d); if (d < 0) { strcat(text, "-"); } itoa(fs[0], num, 10); strcat(text, num); strcat(text, "."); itoa(fs[1], num, 10); strcat(text, num); strcat(text, "'C"); lcdClear(); lcdGotoXY(0, 0); lcdPuts(text); } double getTemp(void) { uint8_t temperatureL; uint8_t temperatureH; double retd = 0; skipRom(); writeByte(CMD_CONVERTTEMP); _delay_ms(750); skipRom(); writeByte(CMD_RSCRATCHPAD); temperatureL = readByte(); temperatureH = readByte(); retd = ((temperatureH << 8) + temperatureL) * 0.0625; return retd; } int main(void) { _delay_ms(100); lcdInit(); lcdClear(); lcdSetDisplay(LCD_DISPLAY_ON); lcdSetCursor(LCD_CURSOR_OFF); oneWireInit(PINB0); double temperature; while (1) { temperature = getTemp(); printTemp(temperature); _delay_ms(500); } } // site: http://micro-pi.ru
double getTemp(void)
— возвращает данные температуры в градусах Цельсия.
inline void printTemp(double d)
— отображает на экран температуру.
inline void explodeDoubleNumber(int* numbers, double flt)
— преобразует вещественное число flt в два целых, которые записываются в numbers.
Вместо функций inline void printTemp(double d)
и inline void explodeDoubleNumber(int* numbers, double flt)
можно использовать sprintf(), но она жрёт слишком много памяти.
Обычное питание
Результат
Паразитное питание
Результат
Подключение нескольких DS18B20 к ATmega8
Подключить несколько датчиков DS18B20 к ATmega8 или к другому микроконтроллеру, можно двумя способами. Первый способ — датчики можно подключить на разные выводы микроконтроллера, это самый простой способ, но в таком случае число подключенных датчиков зависит от числа выводов. Второй и самый лучший способ — это подключить все датчики на одну шину, в данном случае необходимо будет найти адреса всех подключённых датчиков.
Подключение нескольких DS18B20 к ATmega8 на разные выводы
main.cpp
#include "config.h" #include <avr/io.h> #include <util/delay.h> #include <stdlib.h> #include <string.h> #include <math.h> #include "OneWire.h" #include "LCD.h" // 123.4 // numbers[0] = 123 // numbers[1] = 4 inline void explodeDoubleNumber(int* numbers, double flt) { numbers[0] = abs((int) flt); numbers[1] = abs((int) ((flt - ((int) flt)) * 10)); } inline void printTemp(double d, uint8_t i) { char text[17] = "T["; int fs[2]; char num[5]; itoa(i, num, 10); strcat(text, num); strcat(text, "]="); explodeDoubleNumber(fs, d); if (d < 0) { strcat(text, "-"); } itoa(fs[0], num, 10); strcat(text, num); strcat(text, "."); itoa(fs[1], num, 10); strcat(text, num); strcat(text, "'C"); lcdClear(); lcdGotoXY(0, 0); lcdPuts(text); } double getTemp(uint8_t pin) { uint8_t temperatureL; uint8_t temperatureH; double retd = 0; oneWireInit(pin); skipRom(); writeByte(CMD_CONVERTTEMP); _delay_ms(750); skipRom(); writeByte(CMD_RSCRATCHPAD); temperatureL = readByte(); temperatureH = readByte(); retd = ((temperatureH << 8) + temperatureL) * 0.0625; return retd; } int main(void) { _delay_ms(100); lcdInit(); lcdClear(); lcdSetDisplay(LCD_DISPLAY_ON); lcdSetCursor(LCD_CURSOR_OFF); double temperature; uint8_t pin = 0; while (1) { temperature = getTemp(pin); printTemp(temperature, pin); if (pin == 4) { pin = 0; } else { pin++; } _delay_ms(500); } } // site: http://micro-pi.ru
Результат
Подключение нескольких DS18B20 к ATmega8 на одну шину
При подключение нескольких датчиков DS18B20 к ATmega8 на одну шину, главное устройство (микроконтроллер) должно определить коды ROM всех подчиненных устройств на шине. Команда SEARCH ROM [F0h] — (ПОИСК ROM) позволяет устройству управления определять номера и типы подчиненных устройств. Устройство управления изучает коды ROM через процесс устранения, которое требует, чтобы Главное устройство исполнил цикл Поиска ROM (то есть, команда ROM Поиска, сопровождаемая обменом данных). Эту процедуру необходимо выполнить столько раз, сколько необходимо, чтобы идентифицировать все из подчиненных устройств. Если есть только одно подчиненное устройство на шине, более простая команда READ ROM [33h] (Чтения ROM) может использоваться место процесса Поиска ROM.
После каждого цикла Поиска ROM, устройство управления шиной должно возвратиться к Шагу 1 (Инициализация) в операционной последовательности.
Алгоритм поиска 1-Wire устройств с использованием команды Search ROM прекрасно описан в этом видео:
main.cpp
#include "config.h" #include <avr/io.h> #include <util/delay.h> #include <stdlib.h> #include <string.h> #include <math.h> #include "OneWire.h" #include "LCD.h" // 123.4 // numbers[0] = 123 // numbers[1] = 4 inline void explodeDoubleNumber(int* numbers, double flt) { numbers[0] = abs((int) flt); numbers[1] = abs((int) ((flt - ((int) flt)) * 10)); } inline void printTemp(double d, uint8_t i) { char text[17] = "T["; int fs[2]; char num[5]; itoa(i, num, 10); strcat(text, num); strcat(text, "]="); explodeDoubleNumber(fs, d); if (d < 0) { strcat(text, "-"); } itoa(fs[0], num, 10); strcat(text, num); strcat(text, "."); itoa(fs[1], num, 10); strcat(text, num); strcat(text, "'C"); lcdClear(); lcdGotoXY(0, 0); lcdPuts(text); } double getTemp(uint64_t ds18b20s) { uint8_t temperatureL; uint8_t temperatureH; double retd = 0; setDevice(ds18b20s); writeByte(CMD_CONVERTTEMP); _delay_ms(750); setDevice(ds18b20s); writeByte(CMD_RSCRATCHPAD); temperatureL = readByte(); temperatureH = readByte(); retd = ((temperatureH << 8) + temperatureL) * 0.0625; return retd; } int main(void) { _delay_ms(100); lcdInit(); lcdClear(); lcdSetDisplay(LCD_DISPLAY_ON); lcdSetCursor(LCD_CURSOR_OFF); oneWireInit(PIND7); double temperature; uint8_t n = 8; uint64_t roms[n]; searchRom(roms, n); char txt[17] = "devices ["; char num[5]; itoa(n, num, 10); strcat(txt, num); strcat(txt, "]"); lcdClear(); lcdGotoXY(0, 0); lcdPuts(txt); _delay_ms(2000); while (1) { for (uint8_t i = 0; i < n; i++) { temperature = getTemp(roms[i]); printTemp(temperature, i + 1); _delay_ms(500); } } } // site: http://micro-pi.ru
Обычное питание
Результат
Паразитное питание
Результат
Внимание! При использовании паразитного питания не рекомендуется использовать датчики для температуры выше +100ºC, а также при операциях преобразования температуры и копирования данных из Scratchpad в один из регистров EEPROM, потребляемый ток может достигать 1.5 мА, что непосильно внутреннему конденсатору, а на резисторе подтяжки (R1 4.7k) будет большое падение напряжения, что недопустимо скажется на работе устройства в целом. Для этого необходимо организовать линии DQ схему мощной подтяжки, реализуемой по такой схеме:
После выдачи команды конвертирования температуры [44h] или копирования ОЗУ В ПЗУ (Copy Scratchpad) [48h] необходимо включить мощную подтяжку MOSFET-транзистором линии DQ на 10 мкс (макс.), как указанно в даташите датчика, после чего выждать время преобразования или время передачи данных, причем в это время никаких действий при включенной мощной подтяжке на линии DQ быть не должно!
Скачать Atmel Studio 7 проекты и схемы в ISIS Professional (Proteus):
DS18B20 + LCD 16×2 + ATmega8 — ISIS Professional (Proteus)
DS18B20 + LCD 16×2 + ATmega8 — Atmel Studio 7
Собрал пример с одним датчиком, LCD только двухстрочны. На экране «Т = -0,0 С». Почему так???
Все заработало, разобрался.Дело в конфигурации фьюзов, по умолчанию частота стоит 1мгц , а по коду надо 8мгц. Я новичок по этому не сразу вник в детали. А какая конфигурация фьюзов используется вами в данном проекте? На примере khazama AVR.
Спасибо за интересную статью!!! А аналогичные примеры есть с применением I2C подключения к LCD в Atmel Studio???
Жаль, а я только пытаюсь изучить студию…..
Здравствуйте! Пытаюсь внедрить Ваш код по подключению двух датчиков на одну шину в Atmel Studio 6.2. Дело в том, что основной проект у меня написан на СИ (не СИ++), и почему-то компилятор ругается на два определения в OneWire.h и соответственно OneWire.cpp:
void searchRom(uint64_t*, uint8_t&);
и
uint64_t searchNextAddress(uint64_t, uint8_t&);
а именно на знак «&». Честно сказать не понимаю зачем он нужен, но после того как его убрал, проект успешно скомпилировался, но возникла проблема — в массиве rom после выполнения функции searchRom(roms, n), определяется только один серийный номер датчика (второй равен нулю) и соответственно выводится температура только его одно. Помогите разобраться в чем дело. Заранее спасибо.
admin, большое спасибо!
Спасибо вам за статью, вы мне значительно облегчили работу с курсовым проектом
скомпилировал версию c одним датчиком «1xDS18B20+LCD 16×2+ATmega8» в AtmelStudio7 — успешно под atmega8, получил hex, пошел в протеус 8.2 sp3 — перерисовал схему, загрузил ранее полученную прошивку — в результате экран показывает «T= -0.0C» скриншот
было тожесамое как и Евгения «Все заработало, разобрался.Дело в конфигурации фьюзов, по умолчанию частота стоит 1мгц , а по коду надо 8мгц. »
переключил в протеусе фьюз на 8мгц внутренний и заработало
Hi! В OneWire.cpp cтрока 7:
uint8_t ONE_WIRE_DQ = PINB0;
что это значит, ведь датчики подключены к порту D пин 7???
Автору огромное спасибо! Всё работает (прилагая свои мозги и прямые руки ;). Пытаясь подружить Atmel и MPLAB-X v5.2, адаптировал код автора под тулчайн WinAVR — работает так как надо!!!
Здравствуйте, запустил в протеусе схему с одним датчиком, и загрузил программу туда — все работало.
Решил сделать термометр, когда собрал, программу залил в Atmega8 через SinaProg, термометр запитываю с ArduinoUno — все выключается. Вытаскиваю датчик, подключаю питание экран показывает » t=-9999*C «.
Получается что с датчиком схема выключается из-за короткого замыкания, без датчика вроде все работает, но температуру не показывает, схему проверял мультиметром замыканий ни где нет, проверил контакт PB2 включенным без датчика он выдает 5 Вольт, хотя если PB2 настроен на считывание то там не должно быть этих 5-ти Вольт.
Подскажите что можно сделать
А можно туже самую задачу, только на «С»?И еще превратить простой термометр в многоканальный терморегулятор?
Но как опрашивать датчики по порядку, по адресам, если они на одном проводе?
Здравствуйте. Кто занимается программированием на МК? Меня интересует схема 2-х канального термометра на МК. Я ищу любителя-программиста, с которым я бы смог воплотить в жизнь свою задумку. Немного расширить функционал термометра, использовать более крупный ЖК дисплей, добавить некоторые модуля. Если кто в принципе согласен, то можно продолжить общаться далее. А заодно скажите пожалуйста регион вашего проживания и почту для общения.
Добрый день!
Сейчас работаю над аналогичным проектом, вернее над двумя.
Первый — схема с динамической индикацией на MAX7219, МК Atmega1284, часы реального времени DS1307, датчик давления воздуха (атмосферы), датчик относительной влажности воздуха, два датчика температуры DS18B20. Индикаторы -светодиодные. Часы-двухдюймовые, а остальная индикация 10мм. Ранее собрал, но так как не имел опыта программирования, плата одна, а часы, термометр, барометр и измеритель влажности — каждый имел свой контроллер. Конструкцию собирал лет 10 назад. Плюс имеются два будильника с музыкальными мелодиями, можно по заданному времени что-то включать -выключать. Могу поделиться информацией и опытом. Мой e-mail: vigavic07@mail.ru
С уважением, Виктор
Доброго времени суток!!!
Спасибо за проделанную работ!!!
Особенно понравилась написанная работа, над поиском rom code с помощью регистров lastDiscrepancy и lastZero.
Подскажите как обойтись без цикла for и без задержки, а сделать все по прерыванию таймера? Что бы не занимать в пустую тактовое время?
for (uint8_t i = 0; i < n; i++) {
temperature = getTemp(roms[i]);
printTemp(temperature, i + 1);
_delay_ms(1000);
}
У Вас Функция itoa() конвертирует целое число num в строчный эквивалент и помещает результат в строку?
Решил с ассемблера перейти на си, все вроде как бы понятно, но не очень, пока путаюсь в самом синтаксисе языка си.
Доброго времени суток!!!
Подскажите название переменных, где лежит окончательная преобразованная температура двух DS в десятичном виде, после считывания с DS? Что бы была возможность оперировать условиями при изменении температуры.
Я в отладчике смотрел изменение переменных так и не понял какие.
Добавил в Ваш код по таймеру 1 атмега128. Без задержки.
for (uint8_t i = 0; i < n; i++){
temperature = getTemp(roms[i]);
if (BIT_state ==1){
printTemp(temperature, i + 1);
// _delay_ms(1000);
}
}
Доброго времени суток!!!
Если есть время подскажите как на языке С, с переменной uint64_t — byte_data_rom конвертировать в удобочитаемый вид, для вывода посимвольно считанного romcode на LCD?
Я таким макаром, вывожу на дисплей.
Пока есть свободное время, недельки две, хочу позаниматься языком Си.
Всё-таки не работает ни один код. Пробовал с разными датчиками: в корпусе ТО-92 и в герметичном. Показывает -0.0 или без минуса 0.0.
Автор самозванец, никакой он не препод в универе. Код передран отсюда: https://narodstream.ru/stm-urok-94-ds18b20-podklyuchaem-neskolko-datchikov-na-provod-chast-1/ и переделан под ATmega8.
Здравствуйте! Пытаюсь внедрить Ваш код по подключению двух датчиков на одну шину в Atmel Studio 6.2. Дело в том, что основной проект у меня написан на СИ (не СИ++), и почему-то компилятор ругается на два определения в OneWire.h и соответственно OneWire.cpp:
void searchRom(uint64_t*, uint8_t&);
и
uint64_t searchNextAddress(uint64_t, uint8_t&);
а именно на знак «&». Честно сказать не понимаю зачем он нужен, но после того как его убрал, проект успешно скомпилировался, но возникла проблема — в массиве rom после выполнения функции searchRom(roms, n), определяется только один серийный номер датчика (второй равен нулю) и соответственно выводится температура только его одно. Помогите разобраться в чем дело. Заранее спасибо
доброго времени суток почему то не компилируется ругается на #include «config.h»
1 раз отработал и все. Больше в протеусе не работает. на табло -0.0. Частота 8мГц. Все коды по 1 разу отработали …
Здравствуйте. Вопрос : почему микрочип(atmelstudio) не компилирует вот эта #ifndef CONFIG_H_
#define CONFIG_H_
#define F_CPU 8000000UL
#define ONE_WIRE_PORT PORTB
#define ONE_WIRE_DDR DDRB
#define ONE_WIRE_PIN PINB
#endif /* CONFIG_H_ */
zithromax 500 mg lowest price online: cheap zithromax pills — zithromax drug
https://ciprofloxacin.cheap/# cipro
where can i buy cipro online: buy cipro without rx — п»їcipro generic
zithromax z-pak price without insurance generic zithromax 500mg where can i buy zithromax capsules
buy cenforce cenforce.icu Purchase Cenforce Online
https://kamagra.men/# Kamagra tablets
generic rybelsus tabs: semaglutide tablets price — semaglutide tablets store
semaglutide tablets for weight loss: semaglutide best price — cheap semaglutide pills
http://drugs1st.pro/# drugs1st
cheap semaglutide pills generic rybelsus tabs semaglutide tablets store
http://kamagra.men/# buy kamagra online usa
cheapest cenforce: Cenforce 150 mg online — Cenforce 100mg tablets for sale
https://edpills.men/# cheapest ed meds
cheapest ed pills: cheapest ed meds — cheap ed pills online
cenforce for sale: Cenforce 100mg tablets for sale — order cenforce
slot oyunlar? puf noktalar?: az parayla cok kazandiran slot oyunlar? — en cok kazand?ran slot oyunlar?
пин ап казино зеркало пин ап казино официальный сайт пин ап казино
casino en iyi siteler: jackpot play nedir — welches online casino
http://slottr.top/# slot oyunlar?
пин ап казино зеркало: пин ап зеркало — pinup 2025
slot tr online: en cok kazand?ran slot oyunlar? — en kazancl? slot oyunlar?
yabancД± Еџans oyunlarД± siteleri deneme bonusu veren slot siteleri 2025 en gГјvenilir bahis
slot oyunlar?: en cok kazand?ran slot oyunlar? — slot tr online
http://slottr.top/# slot tr online
yatД±rД±m bonusu veren siteler vidobet superbeting
casino gГјncel giriЕџ: casino bonusu veren siteler — kayД±t bonusu veren casino siteleri
betnoo: en Г§ok kazandД±ran bahis siteleri — gГјvenilir siteler
pinup 2025 пин ап пин ап вход
http://pinup2025.com/# pinup 2025
slot tr online: az parayla cok kazandiran slot oyunlar? — en cok kazand?ran slot oyunlar?
en cok kazand?ran slot oyunlar? az parayla cok kazandiran slot oyunlar? slot oyunlar?
sГјperbetine: casino giriЕџ — oyun sitesi oyun sitesi oyun sitesi
slot oyunlar?: az parayla cok kazandiran slot oyunlar? — slot siteleri
en cok kazand?ran slot oyunlar? az parayla cok kazandiran slot oyunlar? slot tr online
http://casinositeleri2025.pro/# oyun dene
пин ап казино официальный сайт: пин ап зеркало — pinup 2025
en iyi bahis uygulamasД±: vidobet giriЕџ 2025 — casinombet
пин ап казино: пин ап казино — pinup2025.com
пин ап зеркало: pinup 2025 — pinup2025.com
slot oyunlar? en cok kazand?ran slot oyunlar? slot tr online
jav siteleri: en iyi kumar sitesi — gГјvenilir bahis siteleri
bilinmeyen bahis siteleri yasal casino siteleri bonus veren siteler
https://mexicanpharmi.com/# best online pharmacies in mexico
online pharmacy india Online India pharmacy pharmacy website india
mail order pharmacy india: India pharmacy delivery — reputable indian pharmacies
cheap pills online: Best Canadian pharmacy — cheap pills online
https://indiapharmi.com/# top online pharmacy india
mexico drug stores pharmacies: Cheapest online pharmacy — mexican rx online
http://canadianpharmi.com/# how to fix ed
ed meds online without doctor prescription: Canada pharmacy online — best ed medications
mexican drugstore online Legit online Mexican pharmacy mexican border pharmacies shipping to usa
buy medicines online in india: Online medicine home delivery — indian pharmacy paypal
https://indiapharmi.com/# india pharmacy
online pharmacy india Indian online pharmacy ship to USA india online pharmacy
mexican rx online: Online pharmacy — buying prescription drugs in mexico online
otc ed pills [url=https://canadianpharmi.com/#]Canada Pharmacy[/url] natural ed remedies
https://mexicanpharmi.com/# reputable mexican pharmacies online
best india pharmacy: Indian online pharmacy ship to USA — reputable indian online pharmacy
mexican drugstore online: Online pharmacy — buying from online mexican pharmacy
carprofen without vet prescription Canada Pharmacy natural pills for ed
https://canadianpharmi.com/# best male enhancement
reputable indian online pharmacy: indiapharmi — buy prescription drugs from india
https://mexicanpharmi.com/# mexican online pharmacies prescription drugs
indianpharmacy com Best Indian pharmacy online shopping pharmacy india
https://canadianpharmi.com/# injections for ed
http://cipharmdelivery.com/# ciprofloxacin 500 mg tablet price
https://clomidonpharm.com/# can you get generic clomid tablets
average cost of prednisone PredniBest buying prednisone without prescription
buy ciprofloxacin over the counter: CiPharmDelivery — buy ciprofloxacin
http://cipharmdelivery.com/# ciprofloxacin over the counter
how to get amoxicillin generic amoxicillin 500mg can we buy amoxcillin 500mg on ebay without prescription
https://amoxstar.com/# amoxicillin 500mg
can you get clomid without prescription: where can i get clomid — order clomid price
where can i get amoxicillin 500 mg: Amox Star — amoxicillin 875 mg tablet
п»їcipro generic ci pharm delivery buy cipro online without prescription
prednisone 5mg over the counter: prednisone 300mg — average cost of prednisone
http://prednibest.com/# prednisone 60 mg tablet
prednisone 20mg tablets where to buy: 1 mg prednisone cost — prednisone cost 10mg
can you buy generic clomid online: can you get clomid for sale — generic clomid no prescription
where can i buy clomid: clomid on pharm — clomid without dr prescription
http://prednibest.com/# can you buy prednisone in canada
1 mg prednisone daily Predni Best prednisone 60 mg tablet
http://amoxstar.com/# amoxicillin over counter
azithromycin amoxicillin: AmoxStar — amoxicillin 500 mg price
amoxicillin for sale amoxicillin online canada amoxicillin 500 mg price
buying prednisone mexico: prednisone 5093 — prednisone 7.5 mg
amoxicillin 500 tablet Amox Star can we buy amoxcillin 500mg on ebay without prescription
prednisone for sale prednisone for sale prednisone online sale
prednisone buy no prescription: buy prednisone 20mg without a prescription best price — prednisone price canada
http://clomidonpharm.com/# can i get generic clomid without rx
cipro ciprofloxacin: buy ciprofloxacin — cipro ciprofloxacin
prednisone 10 mg daily Predni Best pharmacy cost of prednisone
http://amoxstar.com/# amoxicillin for sale
amoxicillin 250 mg capsule: Amox Star — amoxicillin 500
https://amoxstar.com/# amoxicillin 750 mg price
cipro for sale: buy cipro online — cipro online no prescription in the usa