Подключение DS18B20 к ATmega8 и вывод на LCD HD44780-MicroPi
#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);
}
micro-pi.ru
Подключение DS18B20 к ATtiny2313 и вывод на HD44780-MicroPi
#define F_CPU 8000000UL
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include «ds18b20.h»
/*
* ds18b20 — инициализация
*/
uint8_t resetDS18B20() {
uint8_t i;
// импульс сброса, минимум 480?s
DS18B20_PORT &= ~(1 << DS18B20_DQ);
DS18B20_DDR |= (1 << DS18B20_DQ); // выход
_delay_us(480);
// Когда DS18B20 обнаруживает положительный перепад, он ждет от 15?s до 60?s
DS18B20_DDR &= ~(1 << DS18B20_DQ); // вход
_delay_us(60);
// и затем передает импульс присутствия, перемещая шину в логический «0» на длительность от 60?s до 240?s.
i = (DS18B20_PIN & (1 << DS18B20_DQ));
_delay_us(420);
//return the read value, 0=ok, 1=error
return i;
}
/*
* написать один бит
*/
inline void writeBitDS18B20(uint8_t bit) {
// логический «0» на 1?s
DS18B20_PORT &= ~(1 << DS18B20_DQ);
DS18B20_DDR |= (1 << DS18B20_DQ); // выход
_delay_us(1);
// если нужно написать 1, нужно освободить линию (если не — держать низкий уровень)
if (bit) {
DS18B20_DDR &= ~(1 << DS18B20_DQ); // вход
}
// ждать 60?s и освободить линию
_delay_us(60);
DS18B20_DDR &= ~(1 << DS18B20_DQ); // вход
}
/*
* прочитать один бит
*/
uint8_t readBitDS18B20(void) {
uint8_t bit = 0;
// логический «0» на 1?s
DS18B20_PORT &= ~(1 << DS18B20_DQ);
DS18B20_DDR |= (1 << DS18B20_DQ); // вход
_delay_us(1);
// освободить линию и ждать 14?s
DS18B20_DDR &= ~(1 << DS18B20_DQ); // вход
_delay_us(14);
// прочитать значение
if (DS18B20_PIN & (1 << DS18B20_DQ)) {
bit = 1;
}
// ждать 45?s и вернуть значение
_delay_us(45);
return bit;
}
/*
* написать один байт
*/
void writeByteDS18B20(uint8_t byte) {
uint8_t i = 8;
while (i—) {
writeBitDS18B20(byte & 1);
byte >>= 1;
}
}
/*
* прочитать один байт
*/
uint8_t readByteDS18B20(void) {
uint8_t i = 8, n = 0;
while (i—) {
n >>= 1;
n |= (readBitDS18B20() << 7);
}
return n;
}
/*
* получить температуру
*/
double getTempDS18B20() {
uint8_t temperatureL;
uint8_t temperatureH;
double retd = 0;
if (DS18B20_STOPINTERRUPTONREAD == 1) {
cli();
}
resetDS18B20(); // сброс
writeByteDS18B20(DS18B20_CMD_SKIPROM); // пропуск ПЗУ(ROM)
writeByteDS18B20(DS18B20_CMD_CONVERTTEMP); // начать преобразование показаний температуры
while (!readBitDS18B20()); // ждать, пока преобразование не завершится
resetDS18B20(); // сброс
writeByteDS18B20(DS18B20_CMD_SKIPROM); // пропуск ПЗУ(ROM)
writeByteDS18B20(DS18B20_CMD_RSCRATCHPAD); // читать scratchpad
// прочитать 2 байта из scratchpad
temperatureL = readByteDS18B20();
temperatureH = readByteDS18B20();
if (DS18B20_STOPINTERRUPTONREAD == 1) {
sei();
}
// преобразовать полученное 12 битное значение
retd = ((temperatureH << 8) + temperatureL) * 0.0625;
return retd;
}
micro-pi.ru
1-Wire. Работа с DS18B20. Часть 1
Все (и в том числе я) называют DS18B20 цифровым датчиком температуры. Однако это не просто датчик, это программируемый цифровой термометр. Он измеряет температуру в диапазоне от –55 до +125 градусов Цельсия, имеет программируемое температурное разрешение от 9 до 12 бит и позволяет задавать верхний и нижний температурные пороги, в случае превышения которых, устанавливается флаг аварии.Каждый термометр DS18B20 имеет уникальный 64 битный серийный номер, который используется для его адресации на 1-Wire шине. Это позволяет объединять на одной шине несколько независимо работающих термометров и осуществлять между ними и микроконтроллером обмен данными по 1-Wire протоколу.
Также особенностью данного термометра является то, что его можно запитывать не только от источника питания, но и от сигнального провода. Это так называемый режим паразитного питания. В этом режиме для подключения DS18B20 требуется всего два провода — сигнальный и возвратный (земляной, GND).
Схема подключения датчика DS18B20 в режиме паразитного питания.
Вывод Vdd соединяется с GND, а 1-Wire шина дополнительно подключается к источнику питания через полевой транзистор.
Когда датчик DS18B20 выполняет преобразование температуры или копирует данные из ОЗУ в EEPROM память, он потребляет ток до 1,5 мА. Этот ток может вызывать недопустимое снижение напряжения на 1-Wire шине. Чтобы этого не происходило, 1-Wire шину на время выполнения этих операций подключают к источнику питания. Для этого и нужен полевой транзистор.
Для обмена данными термометр DS18B20 использует 1-Wire протокол (однопроводный протокол). Это низкоскоростной двунаправленный полудуплексный последовательный протокол обмена данными использующий всего один сигнальный провод. Естественно требуется еще и возвратный (земляной) провод, но об этом маркетологи обычно умалчивают. 1-Wire протокол был разработан фирмой Dallas Semiconductor в конце 90-х годов.
Имеется несколько типов сигналов, определенных 1-Wire протоколом — импульс сброса, импульс присутствия, запись 0, запись 1, чтение 0 и чтение 1. Все эти сигналы, за исключением импульса присутствия, формируются на шине главным устройством — MASTERом . В нашем случае это микроконтроллер AVR.
Принцип формирования сигналов во всех случаях одинаковый. В начальном состоянии 1-Wire шина с помощью резистора подтянута к плюсу питания. Главное устройство «проваливает» на определенное время 1-Wire шину в ноль, затем «отпускает» ее и, если нужно, «слушает» ответ подчиненного (SLAVE) устройства. В нашем случае подчиненное устройство — термометр DS18B20.
Физически это реализуется так.
Операция записи бита: Вывод микроконтроллера устанавливается в режим выхода и на нем устанавливается логический ноль. Выдерживается пауза, длительность которой зависит от значения передаваемого бита (0 или 1), затем вывод переводится в режим входа в состоянии Hi-z и снова выдерживается пауза.
Операция чтения бита: Вывод микроконтроллера устанавливается в режим выхода и на нем устанавливается логический ноль. Выдерживается определенная пауза, вывод переводится в режим входа в состоянии Hi-z, выдерживается пауза, а затем микроконтроллер считывает потенциал вывода.
Все сеансы связи микроконтроллера с датчиком DS18B20 начинаются с сигнала сброса. Микроконтроллер на 480 мкс «проваливает» 1-Wire шину в ноль, а затем «отпускает» ее. Если к шине подключен термометр DS18B20, то он обнаруживает положительный перепад и после паузы в 15-60 мкс отвечает микроконтроллеру импульсом присутствия — «проваливает» шину в ноль на время от 60 до 240 мкс.
Обмен данными по 1-Wire шине происходит последовательно, младшим битом вперед. Передача или прием одного бита данных выполняются в течении фиксированного промежутка времени, так называемого тайм слота (time slot). Различают тайм слоты записи и тайм слоты чтения. Длительность всех тайм слотов должна быть > 60 мкс, а пауза между тайм слотами > 1 мкс.
Для передачи нуля микроконтроллер «проваливает» 1-Wire шину на время от 60 до 120 мкс. Затем «отпускает» ее и перед записью следующего бита выдерживает паузу >1 мкс.
Для передачи единицы микроконтроллер «проваливает» 1-Wire шину на время от 1 до 15 мкс, «отпускает» ее и выдерживает паузу. Пауза должна быть такой, чтобы длительность тайм слота была > 60+1 мкс.
DS18B20 является подчиненным устройством и может передавать данные, только когда микроконтроллер формирует на 1-Wire шине тайм слоты чтения. Для формирования тайм слота чтения микроконтроллер «проваливает» 1-Wire шину на время от 1 до 15 мкс, а затем «отпускает» ее, передавая управление состоянием 1-Wire шины датчику DS18B20. Если DS18B20 передает ноль, он удерживает шину в «проваленном» состоянии (в состоянии логического нуля) до конца тайм слота. Если он передает 1, он оставляет шину в «подтянутом» состоянии.
chipenable.ru
Подключение температурного датчика DS18B20 по схеме с «паразитным» питанием
Существует несколько способов подключения датчиков температуры DS18B20 к сети 1-wire. В этой заметке я опишу способ подключения температурного датчика по схеме с «паразитным» питанием, где в качестве мастера сети 1-wire используется оригинальное USB-устройство DS9490R.
Данный способ подключения является очень удобным, т.к. используются всего две жилы проводника, а так же нет необходимости в дополнительной обвязке со схемой стабилизации питания (если вы планируете использовать в качестве мастера другие устройства, то возможно будет необходима подтяжка — об этом я расскажу позже). Правда стоит отметить, что в официальной документации говорится о возможных негативных последствиях при подключении температурного датчика, но на практике, при использовании мастера DS9490R, я с этими проблемами не встречался.
Итак, схема подключения датчика довольно простая: в качестве шины сети 1-wire я использую простой кабель UTP-5 (витая пара) и, с целью уменьшения помех на линии, использовал для DATA и GND две свитых в одну пару жилы. Ножки датчика 1 (GND) и 3 (Vdd) соединяются накоротко и подключаются к PIN4 у DS9490R. Ножка 2 (DATA) подключается к PIN3 у DS9490R. Таким способом к одному мастеру можно подключить много датчиков (я проверял работоспособность на 15 одновременно подключенных датчиках).
Принципиальная схема подключения DS18B20 с паразитным питанием:
После подключения, датчики появляются в OWFS и показывают температуру 🙂
Преимущества данной схемы подключения:
- Простой и довольно дешевый способ подключения большого количества датчиков температуры
- Нет необходимости во внешнем питании
- Нет необходимости в дополнительной «обвязке»
Недостатки:
- Возможна нестабильная работа на шинах большой длинны и большим количеством ведомых устройств в сети
- Желательно использовать фирменный мастер сети DS9490R
dom-v-provodah.ru