Си библиотека для работы с 1-Wire устройствами

31/12/2010 - 16:03
   Для работы с устройствами, поддерживающими 1-Wire протокол уже давным-давно написаны библиотеки. Поэтому нет смысла изобретать велосипед (лично я это уже делал, когда программировал  на ассемблере) и писать что-то свое. На сайте фирмы ATMEL есть замечательный application note AVR318: Dallas 1-Wire, в котором рассмотрены два варианта реализации 1-Wire протокола на микроконтроллерах AVR – программная и аппаратная. Программная реализация позволяет использовать однопроводный протокол на любых микроконтроллерах. Аппаратная – только на тех, на которых есть модуль UART. Аппаратной поддержки 1-Wire протокола «в чистом виде» микроконтроллеры AVR не имеют, однако, используя модуль UART неким хитрым образом, эту поддержку можно организовать. К application note идет проект. Я взял из этого проекта исходные файлы библиотеки, добавил, изменил несколько функций и написал файл compilers.h, чтобы можно было использовать эту либу с любым из трех компиляторов – IAR AVR, GNU GCC (WINAVR), CodeVision.

   Библиотека состоит из следующих файлов
 
OWISWBitFunction.h
OWISWBitFunction.c
OWIUARTBitFunction.c
 
OWIHighLevelFunction.h
OWIHighLevelFunction.c
 
OWIPolled.h
compilers.h
 
OWIdefs.h
OWIdevicespecific.h
OWIcrc.h
OWIcrc.c

Как подключить библиотеку к проекту

Процесс интеграции 1-Wire библиотеки с проектом заключается в следующем:

- переписываем файлы библиотеки в папку проекта

- подключаем сишные файлы к проекту
OWIHighFunction.c
OWISWBitFunction.c
OWIUARTBitFunction.c
OWIcrc.c

- добавляем заголовочные файлы в main.c
#include "OWIPolled.h"
#include "OWIHighLevelFunctions.h"
#include "OWIBitFunctions.h"
#include "common_files\OWIcrc.h"

- настраиваем файл OWIPolled.h

- выбираем реализацию OneWire интерфейса – программную 
       #define     OWI_SOFTWARE_DRIVER    
       //#define     OWI_UART_DRIVER

- задаем тактовую частоту микроконтроллера
       #define     CPU_FREQUENCY   16.000

- задаем порт, к которому подключена OneWire шина
       #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.

- в main.c задаем вывод, к которому подключена OneWire шина
      #define BUS   OWI_PIN_7
 
Для GCC проектов в makefile нужно будет добавить все сишные файлы. 
Например, так:
 
SRC = $(TARGET).c bcd.c lcd_lib.c OWISWBitFunctions.c OWIHighLevelFunctions.c OWIUARTBitFunctions.c  common_files/OWIcrc.c

Файлы

Application note AVR318: Dallas 1-Wire

Проекты проверялись в железе и никаких нареканий не вызывали. В Proteus`е я их тоже запустил, но не сразу. Оказывается по умолчанию датчикам DS18B20 присваиваются одинаковые адреса. При использовании нескольких датчиков адреса нужно подправить ручками.

Подробное описание проектов будет уже в новом году...

Comments   

# foxit 2010-12-31 20:16
на сайте gaw.ru есть апноут AVR318 на русском.
# foxit 2011-01-03 09:23
Жду с нетерпением проектов!
# Petrov 2011-01-06 10:39
Спасибо! ;-)
# Vector 2011-01-07 11:01
И в Proteus - все работает!
Тактовая процессора 8MHZ ,и адрес одного датчика поменять. (Proeus по умолчанию лепит одинаковые для всех)
Спасибо!
# Pashgan 2011-01-08 09:14
Отлично. А я не знал, что адреса датчиков менять нужно.
# Vector 2011-01-10 18:37
Ну я свои "грабли" описал, не ожидал, что такую фигню Proteus делает.
# foxit 2011-01-07 11:34
А под winavr будут проекты?
# Pashgan 2011-01-07 13:14
Уже есть. Скоро выложу. Материала пока нет. Праздники - отдыхаю, ленюсь.
# Pashgan 2011-01-10 20:50
Выложил проекты для WINAVR, CodeVision и Proteus`a.
# Ky 2014-09-03 19:49
А можете носом ткнуть в проект для протеуса? Жажду взглянуть на него, ибо у самого в проте далласовский датчик работает крайне нестабильно.
# Vector 2011-01-08 16:27
С частотой в Proteus действительно - лажа. Работает, только если в OWIPolled.h завысить на 50% CPU_FREQUENCY (в Protrus 4MHz ,OWIPolled.h 6MHz)
Предпочтительней уменьшить время в настройках модели датчика процентов на 30. (проверял - помогает с IAR 5.3 и Proteus 7.7 Sp2; макет на ATMEGA8515 4MHz)
# Pashgan 2011-01-10 14:48
А я проверил второй проект в Proteus`e и все работает как часы!!!
# andrdoy 2011-01-10 07:12
а что делать если датчик не 18B20
а 18S20 или 1820 (без буквы)
# Pashgan 2011-01-10 14:46
DS18S20 и DS1820 отличается от DS18B20 температурным разрешением. У первых разрешение 9 бит, у последнего 9-12.
Чтобы использовать проект "работа с одним датчиком DS18B20" для датчика DS18S20, нужно изменить кусок вывода значения температуры на дисплей
Code:
/*выводим знак*/
LCD_Goto(5,0);
if ((scratchpad[1]&128) == 0){
LCD_WriteData('+');
}
else{
LCD_WriteData('-');
tmp = ((unsigned int)scratchpad[1]<<8)|scratchpad[0];
tmp = ~tmp + 1;
scratchpad[0] = tmp;
scratchpad[1] = tmp>>8;
}

/*выводим целую часть*/
temperature = (scratchpad[0]>>4)|((scratchpad[1]&7)<<4);
BCD_3Lcd(temperature);

/*выводим дробную часть*/
temperature = (scratchpad[0]&15);
temperature = (temperature>>1) + (temperature>>3);
LCD_WriteData('.');
BCD_1Lcd(temperature);


на

Code:
LCD_Goto(5,0);
if ((scratchpad[1]&128) == 0){
LCD_WriteData('+');
}
else{
LCD_WriteData('-');
}
temperature = (scratchpad[0]>>1);
BCD_3Lcd(temperature);
# CHERTS74 2011-02-17 06:22
Для DS18B20 вообще можно заменить кусок:
Code:
/*выводим знак*/
LCD_Goto(5,0);
if ((scratchpad[1]&128) == 0){
LCD_WriteData('+');
}
else{
LCD_WriteData('-');
tmp = ((unsigned int)scratchpad[1]<<8)|scratchpad[0];
tmp = ~tmp + 1;
scratchpad[0] = tmp;
scratchpad[1] = tmp>>8;
}

/*выводим целую часть*/
temperature = (scratchpad[0]>>4)|((scratchpad[1]&7)<<4);
BCD_3Lcd(temperature);

/*выводим дробную часть*/
temperature = (scratchpad[0]&15);
temperature = (temperature>>1) + (temperature>>3);
LCD_WriteData('.');
BCD_1Lcd(temperature);


на более короткий и лаконичный:

Code:
LCD_Goto(5,0);
if ((scratchpad[1]&128) == 0){
LCD_WriteData('+');
}else{
LCD_WriteData('-');
}
int reading = (scratchpad[1]<<8) + scratchpad[0];
if (reading & 0x8000) {
reading = (reading ^ 0xffff) + 1;
}
float temp = (6 * reading) + reading / 4;
dtostrf((temp/100),2,2,temperature);
LCD_SendString(temperature);
LCD_WriteData('C');


После этого можно избавиться от файла bcd.c в Makefile
Не забыть добавить вначале main.c
#include и убрать #include "bcd.h"

После
int main( void )
{
удалить
unsigned int tmp = 0;
unsigned char temperature;
добавить
Code:#include<stdlib.h>
int main(void)
{
unsigned char temperature[20];
# Pashgan 2011-02-17 07:44
Код выглядит компактно только на Си. На Асме код будет тяжелый и медленный.
# CHERTS74 2011-02-17 09:50
Не думаю что если я выкину файл bcd.c с кучей ненужных функций и заменю его на более простые, код от этого усложнится. Думаю наоборот полегче станет. Да и стак как бы полегче. Проверено ;)
А так, огромное спасибо за такие полезные статьи!

P.S. Кстате, почему то не приходит письмо с активацией моего акаунта CHERTS :(
# Pashgan 2011-02-19 23:47
Неиспользуемые функции не добавляют лишних байт к прошивке. Чего нельзя сказать о стандартных сишных функциях. Они как правило тяжеловесны, почему я их и недолюбливаю. Сравните два варианта кода и увидите разницу. Размер hex файла во втором случае будет больше.

Кстати, с чего вы решили, что dtostrf более простая? Видели исходники этой функции. Посмотрите.
www.koders.com/c/fid59843B28432C0FF3F7D5DA5BE2A2F4051E5E095E.aspx?s=dtoa_prf#L54
www.koders.com/c/fidDB4D83581A0529937AFB0C8F77401277E6F372AA.aspx?s=dtoa_prf#L29

Quote:
Кстате, почему то не приходит письмо с активацией моего акаунта CHERTS
Может быть не правильно указали е-mail, может быть движок глючит.Я активировал ваш аккаунт вручную.
# Вадим 2011-01-24 19:51
Заметил одну неточность в проекте для IAR AVR — работа с одним датчиком DS18B20. В файле main.c дробная часть обрабатывается так:
Code:
temperature = (scratchpad[0]&15);
temperature = (temperature>>1) + (temperature>>3);
LCD_WriteData('.');
BCD_1Lcd(temperature);

При обработке возникает погрешность (это можно легко проверить: пусть датчик померил 0,9375 гр. или 0x0F, на LCD выведет - 0,8гр. цельсия)
Правильнее написать так:
Code:
temperature = (scratchpad[0]&15);
temperature = (temperature<<1) + (temperature<<3);// Умножаем на 10
temperature = (temperature>>4);//делим на 16 или умножаем на 0,0625
LCD_WriteData('.');
BCD_1Lcd(temperature);
# Pashgan 2011-01-29 21:27
Да, есть некоторые недостатки
# Богдан 2011-04-29 09:39
Дякую авторам!
# Den1s 2011-08-11 13:13
подскажите, а почему ни с одной тини не компилится в ИАРе проект с этой библиотекой. Пробовал 10, 13, 13А, 2313. Ругается на стек.
# Blambik 2011-09-07 13:13
Автор! Респект! Наконец то увидел реализацию функции SearchROM! А то никак не мог ее реализовать :(
# Max 2011-11-05 20:45
Нужен код для конфигурации датчика (изменить его разрешающую способность),
как запрограммирова ть R0=0, R1=0
Заранее спасибо
# Финский 2013-10-19 11:34
Спасибо за библиотеку, разбираюсь потихоньку. Столкнулся с некоторыми затыками, которые решил и делюсь решениями:
1. В Atmel Studio в упор не компилился проект, с ошибкой No such file or directory, на файл compilers.h, пока в свойствах проекта не указал include folders, добавил корневой каталог проекта, и папку common_files.
2. В протеусе в упор не виделись датчики, ни один, ни несколько сразу. Даже на Presence не отвечали. Проблема решилась заменой Code:#define OWI_DELAY_OFFSET_CYCLES 13 //!< Timing delay when pulling bus low and releasing bus. на значение 7 или ниже. При значении 8 - уже не работает. В железе пока не проверялось.
# ДмитрийМ 2013-10-24 13:28
попробовал этот проект на attiny2313 на частоте 8 мгц, в протеусе работает, в железе не идёт дальше вот этой строчки
Code:
/*ждем, когда датчик завершит преобразование*/
while (!OWI_ReadBit(BUS));

наличие датчика проверял функцией OWIsearchRom, датчик находится, если он подключен, не находится, если отключен.
# Pashgan 2013-10-24 13:51
Попробуй заменить программной задержкой и посмотреть результат.
# ДмитрийМ 2013-10-24 16:18
сам только что об этом подумал, поставил вместо этого Code:delay_ms(800);
всё так же, протеус - работает, железо - нет
# ДмитрийМ 2013-10-24 18:47
Работаю, кстати, в codevision, попробую проект для авр студии.
# vitaliy 2014-01-15 14:23
Quote:
1. В Atmel Studio в упор не компилился проект, с ошибкой No such file or directory, на файл compilers.h, пока в свойствах проекта не указал include folders, добавил корневой каталог проекта, и папку common_files.
Такие же грабли в AVR Studio 4.19,пока не прописал в include directories корневой каталог и папку common_files,вы брасывало ту же ошибку.
Контролер Atmega8,кварц 16 МГц.Фокус с proteus в плане понижения в два раза частоты в свойствах Atmega8 - работает.Иначе температура на LCD +0,00.
Еще раз спасибо за библиотеку.
# Володя 2014-01-26 16:33
Скажите пожалуйста где прописывается include directories? Папку common_files добавил, все равно ошибка No such file or directory
# Pashgan 2014-01-28 11:47
Для какого компилятора проект?
# Володя 2014-01-28 12:40
5я студия
AVR GNU C Compiler
# _Артём_ 2014-01-28 13:53
Возможны варианты:
1) Если у вас makefile project - прописываеие пути в makefile :)
2) Проект с визуальными настройками - открываете свойства проекта - вкладка Toolchain - AVR GNU C Compiler -Directories. Там вписываете нужные пути.
# Pashgan 2014-01-29 09:11
Свойства проекта > вкладка Toolchain > AVR GNU C Compiler > Directories
Там нужно прописать пути:
../common_files
../
# Володя 2014-01-29 15:46
Большое спасибо!!!! Заработало ;-)
# Berg 2015-03-13 20:28
Спасибо Всем. Наконец-то заставил работать сей датчик и вывести данные на дисплей nokia5110(3310) в AVR Studio. Теперь мечтаю получить данные с 2-х датчиков.
# Vol-Y.I.P 2015-04-20 14:04
Привет Всем!!!
Такая ошибка:"undefin ed reference to `OWI_Init'"
Atmel Studio 6.2
В чем может быть проблема?
# Sanek0 2016-06-19 08:50
Такая же проблема, похоже как то связано с тем, что исходный проект в C++. Если получится решить как то напишу.
# Sanek0 2016-06-19 10:10
У кого возникает ошибка "undefin ed reference to `OWI_Init'" и проект на C++ необходимо хедлеры указать как внешние "С".
Code:
extern "C"
{
#include "OWIHighLevelFunctions.h"
#include "OWIBitFunctions.h"
#include "common_files/OWIcrc.h"
}

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