1-Wire. Работа с DS18B20. Часть 3

19/02/2011 - 21:45

  Переходим от теории к практике. Наша задача — получить от датчика DS18B20 значение текущей температуры и вывести его на символьный lcd дисплей. 

 Схема

   Подключение DS18B20 к AVR
 

   Описание 1-Wire библиотеки

   Для работы с DS18B20 мы будем использовать слегка подправленную 1-Wire библиотеку из  аппноута AVR318. Эта библиотека интересна тем, что она не «заточена» под конкретные однопроводные устройства и предоставляет пользователю два варианта реализации 1-Wire протокола — программную и аппаратную. Программную реализацию можно использовать с любым микроконтроллером, аппаратную — только с тем, у которого есть в составе модуль UART/USART. В этой статье разобрана работа с программной реализацией 1-Wire протокола. 
 
   Давайте вкратце пробежимся по структуре этой 1-Wire библиотеки.  
 
OWISWBitFunction.h, OWISWBitFunction.c, OWIUARTBitFunction.c — в этих модулях описаны низкоуровневые функции -  функция инициализации, функции записи 0 и 1, функция чтения 1-Wire шины и функция детектирования отклика 1-Wire устройств.     
   Заголовочный файл один, а сишный файлов два — один для программной, другой для   аппаратной реализации протокола.  
 
OWIHighLevelFunction.h, OWIHighLevelFunction.с — в этом модуле описаны высокоуровневые функции (это и так понятно из названия) — функции записи команд, функция чтения данных, функция поиска 1-Wire устройств на шине.  
 
OWIPolled.h — конфигурационный файл 1-Wire библиотеки. В нем задается вариант реализации протокола, тактовая частота микроконтроллера, порт, к которому подключена 1-Wire шина, а также настройки UART/USART модуля. 
 
compilers.h — файл, обеспечивающий совместимость библиотеки с любым из трех компиляторов: IAR AVR, GNU GCC (WinAVR), CodeVision AVR. 
 
OWIdefs.h — общие определения, используемые в обоих реализациях. Определения ROM команд, возвращаемых функциями кодов и UART/USART паттернов. 
 
OWIdevicespecific.h — специфические определения для аппаратной реализации. Имена  битов и регистров UART/USART модулей AVR микроконтроллеров.
 
OWIcrc.h, OWIcrc.c — модуль, в котором содержатся функции вычисления циклического  избыточного кода. 
 
   Файлы библиотеки хорошо прокомментированы и если вы немного знаете английский, то без труда разберетесь с назначением всех функций. 

   Подключение 1-Wire библиотеки

  Чтобы мы могли использовать 1-Wire библиотеку, ее нужно подключить к проекту и настроить. Подключение библиотеки к IAR `овскому проекту состоит из следующих шагов: 
 
1. Переписываем все файлы библиотеки в папку проекта
 
2. Подключаем сишные файлы к проекту
OWIHighFunction.c
OWISWBitFunction.c
OWIUARTBitFunction.c
OWIcrc.c
 
3. Включаем заголовочные файлы в main.c
#include "OWIPolled.h"
#include "OWIHighLevelFunctions.h"
#include "OWIBitFunctions.h"
#include "common_files\OWIcrc.h"
 
4. Настраиваем конфигурационный файл OWIPolled.h
 
-  задаем программную реализацию 1-Wire протокола
       #define     OWI_SOFTWARE_DRIVER    
 
-  устанавливаем тактовую частоту микроконтроллера
       #define     CPU_FREQUENCY   16.000
 
- задаем порт, к которому подключена 1-Wire шина
       #define     OWI_PORT      PORTD //!< 1-Wire PORT Data register
       #define     OWI_PIN         PIND    //!< 1-Wire Input pin register
       #define     OWI_DDR        DDRD    //!< 1-Wire Data direction register
 
5.  В main.c задаем вывод, к которому подключена OneWire шина
      #define BUS   OWI_PIN_7
 
   Точно так же подключается библиотека и в CodeVision AVR и в WINAVR. Только для WINAVR нужно добавить в makefile пути к сишным файлам. Вот так:
   
SRC = $(TARGET).c OWISWBitFunctions.c OWIHighLevelFunctions.c  OWIUARTBitFunctions.c  common_files/OWIcrc.c

   Работа с DS18B20. Получение температуры

   В принципе, для работы с одним датчиком DS18B20 достаточно трех функций:
 
unsigned char OWI_DetectPresence(unsigned char pins)

Назначение: подает сигнал сброса и считывает ответ датчика DS18B20. 
Принимает: пин, к которому подключена шина
Возвращает: 1, если датчик не ответил и 0, если датчик сформировал на шине импульс присутствия.  
 
void OWI_SendByte(unsigned char data, unsigned char pin) 

Назначение: передает датчику команду или данные 
Принимает: байт данных и пин, к которому подключена шина
Возвращает: нет. 
 
unsigned char OWI_ReceiveByte(unsigned char pin)

Назначение: принимает от датчика байт данных
Принимает: пин, к которому подключена шина
Возвращает: принятый байт данных.
 
   Да, чуть не забыл, в начале функции main нужно еще однократно вызвать функцию  
void OWI_Init(unsigned char pin).
 
   Чтобы получить от датчика DS18B20 значение текущей температуры микроконтроллер должен послать датчику команду запуск температурного преобразования - CONVERT_T, выдержать паузу, послать команду чтения ОЗУ - READ_SCRATCHPAD и принять 9 байт.
   Температурное разрешение датчика менять не будем. По умолчанию оно 12-ти разрядное, а значит время преобразования будет равно одной секунде. 
   Фрагмент кода, реализующий описанную последовательность, представлен ниже.
 
#define DS18B20_SKIP_ROM                   0xcc
#define DS18B20_CONVERT_T                0x44
#define DS18B20_READ_SCRATCHPAD     0xbe
 
//буфер для хранения ОЗУ датчика
unsigned char scratchpad[9]
 
unsigned int main(void)
{
    OWI_Init(BUS);
    
    /*подаем сигнал сброса,
    команду для адресации всех устройств на шине
    и команду запуcк преобразования */
    OWI_DetectPresence(BUS);
    OWI_SendByte(DS18B20_SKIP_ROM ,BUS);
    OWI_SendByte(DS18B20_CONVERT_T ,BUS);
    
   /*ждем, когда датчик завершит преобразование   
   прогр. задержка длительностью 1 сек при Fcpu=16МГц*/
    __delay_cycles(16000000);
   
     /*подаем сигнал сброса
    команду для адресации всех устройств на шине и 
    команду чтение внутренней памяти
    затем считываем первые два байта*/
    OWI_DetectPresence(BUS);
    OWI_SendByte(DS18B20_SKIP_ROM, BUS);
    OWI_SendByte(DS18B20_READ_SCRATCHPAD, BUS);
    
    /*чтение ОЗУ датчика*/
    for(unsigned char i = 0; i<9; i++){
      scratchpad[i] = OWI_ReceiveByte(BUS);
    }
 
    Заметьте, из-за того, что мы работаем только с одним датчиком, отпадает необходимость в его адресации и «обращения» к нему выполняются с помощью команды SKIP_ROM.
   
   Этот код можно слегка улучшить. 
  Поскольку команда SKIP_ROM является общей для всех 1-Wire устройств, в библиотеке определена функция для ее подачи void OWI_SkipRom(unsigned char pin). 
  Если датчик DS18B20 работает от внешнего источника питания, то после запуска температурного преобразования можно отслеживать, когда оно будет выполнено. Для этого микроконтроллер должен формировать на шине тайм слоты чтения и ждать, когда датчик ответит ему единицей. 
  Также можно ограничиться чтением первых двух байт ОЗУ, если остальное содержимое памяти датчика не представляет для нас интерес. 
   
    /*подаем сигнал сброса,
    команду для адресации всех устройств на шине
    и команду запуcк преобразования */
    OWI_DetectPresence(BUS);
    OWI_SkipRom(BUS);
    OWI_SendByte(DS18B20_CONVERT_T ,BUS);
 
    /*ждем, когда датчик завершит преобразование*/ 
    while (!OWI_ReadBit(BUS));
   
   /*подаем сигнал сброса
    команду для адресации всех устройств на шине и 
    команду чтение внутренней памяти
    затем считываем первые два байта*/
    OWI_DetectPresence(BUS);
    OWI_SkipRom(BUS);
    OWI_SendByte(DS18B20_READ_SCRATCHPAD, BUS);
  
    /*чтение ОЗУ датчика*/
    scratchpad[0] = OWI_ReceiveByte(BUS);
    scratchpad[1] = OWI_ReceiveByte(BUS);   
 

   Работа с DS18B20. Вывод температуры на дисплей

   Первые два байта ОЗУ датчика имеют следующий формат. 
Формат первых двух байт ОЗУ датчика DS18B20        
где S – знак температуры (0 – положительная температура, 1 – отрицательная), BIT10–BIT4 -  целая часть значения температуры, BIT3-BIT0 – дробная часть. 
 
  Вывод значения температуры на дисплей состоит из следующих шагов:
 
1.  Определяем знак температуры и отображаем его на дисплее
Для работы с символьным дисплеем можно использовать библиотеку lcd_lib или любую другую. 
    
   LCD_Goto(5,0);            //устанавливаем курсор в нужное место
    if ((scratchpad[1]&128) == 0){   //проверяем старший разряд 
      LCD_WriteData('+');
    }
    else{
      LCD_WriteData('-');
      …..
    }
 
2. Если значение температуры отрицательное, преобразуем его в положительное
   В DS18B20 для представления отрицательной температуры используется дополнительный код. Особенность этого кода заключается в том, что он позволяет осуществлять операции вычитания через сложение. Чтобы получить дополнительный код числа, нужно выполнить над числом поразрядную инверсию (~) и прибавить к результату единицу. 
     
      tmp = ~tmp + 1; 
 
   Для преобразования отрицательного числа в положительное нужно выполнить операцию логического отрицания. Для чисел представленных в дополнительном коде эта операция заключается в получении … дополнительного кода числа. Да, да, именно так.      
 
      unsigned int tmp;
      …
      // «склеиваем» нулевой и первый байты ОЗУ датчика
      tmp = ((unsigned int)scratchpad[1]<<8)|scratchpad[0]; 
      
      //выполняем операцию логического отрицания
      tmp = ~tmp + 1;  
 
      //помещаем результат в соответствующие переменные
      scratchpad[0] = tmp;
      scratchpad[1] = tmp>>8;  
 
3.  Выделяем с помощью битовых масок целую часть температуры, переводим  в символы и отображаем на дисплее. 
   Чтобы перевести оцифрованное значение температуры в градусы, нужно это значение умножить на вес младшего разряда. Для целой части температуры вес младшего разряда (BIT4) равен 1 градусу Целься, а значит умножать ничего не нужно.        
    Для перевода целых чисел в символы можно использовать функцию void BCD_3Lcd(unsigned char temp) из библиотеки bcd. Принцип работы функции крайне простой - из переданного ей  числа многократно вычитается сначала 100, затем 10. Колличество вычитаний и оставшееся после этих операций число, переводится в символы и выводится на дисплей с помощью void LCD_WriteData(char data). 
 
    temperature = ((scratchpad[1]&7)<<4)|(scratchpad[0]>>4);
    BCD_3Lcd(temperature);
 
4. Выделяем дробную часть, преобразуем дробную часть в целую, переводим  в символы и отображаем на дисплее. 
    Для перевода дробной части температуры в градусы, нужно умножить ее значение на 0,0625. Это вес разряда BIT0.
    Если выполнять эту операцию "в лоб", нам придется связываться с переменными типа float, а это довольно затратно с точки зрения объема кода. Домножим предварительно дробную часть температуры на 10, чтобы этого избежать. 
   
    //выделяем с помощью битовой маски дробную часть
    temperature = (scratchpad[0]&15);
    
    //преобразуем в целое число
    temperature = (temperature<<1) + (temperature<<3);// Умножаем на 10
    temperature = (temperature>>4);//делим на 16 или умножаем на 0.0625  
    
    //выводим на дисплей
    LCD_WriteData('.');
    BCD_1Lcd(temperature);  

   Этот код выведет на дисплей один знак после запятой.  

   Конечно, это не единственный способ отобразить значение температуры на дисплее, но он довольно простой с точки зрения понимания и кода. На этом все. Полный код смотрите в архивах проектов. 

   Файлы

Проект для IAR AVR — работа с одним датчиком DS18B20
Проект для WINAVR
Проект для CodeVision AVR
Проект для AVR Studio 4

   С Протеусом у меня возникли некоторые проблемы - проекты для IAR и WINAVR работали только при тактовой частоте микроконтроллера 8МГц. Выкладываю на всякий случай, может кто-нибудь объяснит мне в чем дело.

Проект для Proteus

  В железе никаких проблем не было, все работало как часы.  

Comments   

# foxit 2011-02-22 04:23
Спасибо. Буду разбираться.

А как работать с несколькими датчиками?
# Pashgan 2011-02-23 13:48
Об этом в следующей части.
Нужно выполнить процедуру поиска 1-Wire устройств. А затем обращаться к найденным устройствам с помощью их адреса.
# dma 2011-02-22 16:06
Спасибо автору за данный материал ! Только начал учить WinAVR. Помогают твои статьи. Спасибо!
# Pashgan 2011-02-23 13:50
Пожалуйста
# dma 2011-02-22 21:06
Уважаемый, Pashgan ! Хочу похвалиться, благодаря Вам написал и спял за два дня на WinAVR цифровой термометр на 4-х разрядном семисегментном индикаторе. Раньше использовал BascomAVR. Быстро пишется - долго отлаживается, работает само по себе. Плюнул на этот черный ящик, перешел на Си. Планируете ли Вы в ближайшее время рассмотреть также доступно (как с 1-wire)работу с i^2c (в частности ds1307 - часами реального времени)? Или хотя бы наведите на цель..я начинающий в WinAVR. Из удобных вещей Bascom AVR остались несколько - удобная работа с RC5 протоколом (функции RC5send, getRc5command. Привык к беспроводному управлению устройствами без кнопок и тд. Имеется ли альтернатива в Си ? Думаю эта тема очень актуальна на Вашем сайте. Еже раз спасибо за разжеванный теоретический материал.
# foxit 2011-02-22 21:25
Quoting dma:
написал и спял за два дня на WinAVR цифровой термометр на 4-х разрядном семисегментном индикаторе.


А можно увидеть код и реализацию?
# dma 2011-02-23 16:24
Quoting foxit:
Quoting dma:
написал и спял за два дня на WinAVR цифровой термометр на 4-х разрядном семисегментном индикаторе.


А можно увидеть код и реализацию?


Дай свое мыло сброшу проект.
# Pashgan 2011-02-23 13:50
Это радует. Значит не зря материал делал.
Quote:
Планируете ли Вы в ближайшее время рассмотреть также доступно (как с 1-wire)работу с i^2c (в частности ds1307 - часами реального времени)?
Честно скажу - не знаю.
# foxit 2011-02-23 16:37
Quoting dma:
Quoting foxit:
Quoting dma:
написал и спял за два дня на WinAVR цифровой термометр на 4-х разрядном семисегментном индикаторе.


А можно увидеть код и реализацию?


Дай свое мыло сброшу проект.


foxit[собака]ga la.net
# Viaceskav(C) 2011-02-23 21:28
Ух как раз собираюсь делать термометр с датчиком DS18B20 :-)

кстати проверил в протеусе - эмуляция работает на отлично (версия 7.7 sp2)
# Pashgan 2011-02-24 22:25
У меня тоже работает, но только при тактовой частоте в 8 МГц. А проект заточен под 16 МГц.
# САБ 2011-02-24 12:09
Quote:
Чтобы получить дополнительный код числа, нужно выполнить над числом поразрядную инверсию (~) и прибавить к результату единицу. tmp = ~tmp + 1; Для преобразования отрицательного числа в положительное нужно выполнить операцию логического отрицания.
Какая-то ерунда написана. Наверное "чтобы получить отрицательное число в дополнительном коде из положительного. .." Во второй части насчет логического отрицания написано то же самое, что в первой, но забыто про прибавление единицы.
Что помешало в коде сделать tmp = -tmp;?
# Pashgan 2011-02-24 22:27
Почему ерунда? По моему все логично и последовательно .
Quote:
В DS18B20 для представления отрицательной температуры используется дополнительный код. Особенность этого кода заключается в том, что он позволяет осуществлять операции вычитания через сложение. Чтобы получить дополнительный код числа, нужно выполнить над числом поразрядную инверсию (~) и прибавить к результату единицу.

tmp = ~tmp + 1;

Для преобразования отрицательного числа в положительное нужно выполнить операцию логического отрицания. Для чисел представленных в дополнительном коде эта операция заключается в получении … дополнительного кода числа.
Quote:
Что помешало в коде сделать tmp = -tmp;
Помешало низкоуровневое мышление.. мне просто не пришло это в голову.
# Netouch 2012-01-17 13:25
Но ведь tmp - unsigned int.
разве tmp = -tmp в таком случае корретная запись?
# Viaceskav(C) 2011-02-25 15:04
а как переделать под Atmega8?
может ли автор по быстрому пробежаться по коду и заточить под Atmega8? :-)
благодарность моя не имела бы границ :-)
# Viaceskav(C) 2011-02-25 19:08
просьба снимается :-)
переделал сам...
посадил на порт D вывод на лсд
датчик тоже на D, на 0 пин
Порт С перекинул на младшие биты
# Вадим 2011-02-27 19:32
А зачем нужен диод D3 на схеме?
# JoJo 2011-02-27 19:57
Для быстрой разрядки кодера C1 при выключении питания
# dma 2011-03-03 11:36
А как можно было бы оптимизировать код чтения температуры, чтобы при динамической индикации время от времени чуть заметно не моргали цифры(думаю это эффект от запрета прерываний в функции OWIDETECT или задежек на чтение в библиотеке RTC1307) ?
# Pashgan 2011-03-03 12:47
Сходу не могу сказать, нужно сначало точно выяснить, что мешает индикации. Отключи работу с RTC1307 и посмотри, что будет.
# dma 2011-03-03 11:38
Pashgan, ожидается ли часть 4 ?
# Pashgan 2011-03-03 12:32
Ожидается, только не знаю когда. Вдохновение нужно поймать.
# Viaceskav(C) 2011-03-03 20:23
подкючил ЖКИ GDM1601C на процессоре S6A0069

но почему то показывает только восемь первых символов...

в чем может быть проблема?

может необходимо что то переделать в коде под этот ЖКИ?
# dma 2011-03-04 22:46
подключил два датчика DS18B20, хочу работать с каждым по отдельности, для этого пытаюсь считать их адреса в unsigned char serial[8];:
OWI_SearchRom(serial, lastDeviation, BUS);
if (OWI_ROM_SEARCH _FINISHED ==0x00)
{вывод на семисегментник последовательно сти 8 байт датчика}

Получаю на выходе для 1-го датчика: 40 06 35 7 01 00 00 0
где 40 = family code Ds18b20= 0x28h.
запускаю повторно функцию и получаю нули. В чем может быть проблема. Помогите пожалуйста в последовательно сти действий. Если я правильно понял, мне нужно после Init прочитать адреса каждого из датчиков и работать по matchrom последовательно (читать темпер. с датчика вначале дома и потом со второго на улице)? Запутался.
# Pashgan 2011-03-05 06:12
Посмотри как сделал я.
http://www.chipenable.ru/index.php/files-for-lessons-iar-avr/13-files-for-lessons/132-1-wire-2-datchika-ds18b20-iar-avr.html
# dma 2011-03-05 13:03
Спасибо, Pashgan. разобрался благодаря твоему примеру!
Подскажи увеличит ли скорость попеременного чтения двух датчиков изменение значения Thermometer Resolution Configuration

0 0 9 93.75ms (tCONV/8)
0 1 10 187.5ms (tCONV/4)
1 0 11 375ms (tCONV/2)
1 1 12 750ms (tCONV)
И как его менять, через OWI_SendByte(DS 18B20_READ_SCRA TCHPAD, BUS); ?
# Pashgan 2011-03-06 21:50
Да, увеличит. Чем меньше разрешение - тем меньше время преобразования
Code:
#define RES_9BIT 0x1f
#define RES_10BIT 0x3f
#define RES_11BIT 0x5f
#define RES_12BIT 0x7f

#define DS18B20_WRITE_SCRATCHPAD 0x4e
...
//подаем команду
OWI_SendByte(DS18B20_WRITE_SCRATCHPAD, BUS);

//передаем Th, Tl и конфигурационный регистр
OWI_SendByte(0, BUS);
OWI_SendByte(0, BUS);
OWI_SendByte(RES_9BIT, BUS);
# foxit 2011-07-02 16:42
Quoting Pashgan:
Посмотри как сделал я.
http://www.chipenable.ru/index.php/files-for-lessons-iar-avr/13-files-for-lessons/132-1-wire-2-datchika-ds18b20-iar-avr.html

А есть данный пример для winavr?
# Viaceskav(C) 2011-03-05 09:20
Pashgan ну а что по моему вопросу насчет половины вывода?
как вы думаете, что может быть?
# Pashgan 2011-03-05 11:53
Я посмотрел описание на твой дисплей и WH1602 и понял в чем дело. У WH1602 адрес первой строки 0х00, второй 0х40. У GDM1601C адрес 0-ого символа первой строки 0х00, адрес 8-ого символа первой строки 0x40. Нужно переделать код lcd_lib или использовать старую библиотеку так:
Code:
//вывод в первые 8 символов строки
LCD_Goto(0,0);
....
//вывод во вторые 8 символов строки
LCD_Goto(0,1);
....
# Viaceskav(C) 2011-03-05 14:54
огромное спасибо за затраченное время для меня :-)
сейчас попробую переделать....
правда не знаю как и где... :lol:
# uuu 2011-03-08 11:29
какая версия вашего IAR?
# Pashgan 2011-03-08 12:14
5.11
# uuu 2011-03-09 13:14
Не могу найти где в IAR настраивается модель контроллера.
# Viaceskav(C) 2011-03-09 17:32
самая самая верхняя строчка, на название проекта нажимай правой кнопкой мыши и выбирай options.
# uuu 2011-03-09 19:11
спасибо
# Vovan 2011-03-11 12:29
Вот и мне понадобилось работать с этим датчиком. Прочитал все 3 статьи, вроде бы всё оч просто. Скачал пример программы запустил в протеусе работает. Решил немного переделать программу чтоб значение температуры в ЮАРТ приходило т.е отправляю
scratchpad[0] и scratchpad[1] через ЮАРТ и приходят оба байта FF. В чём может быть причина? Помогите подалуйста
# Pashgan 2011-03-11 12:47
Для начала проверь отдельно работу UARTа. Вместо scratchpad передай какие-нибудь два известных тебе значения.
# Vovan 2011-03-11 17:21
Pashgan юарт работает отлично, посылал значения всё ок. Есть ли какие то методы, способы, приёмы отладки 1-Wire? как найти в чём бок? За рание спасибо.
# нечто 2011-03-11 21:41
здесь как-нибудь можно выложить файл? хочу поделиться своим вариантом функции вывода целого числа (той что в bcd.c)
зщ: по большому счету, можно использовать sprintf(), если не жалко 4кб
# JoJo 2011-03-11 21:52
На форум выкладывай
# wog39 2011-03-12 07:24
для чего нужна строка в OWIPolled.h
"OWI_DELAY_OFFSET_CYCLES 13" ?
дело в том, что у меня не выводилась температура, на экране все время было "Temp:- 0", наугад заменил в этой строке 13 на 0 и начало нормально показывать температуру.
# wog39 2011-03-12 08:18
хотя... я погорячился. это походу был прикол протеуса, потому что в живую наоборот, работает при 13
# lamana 2011-08-29 19:40
Quoting wog39:

дело в том, что у меня не выводилась температура, на экране все время было "Temp:- 0", наугад заменил в этой строке 13 на 0 и начало нормально показывать температуру.

Quoting wog39:
для чего нужна строка в OWIPolled.h
"OWI_DELAY_OFFSET_CYCLES 13" ?
дело в том, что у меня не выводилась температура, на экране все время было "Temp:- 0", наугад заменил в этой строке 13 на 0 и начало нормально показывать температуру.

А у меня собран термометр на Atmega16,датчик и дисплей подключены к порту A, и на экране появляется только строка "Temp:- 0.0" (в случае 1 датчика) и "Sensors not not 0 "(в случае 2х датчиков). В чем может быть проблема???
# Viaceskav(C) 2011-03-12 18:53
а меня бесит немного, когда температура доходит до 35 (при замере темп. тела) а потом по чуть-чуть двигается дальше...

хочется, чтоб сразу показывало температуру :-)
# Валентин 2011-03-13 17:53
Сделайте свой вариант и предъявите пожалуйста, будем только рады.
# Viaceskav(C) 2011-03-13 20:21
я к тому, что чувствительност ь датчика маловата.
# XANDER 2011-03-22 14:05
На страничке "DS18X20 with AVR" от Martin Thomas находится отличная библиотека работы с 1-Wire: http://www.siwawi.arubi.uni-kl.de/avr_projects/tempsensor/index.html
(паразитное питание для 1-Wire устройств работает без 8) вспомогательног о транзистора, прямо с ноги МК!)

Имхо удобней и проще работать чем с библиотекой 1-Wire из аппноута AVR318.
# Viaceskav(C) 2011-03-26 15:56
никак не могу подключить жки от нокиа3310 :cry:
примеры брал из примеров с этого сайта.
слепил все вместе, но почему то не работает...
может можно примерчик накидать? автору то раз плюнуть, ну а моей благодарности не будет предела :-) да и многим будет интересно...
что то у меня никак не получается :-?
# Viaceskav(C) 2011-03-26 22:57
вопрос снимается, добил я код 8)
осталось анимацию в спрайтах сделать.
# serg602009 2011-04-08 14:31
Очень интересная статья. Спасибо.
Вопрос: хочу подключить 3 датчика к трем пинам, чтобы точно знать где какой находится. Достаточно ли просто переопределить пин, сначала
#define BUS OWI_PIN_7 , потом -
#define BUS OWI_PIN_6 и т.д.?
# Kalyan 2011-04-08 21:37
Добрый вечер! Пытаюсь поднять датчик по описанию. Вот код : while (1)
{

OWI_DetectPrese nce(BUS);
OWI_SendByte(DS 18B20_SKIP_ROM ,BUS);
OWI_SendByte(DS 18B20_CONVERT_T ,BUS);

__delay_cycles( 16000000);

OWI_DetectPrese nce(BUS);
OWI_SendByte(DS 18B20_SKIP_ROM ,BUS);
OWI_SendByte(DS 18B20_READ_SCRA TCHPAD, BUS);

for(i = 0; i
# Kalyan 2011-04-08 21:46
В общем все как в примере. :roll: На индикацию вывожу два младших байта (те шо с температурой). Проверяю в протеусе. И вот при фиксированной температуре их значения изменяются :cry: Сначала 0хFF, а потом вообще какие то произвольные значения! Может кто-то знает как с этим бороться??
# ooogo 2011-05-21 07:46
я конечно не спец, но по моему функция
unsigned char OWI_DetectPrese nce(unsigned char pins)
возвращает 0, если датчик не ответил и 1, если датчик сформировал на шине импульс присутствия, потому как по другому не отвечает.
вырезка из файла OWISWBitFunctio ns.c
Quote:
unsigned char OWI_DetectPrese nce(unsigned char pins)
{
unsigned char intState;
unsigned char presenceDetecte d;

// Disable interrupts.
intState = __save_interrupt();
__disable_interrupt();

// Drive bus low and delay.
OWI_PULL_BUS_LOW(pins);
__delay_cycles(OWI_DELAY_H_STD_MODE);

// Release bus and delay.
OWI_RELEASE_BUS(pins);
__delay_cycles(OWI_DELAY_I_STD_MODE);

// Sample bus to detect presence signal and delay.
presenceDetecte d = ((~OWI_PIN) & pins);
__delay_cycles(OWI_DELAY_J_STD_MODE);

// Restore interrupts.
__restore_interrupt(intState);

return presenceDetecte d;
}
в строке presenceDetecte d = ((~OWI_PIN) & pins); стоит инверсия
# ooogo 2011-05-21 07:53
загнался все правильно 1, если датчик не ответил и 0, если датчик сформировал на шине импульс присутствия, но почему у меня не работает не знаю!? :-?
# ooogo 2011-05-21 08:01
Точно загнался, макроопределение
#define OWI_PIN PIND //!< 1-Wire Input pin register.
pins входная переменная номер порта, значит 0, если датчик не ответил и 1, если датчик сформировал на шине импульс присутствия. извините, что так много написал. :-*
# Ivan 2011-05-25 16:21
Вопрос, а в чем будут отличия если использовать датчики DS1820 или аналог DS18S20
# stolyars 2011-06-08 16:27
У кого есть переделка под Атмегу8 и проект в протеусе для нее скинте в любой обменник пожалуйста или выложите сдесь(WinAVR)
# londo 2011-06-12 08:35
А как подсчитывается контрольная сумма?
# Valia 2011-08-09 12:46
подскажите пожалуйста, а как увеличить количество знаков после запятой (один знак мало)
# Джо 2011-09-11 10:22
Жаль на асме нет кода :-)
# Владимир Андреевич 2012-10-07 18:38
if ((scratchpad[1] &128) == 0){ //проверяем старший разряд

(scratchpad[1]& 128) у меня всегда = 128, ребята, что делать? Соответственно всегда минус и то число, что считается после, выводится как Quote:
||
на дисплей.
Зачем вообще Quote:
&128
?
# Владимир Андреевич 2012-10-07 20:43
Quoting Владимир Андреевич:
if ((scratchpad[1]&128) == 0){ //проверяем старший разряд


(scratchpad[1]&128) у меня всегда = 128, ребята, что делать? Соответственно всегда минус и то число, что считается после, выводится как Quote:
||
на дисплей.
Зачем вообще Quote:
&128
?
Я понял почти все, кроме того что мне почему то приходят ms ls байты равные 11111111
# Pashgan 2012-10-08 20:48
Владимир, попробуй подключить другой датчик. Может быть этот испортился.
# bohdan4ik13 2012-11-11 14:16
Огромнейшее спасибо за наглядный пример.
# zadorand 2012-11-24 06:16
Как я понял, при переводе значения температуры в дополнительный код, считываем старшибайт,сдви гая на 8бит влево, затем "приписываем" младший байт, проводим поразрядную инверсию и добавляем единицу. Так?
# Pashgan 2012-11-24 11:48
да
# zadorand 2012-11-24 06:27
при чтении озу датчика сначала считывается младший байт, а затем старший?

при появлении нового значения температуры,так же сначала младший, затем старший.
не может появиться ситуация, когда младший байт от нового значения температуры, старший от предыдущего?
# Pashgan 2012-11-24 11:53
Не знаю. На этот вопрос может ответить только производитель датчика. Думаю, что нет.
В любом случае последний байт ОЗУ содержит контрольную сумму и по ней всегда можно проверить содержимое ОЗУ.
# zadorand 2012-11-26 13:07
немного не понял перевод в символы для отображения на дисплее. выделяем целую часть значения температуры(в двоичном коде), а вот потом не понятно каким образом преобразовать в десятичный код выделить сотни, дясятки, единицы и отобразить на дисплее.
# zadorand 2012-11-30 16:50
Мне не совсем понятно. Например, получили от датчика значение 0000 0101 0101 0000, что соответствует +85 градусов. Выделяем целое значение температуры, получаем 1010101. А вот дальше не понятно. На дисплей мы выводим символы и надо выделить сотни, десятки и единицы, для чего делим, отбрасывая остаток, на 100 и 10 соответственно.
переменная у нас содержит двоичное число, 1010101%10 = ? как программа поступит? То ли результатом будит 101010(сто одна тысяча десять) , то ли двоичное число 0001000 (в десятичной СС 8). Может я туплю(Вы уж простите), но число в двоичной СС делим на число десятичной СС, что должно получиться?
# zadorand 2012-12-12 11:25
В OWIdefs.h есть строка
#include "compilers.h"
Не понимает AVR studio. Нет там такой библиотеки. Подскажите, пожалуйста.
# Pashgan 2012-12-18 19:47
Это не библиотека, это заголовочный файл для простого переноса проекта под три компилятора. В настройках AVR Studio нужно указать папку проекта. Я залил проект для AVR Studio 4, смотрите как сделано там.
# Дмитрий Д 2012-12-18 12:45
Quoting zadorand:
В OWIdefs.h есть строка
#include "compilers.h"
Не понимает AVR studio. Нет там такой библиотеки. Подскажите, пожалуйста.


У меня такая же проблема. Не могу даже скомпилить оригинал на WinAvr. Выдает ошибку:
compilers.h: No such file or directory OWIde fs.h 24 23 cher novik2
# Pashgan 2012-12-18 19:48
Я залил проект для AVR Studio 4, смотрите как сделано там.
# Дмитрий Д 2013-01-12 19:41
Прости конечно, но у меня даже скачав и открыв твой проект в содевизион не компилится. Ошибка в библиотеке лсд_либ! Сам пишу в авр стидио 6, и ошибку compilers.h: No such file or directory OWIde fs.h уже 3 день парю) ничто не помогает. И проект на 4 тоже такое же дает.
# Дмитрий Д 2013-01-13 10:13
Закоментировал строку compilers.h в файле OWIde fs.h . Срезу же скомпилил - не знаю во что это потом выльется.)
# Валерий 2012-12-27 09:29
!
# zadorand 2012-12-28 22:00
По поводу compilers.h Нашел свою ошибку.
прочиал комментарии в файле, убрал добавочные(анал огичные) строки для других компиляторов(IC CAVR,CODEVISION AVR). для avrstudio4 оставил:
#ifndef COMPILERS_H
#define COMPILERS_H

#include
#include
#include

#define __save_interrup t() SREG
#define __restore_inter rupt(var) SREG = (var)
#define __disable_inter rupt() cli()
#define __enable_interr upt() sei()
#define __delay_cycles( var) _delay_us((unsi gned int)(var)/(F_CPU/1000000))

#endif //COMPILERS_H
# IurriI 2013-01-27 10:58
В Протеусе, при отрицательных температурах, не верно отображаются десятые доли градуса. Это глюк модели? Кто-нибудь проверял на реальном устройстве?
Буду очень признателен, если кто ткнёт в нужном направлении.
# Pashgan 2013-01-27 20:34
Если будешь задавать там температуру кратно 0.0625 (это вес младшего разряда DS18b20), то все будет отображаться корректно.
# IurriI 2013-01-28 01:06
Pashgan, спасибо за оперативность. Задавал я и CurrentValue и Granularity кратными 0.0625 - без толку. Округляет до десятых в меньшую сторону.Значит такая модель... А у меня проект работает только на частоте 4МГц. :-| Надо осваивать JTAG.
# Pashgan 2013-01-28 04:21
Выведи на дисплей необработанное значение температуры с датчика и посмотри какие цифры он генерит.
Если ты используешь мой код, то там есть округление. Выводится только один знак после запятой, но он соответствует температуре датчика.
# IurriI 2013-01-28 22:26
Pashgan,в том то и дело, что вывожу необработанные данные вот таким образом
Code:
unsigned int mask = 0x8000;
while(mask)
{
if( tmp&mask )
lcd_data('1');
else
lcd_data('0');
mask >>= 1;
}

и получаю следующие значения для отрицательных температур:
Должно быть.. показания..... двоичный код
0,0 ............... ........0,0.... .......0000
-0.1........... ........... 0,0...........1 111
-0.2........... .......... -0.1........... 1101
-0.3........... .......... -0,3...... ....1011
-0,4........... .......... -0,3........... 1010
-0,5........... .......... -0,5........... 1000
-0,6........... .......... -0,5........... 0111
-0,7........... ...........-0,6 ...........1100
-0,8........... ...........-0,8 ...........0011
-0,9........... .......... -0,8...........0010
Получается, что после умножения отбрасываетcя всё, что справа от запятой. А надо округлять с учётом младшего разряда.
У меня код немножко другой, но я запускал твой проект и в Протеусе и в AVRStudio - та же байда. Потому и задал вопрос тут.
Что-то не пойму как форматировать на этом сайте текст...
# zoomerland 2013-02-08 11:06
Pashgan, писал вам ранее. Есть прогресс. После изменения OWI_DELAY_OFFSE T_CYCLES на 0 схема заработала в протеусе. Но на железе не хочет, ни в паразитном, ни в обычном исполнении :cry:
Посоветуйте куда копать, уже замучался.
# XanderEVG 2013-04-07 17:53
Code: temperature = (temperature<<1) + (temperature<<3);// Умножаем на 10

хитро. почему так?
# Pashgan 2013-04-07 19:32
Получается более компактный ассемблерный код на микроконтроллер ах без аппаратного умножителя.
# XanderEVG 2013-04-08 04:23
Да. По запаре я не сразу понял что
Code:temperature = (temperature<<1) + (temperature<<3);// Умножаем на 10
=
Code:temperature = temperature*2 + temperature*8;// Умножаем на 10
умножитель есть много где и сним короче на пару команд.
но наверно так можно и делить на 10? а это уже что то.
# Pashgan 2013-04-08 07:22
Делить так можно только на степени двойки (на 2, 4, 8, 16). На 10 сдвигами разделить не получится. Я по крайней мере не знаю, как это сделать.
Написав эту строчку, я в принципе никаких оптимизационных целей не преследовал. И сделал так скорее по старой привычке.
# Sergofan5 2013-05-04 09:28
Делаю проект контроллера для аквариума в Atmel Studio 6 - никак не получается прикрутить DS18B20 - ругается на compillers.h, и экран у меня nokia3310 не посоветуете что можно придумать????
# Сашка 2013-10-17 04:49
Такая проблемка: ругается на delay.h?, при компиляции сначала варнинг выдаёт:warning Code:"F_CPU not defined for <util/delay.h>",#define F_CPU 1000000UL продефайнено первой строчкой!!! потом 4 ошибки __builtin_avr_d elay_cycles expects an integer constant Судя по записям во вкладке Output ошибка вылазит ещё на стадии подключения библиотек. Другие библиотеки, использующие delay.h работают корректно. компилятор avr studio 5.1.208, пример для 4-й студии выдаёт те же ошибки. Может кто поможет разобраться через какое место работает эта студия? Спасибо.
# Pashgan 2013-10-17 08:51
F_CPU должен быть определен в Make файле
# angell 2013-12-11 16:51
Мужик! человеческой спасибо! с полпинка заработало!
# Pashgan 2013-12-11 23:09
Это радует.
# RONIN 2013-12-12 05:22
а как изменить температурное разрешение датчика??
# JoJo 2013-12-12 22:13
Подать команду write scratchpad, а затем передать три байта. Последний байт - значение конфигурационно го регистра. А он как раз устанавливает разрешение датчика.
# RONIN 2013-12-15 23:02
мне нужно реализовать термометр с шагом измерений 0,5 градуса на атмеге48. показания выводить на ПК через usart.как изменится код для AVR Studio??
# Pashgan 2013-12-17 09:30
Что значит как? Ну изменится. Нужно взять проект от этой статьи и прикрутить к нему USART драйвер/библиот еку.
# decibel 2014-02-15 11:09
Помогите пожалуста.
Вроде всё сделал как в Проекте для AVR Studio 4. Но выдаёт error:./OWIPoll ed.h:24:34: fatal error: common_files\OW Idefs.h: No such file or directory. Кидает в эту строку #include "common_files\O WIdefs.h" в файле OWIpolled.h. Почему не находит OWIdefs.h?
# _Артём_ 2014-02-16 15:21
Попробуйте так:
Code:
#include "..\common_files\OWIdefs.h"

или пропишите директорию в которой лежит OWIdefs.h в настройках проекта и тогда можно писать так:
Code:
#include "OWIdefs.h"
# decibel 2014-02-20 17:19
Разобрался, неправильна подключил библиотеку в Include Directories.
# KiberPank 2014-02-24 18:47
Спасибо за обзор библиотеки и протокола. Очень помог, за пару часов всё запустилось.
Еще добавить фенечек, чтобы не блокировало основную программу и будет шикарно) Сейчас этим и занимаюсь.
# shurf 2014-02-26 20:52
Прикрутил эту библиотеку без особых проблем, но когда читаю данные с датчика - датчик походу и не дрыгается - прут сплошные единички (Детект Пресенс показывает наличие датчика). Единички прут как в протеусе, так и в железе. Подскажите, куда копать?
# shurf 2014-02-28 18:12
Пошуршал в протеусе с логическим анализатором - почему-то все тайминги увеличены в три раза 0_о
# Pashgan 2014-03-18 19:56
Где-то неправильно задана тактовая частота. Эта библиотека многократно проверена.
# shurf 2014-03-18 20:00
Чертовщина какая-то. Ладно бы в 2, 4 или 1024 раза. А так - в три раза. Пробовал ставить разные частоты и делитель включать-выключ ать - то же самое, увеличивается в три раза(
# Pashgan 2014-03-18 20:03
Скинь rar архив проекта на форум (там есть ветка для временных проектов). Завтра попробую запустить у себя и напишу о результатах.
# Vinipuhh13 2014-05-24 12:44
Пытаюсь скомпилировать проект в Atmel Studio 6.
ошибка __builtin_avr_d elay_cycles expects a compile time integer constant, как я понял неправильно определяется версия компилятора и файл compilers.h не отрабатывается. что должно быть в этом файл только для AS6
# Roman1984 2014-07-08 02:32
Здравствуйте у меня вопрос: почему при запуске датчик кратковременно выводит значение +85, а затем начинает показывать нормально?
# IDHacker 2014-10-13 02:40
Потому что сначала надо запустить преобразование температуры. +85 это начальное значение температуры при подаче питания на датчик.
# IDHacker 2014-10-13 02:39
Статьи конечно познавательные, и библиотека для сборки градусников полезная. Но вот опять как у всех, нет внятных описаний алгоритмов работы. Ведь 1wire не такая уж сложная. Если подключать к UART всё складывается в отправку приём байтов. Как можно прикрутить чужую библиотеку когда в своей программе крутится пару таймеров и работает пяток прерываний. Совершенно невозможно представить временные интервалы.
Опять же не расписан формат данных температуры, одни конструкторы, со своими библиотеками. Надо алгоритмы описывать, а не пихать свои библиотеки, ещё и без внятного описания всех функций библиотеки.
# Ilya 2014-12-07 08:09
Подскажите код для вывода температуря через UART, для этого проекта.
# feekus 2014-12-18 08:07
при прошивке на ATMegs32 выдает на дисплее число +127,9 что это может быть и как можно исправить?
# Виктор 2015-01-30 16:31
У вас нет проекта в Atmel Studio??
# ASDFG123 2015-03-11 05:36
Code:#define RES_9BIT 0x1f
#define BUS OWI_PIN_0
#define DS18B20_CONVERT_T 0x44
#define DS18B20_READ_SCRATCHPAD 0xbe
#define DS18B20_WRITE_SCRATCHPAD 0x4e
unsigned char scratchpad[9];
unsigned char temperature;
......
void main( void )
{
OWI_SendByte(DS18B20_WRITE_SCRATCHPAD, BUS);
OWI_SendByte(0, BUS);
OWI_SendByte(0, BUS);
OWI_SendByte(RES_9BIT, BUS);
OWI_Init(BUS);
.....
while (1)
{
OWI_DetectPresence(BUS);
OWI_SkipRom(BUS);
OWI_SendByte(DS18B20_CONVERT_T ,BUS);
__delay_cycles(540000); //задержка 70мс
OWI_DetectPresence(BUS);
OWI_SkipRom(BUS);
OWI_SendByte(DS18B20_READ_SCRATCHPAD, BUS);

......
Подскажите пожалуйста, правильно я запускаю датчик в 9 битовом режиме ?
# Дмитрий_92 2016-06-28 19:38
Подскажите пожалуйста, как правильно собрать значение температуры в знаковую переменную с плавающей точкой, типа float, чтоб значение хранилось в одной переменной и дальше с ним можно было делать всякие математические операции. Ну или хотя-бы с фиксированной точкой, просто скажем signed int.

У вас недостаточно прав для комментирования.