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

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

Комментарии   

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

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


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


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


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


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


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


foxit[собака]ga la.net
Ответить | Ответить с цитатой | Цитировать
# Viaceskav(C) 23.02.2011 21:28
Ух как раз собираюсь делать термометр с датчиком DS18B20 :-)

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

tmp = ~tmp + 1;

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

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

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

может необходимо что то переделать в коде под этот ЖКИ?
Ответить | Ответить с цитатой | Цитировать
# dma 04.03.2011 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 05.03.2011 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 05.03.2011 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 06.03.2011 21:50
Да, увеличит. Чем меньше разрешение - тем меньше время преобразования
Код:
#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 02.07.2011 16:42
Цитирую 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) 05.03.2011 09:20
Pashgan ну а что по моему вопросу насчет половины вывода?
как вы думаете, что может быть?
Ответить | Ответить с цитатой | Цитировать
# Pashgan 05.03.2011 11:53
Я посмотрел описание на твой дисплей и WH1602 и понял в чем дело. У WH1602 адрес первой строки 0х00, второй 0х40. У GDM1601C адрес 0-ого символа первой строки 0х00, адрес 8-ого символа первой строки 0x40. Нужно переделать код lcd_lib или использовать старую библиотеку так:
Код:
//вывод в первые 8 символов строки
LCD_Goto(0,0);
....
//вывод во вторые 8 символов строки
LCD_Goto(0,1);
....
Ответить | Ответить с цитатой | Цитировать
# Viaceskav(C) 05.03.2011 14:54
огромное спасибо за затраченное время для меня :-)
сейчас попробую переделать....
правда не знаю как и где... :lol:
Ответить | Ответить с цитатой | Цитировать
# uuu 08.03.2011 11:29
какая версия вашего IAR?
Ответить | Ответить с цитатой | Цитировать
# uuu 09.03.2011 13:14
Не могу найти где в IAR настраивается модель контроллера.
Ответить | Ответить с цитатой | Цитировать
# Viaceskav(C) 09.03.2011 17:32
самая самая верхняя строчка, на название проекта нажимай правой кнопкой мыши и выбирай options.
Ответить | Ответить с цитатой | Цитировать
# Vovan 11.03.2011 12:29
Вот и мне понадобилось работать с этим датчиком. Прочитал все 3 статьи, вроде бы всё оч просто. Скачал пример программы запустил в протеусе работает. Решил немного переделать программу чтоб значение температуры в ЮАРТ приходило т.е отправляю
scratchpad[0] и scratchpad[1] через ЮАРТ и приходят оба байта FF. В чём может быть причина? Помогите подалуйста
Ответить | Ответить с цитатой | Цитировать
# Pashgan 11.03.2011 12:47
Для начала проверь отдельно работу UARTа. Вместо scratchpad передай какие-нибудь два известных тебе значения.
Ответить | Ответить с цитатой | Цитировать
# Vovan 11.03.2011 17:21
Pashgan юарт работает отлично, посылал значения всё ок. Есть ли какие то методы, способы, приёмы отладки 1-Wire? как найти в чём бок? За рание спасибо.
Ответить | Ответить с цитатой | Цитировать
# нечто 11.03.2011 21:41
здесь как-нибудь можно выложить файл? хочу поделиться своим вариантом функции вывода целого числа (той что в bcd.c)
зщ: по большому счету, можно использовать sprintf(), если не жалко 4кб
Ответить | Ответить с цитатой | Цитировать
# JoJo 11.03.2011 21:52
На форум выкладывай
Ответить | Ответить с цитатой | Цитировать
# wog39 12.03.2011 07:24
для чего нужна строка в OWIPolled.h
"OWI_DELAY_OFFSET_CYCLES 13" ?
дело в том, что у меня не выводилась температура, на экране все время было "Temp:- 0", наугад заменил в этой строке 13 на 0 и начало нормально показывать температуру.
Ответить | Ответить с цитатой | Цитировать
# wog39 12.03.2011 08:18
хотя... я погорячился. это походу был прикол протеуса, потому что в живую наоборот, работает при 13
Ответить | Ответить с цитатой | Цитировать
# lamana 29.08.2011 19:40
Цитирую wog39:

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

Цитирую 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) 12.03.2011 18:53
а меня бесит немного, когда температура доходит до 35 (при замере темп. тела) а потом по чуть-чуть двигается дальше...

хочется, чтоб сразу показывало температуру :-)
Ответить | Ответить с цитатой | Цитировать
# Валентин 13.03.2011 17:53
Сделайте свой вариант и предъявите пожалуйста, будем только рады.
Ответить | Ответить с цитатой | Цитировать
# Viaceskav(C) 13.03.2011 20:21
я к тому, что чувствительност ь датчика маловата.
Ответить | Ответить с цитатой | Цитировать
# XANDER 22.03.2011 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) 26.03.2011 15:56
никак не могу подключить жки от нокиа3310 :cry:
примеры брал из примеров с этого сайта.
слепил все вместе, но почему то не работает...
может можно примерчик накидать? автору то раз плюнуть, ну а моей благодарности не будет предела :-) да и многим будет интересно...
что то у меня никак не получается :-?
Ответить | Ответить с цитатой | Цитировать
# Viaceskav(C) 26.03.2011 22:57
вопрос снимается, добил я код 8)
осталось анимацию в спрайтах сделать.
Ответить | Ответить с цитатой | Цитировать
# serg602009 08.04.2011 14:31
Очень интересная статья. Спасибо.
Вопрос: хочу подключить 3 датчика к трем пинам, чтобы точно знать где какой находится. Достаточно ли просто переопределить пин, сначала
#define BUS OWI_PIN_7 , потом -
#define BUS OWI_PIN_6 и т.д.?
Ответить | Ответить с цитатой | Цитировать
# Kalyan 08.04.2011 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 08.04.2011 21:46
В общем все как в примере. :roll: На индикацию вывожу два младших байта (те шо с температурой). Проверяю в протеусе. И вот при фиксированной температуре их значения изменяются :cry: Сначала 0хFF, а потом вообще какие то произвольные значения! Может кто-то знает как с этим бороться??
Ответить | Ответить с цитатой | Цитировать
# ooogo 21.05.2011 07:46
я конечно не спец, но по моему функция
unsigned char OWI_DetectPrese nce(unsigned char pins)
возвращает 0, если датчик не ответил и 1, если датчик сформировал на шине импульс присутствия, потому как по другому не отвечает.
вырезка из файла OWISWBitFunctio ns.c
Цитата:
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 21.05.2011 07:53
загнался все правильно 1, если датчик не ответил и 0, если датчик сформировал на шине импульс присутствия, но почему у меня не работает не знаю!? :-?
Ответить | Ответить с цитатой | Цитировать
# ooogo 21.05.2011 08:01
Точно загнался, макроопределение
#define OWI_PIN PIND //!< 1-Wire Input pin register.
pins входная переменная номер порта, значит 0, если датчик не ответил и 1, если датчик сформировал на шине импульс присутствия. извините, что так много написал. :-*
Ответить | Ответить с цитатой | Цитировать
# Ivan 25.05.2011 16:21
Вопрос, а в чем будут отличия если использовать датчики DS1820 или аналог DS18S20
Ответить | Ответить с цитатой | Цитировать
# stolyars 08.06.2011 16:27
У кого есть переделка под Атмегу8 и проект в протеусе для нее скинте в любой обменник пожалуйста или выложите сдесь(WinAVR)
Ответить | Ответить с цитатой | Цитировать
# londo 12.06.2011 08:35
А как подсчитывается контрольная сумма?
Ответить | Ответить с цитатой | Цитировать
# Valia 09.08.2011 12:46
подскажите пожалуйста, а как увеличить количество знаков после запятой (один знак мало)
Ответить | Ответить с цитатой | Цитировать
# Джо 11.09.2011 10:22
Жаль на асме нет кода :-)
Ответить | Ответить с цитатой | Цитировать
# Владимир Андреевич 07.10.2012 18:38
if ((scratchpad[1] &128) == 0){ //проверяем старший разряд

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


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

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


У меня такая же проблема. Не могу даже скомпилить оригинал на WinAvr. Выдает ошибку:
compilers.h: No such file or directory OWIde fs.h 24 23 cher novik2
Ответить | Ответить с цитатой | Цитировать
# Pashgan 18.12.2012 19:48
Я залил проект для AVR Studio 4, смотрите как сделано там.
Ответить | Ответить с цитатой | Цитировать
# Дмитрий Д 12.01.2013 19:41
Прости конечно, но у меня даже скачав и открыв твой проект в содевизион не компилится. Ошибка в библиотеке лсд_либ! Сам пишу в авр стидио 6, и ошибку compilers.h: No such file or directory OWIde fs.h уже 3 день парю) ничто не помогает. И проект на 4 тоже такое же дает.
Ответить | Ответить с цитатой | Цитировать
# Дмитрий Д 13.01.2013 10:13
Закоментировал строку compilers.h в файле OWIde fs.h . Срезу же скомпилил - не знаю во что это потом выльется.)
Ответить | Ответить с цитатой | Цитировать
# zadorand 28.12.2012 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 27.01.2013 10:58
В Протеусе, при отрицательных температурах, не верно отображаются десятые доли градуса. Это глюк модели? Кто-нибудь проверял на реальном устройстве?
Буду очень признателен, если кто ткнёт в нужном направлении.
Ответить | Ответить с цитатой | Цитировать
# Pashgan 27.01.2013 20:34
Если будешь задавать там температуру кратно 0.0625 (это вес младшего разряда DS18b20), то все будет отображаться корректно.
Ответить | Ответить с цитатой | Цитировать
# IurriI 28.01.2013 01:06
Pashgan, спасибо за оперативность. Задавал я и CurrentValue и Granularity кратными 0.0625 - без толку. Округляет до десятых в меньшую сторону.Значит такая модель... А у меня проект работает только на частоте 4МГц. :-| Надо осваивать JTAG.
Ответить | Ответить с цитатой | Цитировать
# Pashgan 28.01.2013 04:21
Выведи на дисплей необработанное значение температуры с датчика и посмотри какие цифры он генерит.
Если ты используешь мой код, то там есть округление. Выводится только один знак после запятой, но он соответствует температуре датчика.
Ответить | Ответить с цитатой | Цитировать
# IurriI 28.01.2013 22:26
Pashgan,в том то и дело, что вывожу необработанные данные вот таким образом
Код:
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 08.02.2013 11:06
Pashgan, писал вам ранее. Есть прогресс. После изменения OWI_DELAY_OFFSE T_CYCLES на 0 схема заработала в протеусе. Но на железе не хочет, ни в паразитном, ни в обычном исполнении :cry:
Посоветуйте куда копать, уже замучался.
Ответить | Ответить с цитатой | Цитировать
# XanderEVG 07.04.2013 17:53
Код: temperature = (temperature<<1) + (temperature<<3);// Умножаем на 10

хитро. почему так?
Ответить | Ответить с цитатой | Цитировать
# Pashgan 07.04.2013 19:32
Получается более компактный ассемблерный код на микроконтроллер ах без аппаратного умножителя.
Ответить | Ответить с цитатой | Цитировать
# XanderEVG 08.04.2013 04:23
Да. По запаре я не сразу понял что
Код:temperature = (temperature<<1) + (temperature<<3);// Умножаем на 10
=
Код:temperature = temperature*2 + temperature*8;// Умножаем на 10
умножитель есть много где и сним короче на пару команд.
но наверно так можно и делить на 10? а это уже что то.
Ответить | Ответить с цитатой | Цитировать
# Pashgan 08.04.2013 07:22
Делить так можно только на степени двойки (на 2, 4, 8, 16). На 10 сдвигами разделить не получится. Я по крайней мере не знаю, как это сделать.
Написав эту строчку, я в принципе никаких оптимизационных целей не преследовал. И сделал так скорее по старой привычке.
Ответить | Ответить с цитатой | Цитировать
# Sergofan5 04.05.2013 09:28
Делаю проект контроллера для аквариума в Atmel Studio 6 - никак не получается прикрутить DS18B20 - ругается на compillers.h, и экран у меня nokia3310 не посоветуете что можно придумать????
Ответить | Ответить с цитатой | Цитировать
# Сашка 17.10.2013 04:49
Такая проблемка: ругается на delay.h?, при компиляции сначала варнинг выдаёт:warning Код:"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 17.10.2013 08:51
F_CPU должен быть определен в Make файле
Ответить | Ответить с цитатой | Цитировать
# angell 11.12.2013 16:51
Мужик! человеческой спасибо! с полпинка заработало!
Ответить | Ответить с цитатой | Цитировать
# Pashgan 11.12.2013 23:09
Это радует.
Ответить | Ответить с цитатой | Цитировать
# RONIN 12.12.2013 05:22
а как изменить температурное разрешение датчика??
Ответить | Ответить с цитатой | Цитировать
# JoJo 12.12.2013 22:13
Подать команду write scratchpad, а затем передать три байта. Последний байт - значение конфигурационно го регистра. А он как раз устанавливает разрешение датчика.
Ответить | Ответить с цитатой | Цитировать
# RONIN 15.12.2013 23:02
мне нужно реализовать термометр с шагом измерений 0,5 градуса на атмеге48. показания выводить на ПК через usart.как изменится код для AVR Studio??
Ответить | Ответить с цитатой | Цитировать
# Pashgan 17.12.2013 09:30
Что значит как? Ну изменится. Нужно взять проект от этой статьи и прикрутить к нему USART драйвер/библиот еку.
Ответить | Ответить с цитатой | Цитировать
# decibel 15.02.2014 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?
Ответить | Ответить с цитатой | Цитировать
# _Артём_ 16.02.2014 15:21
Попробуйте так:
Код:
#include "..\common_files\OWIdefs.h"

или пропишите директорию в которой лежит OWIdefs.h в настройках проекта и тогда можно писать так:
Код:
#include "OWIdefs.h"
Ответить | Ответить с цитатой | Цитировать
# decibel 20.02.2014 17:19
Разобрался, неправильна подключил библиотеку в Include Directories.
Ответить | Ответить с цитатой | Цитировать
# KiberPank 24.02.2014 18:47
Спасибо за обзор библиотеки и протокола. Очень помог, за пару часов всё запустилось.
Еще добавить фенечек, чтобы не блокировало основную программу и будет шикарно) Сейчас этим и занимаюсь.
Ответить | Ответить с цитатой | Цитировать
# shurf 26.02.2014 20:52
Прикрутил эту библиотеку без особых проблем, но когда читаю данные с датчика - датчик походу и не дрыгается - прут сплошные единички (Детект Пресенс показывает наличие датчика). Единички прут как в протеусе, так и в железе. Подскажите, куда копать?
Ответить | Ответить с цитатой | Цитировать
# shurf 28.02.2014 18:12
Пошуршал в протеусе с логическим анализатором - почему-то все тайминги увеличены в три раза 0_о
Ответить | Ответить с цитатой | Цитировать
# Pashgan 18.03.2014 19:56
Где-то неправильно задана тактовая частота. Эта библиотека многократно проверена.
Ответить | Ответить с цитатой | Цитировать
# shurf 18.03.2014 20:00
Чертовщина какая-то. Ладно бы в 2, 4 или 1024 раза. А так - в три раза. Пробовал ставить разные частоты и делитель включать-выключ ать - то же самое, увеличивается в три раза(
Ответить | Ответить с цитатой | Цитировать
# Pashgan 18.03.2014 20:03
Скинь rar архив проекта на форум (там есть ветка для временных проектов). Завтра попробую запустить у себя и напишу о результатах.
Ответить | Ответить с цитатой | Цитировать
# Vinipuhh13 24.05.2014 12:44
Пытаюсь скомпилировать проект в Atmel Studio 6.
ошибка __builtin_avr_d elay_cycles expects a compile time integer constant, как я понял неправильно определяется версия компилятора и файл compilers.h не отрабатывается. что должно быть в этом файл только для AS6
Ответить | Ответить с цитатой | Цитировать
# Roman1984 08.07.2014 02:32
Здравствуйте у меня вопрос: почему при запуске датчик кратковременно выводит значение +85, а затем начинает показывать нормально?
Ответить | Ответить с цитатой | Цитировать
# IDHacker 13.10.2014 02:40
Потому что сначала надо запустить преобразование температуры. +85 это начальное значение температуры при подаче питания на датчик.
Ответить | Ответить с цитатой | Цитировать
# IDHacker 13.10.2014 02:39
Статьи конечно познавательные, и библиотека для сборки градусников полезная. Но вот опять как у всех, нет внятных описаний алгоритмов работы. Ведь 1wire не такая уж сложная. Если подключать к UART всё складывается в отправку приём байтов. Как можно прикрутить чужую библиотеку когда в своей программе крутится пару таймеров и работает пяток прерываний. Совершенно невозможно представить временные интервалы.
Опять же не расписан формат данных температуры, одни конструкторы, со своими библиотеками. Надо алгоритмы описывать, а не пихать свои библиотеки, ещё и без внятного описания всех функций библиотеки.
Ответить | Ответить с цитатой | Цитировать
# Ilya 07.12.2014 08:09
Подскажите код для вывода температуря через UART, для этого проекта.
Ответить | Ответить с цитатой | Цитировать
# feekus 18.12.2014 08:07
при прошивке на ATMegs32 выдает на дисплее число +127,9 что это может быть и как можно исправить?
Ответить | Ответить с цитатой | Цитировать
# Виктор 30.01.2015 16:31
У вас нет проекта в Atmel Studio??
Ответить | Ответить с цитатой | Цитировать
# ASDFG123 11.03.2015 05:36
Код:#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 28.06.2016 19:38
Подскажите пожалуйста, как правильно собрать значение температуры в знаковую переменную с плавающей точкой, типа float, чтоб значение хранилось в одной переменной и дальше с ним можно было делать всякие математические операции. Ну или хотя-бы с фиксированной точкой, просто скажем signed int.
Ответить | Ответить с цитатой | Цитировать

Добавить комментарий

Защитный код
Обновить