В начало | Зарегистрироваться | Заказать наши киты почтой
 
 
 
 

Немного про шину 1-Wire и цифровой термометр DS18b20

📆31 марта 2014   ✒️teXnik   🔎35.196   💬18  

Здравствуйте, друзья. Хочу предложить вашему вниманию несколько простых функций для работы с шиной 1-Wire и термометром DS18b20 на микроконтроллерах от ATMEL.

1-Wire

Потребовалось мне узнать температуру радиатора в усилителе и как нельзя кстати в закромах была ATMega8 и DS18b20 – цифрой датчик температуры с протоколом 1-wire. Запустил CODEVISIONAVR, взял функции из стандартных библиотек, прошил, запустил и… датчик нагло врал на 3-5 градусов, я сравнивал с пирометром и комнатным термометром. В чем причина безобразия я не понял и решил сам написать все процедуры обмена данными, а заодно и изучить данную шину.

1-Wire — двунаправленная шина связи для устройств с низкоскоростной передачей данных подробнее можно почитать на Wikipedia

Что нужно запомнить

  1. Передача данных и сигналов синхронизации происходит по одному проводу.
  2. Передачу данных всегда инициализирует МК.
  3. Биты данных передаются тайм-слотами со строго ограниченными временными рамками.
  4. На одной шине может находиться несколько устройств.
  5. У каждого устройства есть свой уникальный ROM код.


Начинаем передачу

Для дальнейшей работы с шиной у нас должна быть подключена библиотека delay.h и определены три дефайна.
#include 
// В место 3-его вывода порта B можно использовать любой другой
#define w1_port PORTB.3
#define w1_pin PINB.3
#define w1_ddr DDRB.3

Прежде чем общаться с датчиком МК необходимо убедиться, что на проводе собственно присутствует устройство 1-wire. Для этого есть процедура инициализации. Взглянем на ее диаграмму 1 из даташита на датчик.
Диаграмма 1 — Инициализация.

Что должно происходить:
  1. МК генерирует сигнала reset, удерживая шину в 0 состоянии в течении 480 микросекунд.
  2. Ждем не менее 15, но не боле 60 микросекунд. За это время подтягивающий резистор должен поднять уровень на шине до логической единицы.
  3. Датчик удерживает шину в нулевом состоянии в течении не менее 60 микросекунд. Если за это время шина не смени свое состояние на 0 значит на шине ошибки или датчик не исправен (Долго не мог понять, в чем дело, когда отпаялся подтягивающий резистор и на шине всегда считывался 0).


И собственно функция:
Исключён фрагмент. Полный вариант доступен меценатам и полноправным членам сообщества.

Данная функция возвращает 0 если все в порядке и 1 если нет.

Обмениваемся данными

Передача данных осуществляется побитно так называемыми тайм слотами. Тайм слот – последовательность действий по передачи одного бита. Тайм слот продолжается от 60 до 120 микросекунд.
Снова посмотрим на диаграмму, которою нам предлагают разработчики.
Диаграмма 2 — чтение, запись.

Передаем «0». Что должно происходит:
  1. МК удерживает шину в 0 состоянии в течении 60 микросекунд.
  2. МК отпускает шину давая резистору подтяжки делать свое дело.


Передаем «1». Что должно происходить:
  1. МК удерживает шину в 0 состоянии в течении 15 микросекунд.
  2. МК отпускает шину.

Чтобы передать байт данных необходимо инициализировать 8 тайм слотов соответственно. Передача (и чтение тоже) начинается с младшего разряда.
Функция передачи байта данных:
void w1_send(char cmd)
{
unsigned char bitc=0; 
#asm("cli"); // запрещаем прерывания, что бы не было сбоев при передачи
for (bitc=0; bitc < 8; bitc++)
 {
    if (cmd&0x01) // сравниваем младший бит
        {  
        w1_ddr=1;
        w1_port=0;
        delay_us(15);
        w1_port=1;
        delay_us(50);
        w1_ddr=0;
        delay_us(5);
        }
        else
        { 
        w1_ddr=1;
        w1_port=0;
        delay_us(65);
        w1_ddr=0;
        delay_us(5);
        };          
    cmd=cmd>>1; //сдвигаем передаваемый байт данных на 1 в сторону младших разрядов
    };
#asm("sei");
};


Чтение данных немного сложнее. Что должно происходит:
  1. МК удерживает шину в 0 состоянии в течении 1 микросекунд.
  2. МК отпускает шину.
  3. ждем завершения переходных процессов 14 микросекунд.
  4. МК считывает состояние шины.
  5. Ждем еще 45 микросекунд до конца тайм слота.


Как и при записи для чтения одного байта необходимо 8 тайм слотов.
Функция чтения:
char w1_readbyte(void)
{
unsigned char bitc=0;// счетчик принятых байт
unsigned char res=0; // принятый байт
#asm("cli");

for (bitc=0; bitc < 8; bitc++)
    {
    w1_ddr=1;    // порт на вывод
    w1_port=0;   // начинаем тайм слот записью 0
    delay_us(1);
    w1_ddr=0;         // порт на ввод 
    delay_us(14);     // ждем завершения переходных процессов

    if (w1_pin)                      
        { 
        res|= (1 < < bitc);     // если на ходе 1 то запишем ее в текущий бит
        };
    delay_us(45); // ждем до завершения тайм слота
    };
    delay_us(5);
#asm("sei");
return res;
};


Мы научились читать и передавать байты, но для работы этого еще мало.
В связи с тем, что шина однопроводная и на ней может быть несколько устройств, возможны ошибки при передаче данных. Что бы поверить целостность данных необходимо проверить контрольную сумму. Существует два метода подсчета контрольной суммы – алгоритмический и табличный. Алгоритм не самый тривиальный и я решил использовать табличный.
Нашел на просторах интернета уже вычисленные сигнатуры. Определим их в массив и заведем переменную:
Исключён фрагмент. Полный вариант доступен меценатам и полноправным членам сообщества.


Что бы определить истинность принятых данных необходимо выполнить следующую процедуру для каждого принимаемого байта. При безошибочной передачи значение переменной будет нулевым.

char crc=0;
// строчка в обработчике принятых байт
crc=crckey[crc^received_byte];


Общение с датчиком

Существует ряд общих команд для всех 1-wire устройств. Среди них:
  • 0x33h – считать ромкод (уникальное имя каждого устройства). Применение возможно только, если на шине всего одно устройство.
  • 0x55h – обратиться по ром коду к конкретному устройству. После необходимо также передать 64 битный ром код. Только устройство у которого переданный код совпадет с записанным в него на заводе останется на шине, остальные отключатся.
  • 0xCCh — После приема данной команды все устройства останутся активными на шине. Удобно использовать если устройство одно или есть однотипные.


Несколько команд для DS’ ки:
  • 0x44h – Запуск преобразования температуры. Если датчик питает не от линии данных, то после можно прочитать состояние шины 0 – если преобразование не завершено и 1 – если преобразование завершено.
  • 0xBEh – Считать 8 байт данных. Первые два байта – вычисленная температура.
  • 0x4Eh – запись в память датчика. Необходимо передать три байта – верхнюю границу термостата, нижнюю границу термостата и значение контрольного регистра.


В контрольном регистре задается разрешение термометра от 9 до 12 бит. В зависимости от разрешения сильно меняется время преобразования.
  • 0x1Fh — 9 бит (±0,5 градуса Цельсия), преобразование примерно 94 миллисекунды;
  • 0x3Fh — 10 бит (±0,25 градуса Цельсия), преобразование примерно 188 миллисекунд;
  • 0x5Fh — 11 бит (±0,125 градуса Цельсия), преобразование примерно 375 миллисекунд;
  • 0x7Fh — 12 бит (±0,0625 градуса Цельсия), преобразование примерно 750 миллисекунд;


Подробнее о командах и структуре памяти можно почитать в даташите в конце статьи.
Мне высокая точность вычисления не нужна. Поэтому приведу свой вариант процедур настройки датчика и чтения результатов работы. В нем устанавливается самый быстрый режим работы датчика и чтение результатов с точность до градуса, без учета возможных отрицательных температур.

Настройка датчика:
void ds1820_init(void)
{
if (w1_reset()==0) // если на шине есть откликнувшееся устройство то продолжаем
    {  
    w1_send(0xcc);  // пропустить ром
    w1_send(0x4e); // команда записи в датчик
    w1_send(0x32); // верхняя граница термостата th
    w1_send(0); // нижняя граница термостата tlow
    w1_send(0x1f); // режим работы - 9 бит
    }
    else
    {
// здесь должен быть обработчик ошибки на шине, у меня выводится сообщение на дисплей
    lcd_fstrxy(0,0,"ds1820 error",12);
    };
}


В комментария выше фигурирует слово «термостат». DS18B20 — имеет такую функцию. Если после преобразования температура окажется ниже Tlow или выше Th, установиться флаг alarm. Есть команда ALARM SEARCH [0xECh] на нее отзываться только устройства с установленным флагом аварии. Функция поиска — довольно медленная. Ее использование актуально, на мой взгляд, толь при большом количестве датчиков.

Считываем температуру. Если датчик у нас не один то обращаться придется по rom коду, который вначале необходимо считать
Исключён фрагмент. Полный вариант доступен меценатам и полноправным членам сообщества.


Недостатком использование этой процедуры в том, что ее использовать можно только когда на шине присутствует одно устройство. Соответственно, если на датчиков несколько, то их подключать надо по очереди и для каждого вызывать эту функцию.

Функция выдачи ром кода на шину:
void w1_writerom(char num)
{
char bytec=0;
for (bitc=0; bytec < 8; bytec++)
    { 
    w1_send(dsrom[num][bytec]);
    };
};

И наконец чтение температуры с датчика с номером DSnum:

char ds1820_readt(char DSnum)
{
int r=0;
#asm ("cli"); 
if (w1_reset()==0)
    {
    w1_send(0xcc);  // пропустить ром
    w1_send(0x44);  // посылаем команду старта преобразования      
    };
    delay_ms(95); // ждем пока идет преобразование; 
if (w1_reset()==0) // если на шине есть откликнувшееся устройство то продолжаем
    {
    w1_send(0x55); // обратиться по ром коду                             
    w1_writerom(DSnum);   // выдаем ром код выбранного датчика на шину
    w1_send(0xbe);             // считать память
    // температура хранится в двух байт и младший разряд целой составляющей 
    // расположен в 5ом бите первого байта
    r=(w1_readbyte() > > 4); // поэтому сдвигаем в право на 4 бита     
    r=r+ (w1_readbyte() < < 4);   // и добавляем 4 бита из второго байта
    w1_reset(); // по правилам DS'ки прервать дальнейшее чтение стоит командой RESET  
    };
#asm ("sei");
return (char) r;
};

функция возвращает целое значение температуры, если она была положительная и 0 если были ошибки при чтении.

Файлы

Даташит на DS18B20: 🎁 DS18B20.pdf  528.7 Kb ⇣ 79

Многие моменты, например, использование команды «SEARCH ROM» — поиск устройств на шине, или чтение температуры с большей точностью я не осветил потому, что такой необходимости у меня не было. Надеюсь моя работа окажется для кого-то полезной.

Спасибо за внимание!

Камрад, рассмотри датагорские рекомендации

🌼 Полезные и проверенные железяки, можно брать

Опробовано в лаборатории редакции или читателями.




 

Читательское голосование

Нравится

Статью одобрили 42 читателя.

Для участия в голосовании зарегистрируйтесь и войдите на сайт с вашими логином и паролем.
 

Поделись с друзьями!

 

 

Связанные материалы

 

Схема на Датагоре. Новая статья Программная реализация протокола SPI на AVR в CodeVisionAVR... Всем коллегам и согражданам привет! Увлёкся я изучением протоколов. Про реализацию протокола I2C у...
Схема на Датагоре. Новая статья Несколько функций для програмной реализации протокола I2C на AVR... Добрый день, дорогие друзья! Решил поделиться с вами несколькими функция для работы по протоколу...
Схема на Датагоре. Новая статья Визуализация для микроконтроллера. Часть 4. Android... Вообще то я планировал рассказать сегодня про дисплей на базе ILI9481. Однако, он настолько похож...
Схема на Датагоре. Новая статья USB адаптер для чтения и программирования цифровых термостатов MAXIM/DALLAS DS1821... В статье описано, как за час сделать простой USB-адаптер для чтения/записи цифровых термометров...
Схема на Датагоре. Новая статья Работа с датчиком DHT11. Строим термометр-гигрометр на ATMEGA8... Привет любителям электроники! Сегодня я решил познакомиться с датчиком влажности DHT11, который...
Схема на Датагоре. Новая статья Универсальный контроллер управления 7-сегментными LED индикаторами по двум проводам (Atmega16)... Занялся я конструированием нового устройства и встал вопрос — на чем отображать данные....
Схема на Датагоре. Новая статья Простой цифровой термометр на ATmega8535 + DS18B20... Доброго времени суток! Представляю простой, цифровой термометр на индикаторе ИЖЦ21-4/7,...
Схема на Датагоре. Новая статья Программная реализация протокола I2C на AVR в CodeVisionAVR... Пару лет назад, изучая Atmega8, я захотел программно реализовать работу с устройствами на шине...
Схема на Датагоре. Новая статья Arduino shield: акселерометр на LIS302DL... Собрал недавно arduino на atmega8, поморгал диодом, захотелось большего. Начал изучать различные...
Схема на Датагоре. Новая статья Texas Instruments. Руководство по выбору компонентов для аналоговых схем... Операционные усилители, компараторы, буфферы, ЦАП/АЦП преобразователи данных, интерфейсы, схемы...
Схема на Датагоре. Новая статья 10 практических устройств на AVR-микроконтроллерах. Книга 1. А.В. Кравченко... 10 практических устройств на AVR-микроконтроллерах. Книга 1. А.В. Кравченко Издательство: Москва,...
Схема на Датагоре. Новая статья Грызём микроконтроллеры. Урок 4. Мерим температуру или напряжение... Мигалки – это хорошо, по новогоднему! Но ведь нельзя останавливаться на достигнутом! Пора сделать...
 

Комментарии, вопросы, ответы, дополнения, отзывы

 

Назад Вперед
<
Читатель Датагора

Spirit

<
Читатель Датагора

Alexverb

<
Читатель Датагора

2UnLiMiTeDD

<
Читатель Датагора

teXnik

<
Читатель Датагора

AudioKiller

<
Читатель Датагора

teXnik

<
Читатель Датагора

teXnik

<
Читатель Датагора

Spirit

<
Читатель Датагора

teXnik

<
Читатель Датагора

Spirit

<
Читатель Датагора

teXnik

<
Читатель Датагора

Spirit

<
Читатель Датагора

Chugunov

<
Читатель Датагора

Spirit

<
Читатель Датагора

teXnik

<
Читатель Датагора

Chugunov

Назад Вперед

Добавить комментарий, вопрос, отзыв 💬

Камрады, будьте дружелюбны, соблюдайте правила!

  • Смайлы и люди
    Животные и природа
    Еда и напитки
    Активность
    Путешествия и места
    Предметы
    Символы
    Флаги
 
 
В начало | Зарегистрироваться | Заказать наши киты почтой