Страница 1 из 1

Проблемы с Onewire

Добавлено: Ср апр 13, 2011 11:42:27
AlexL
Здравствуйте. Мне нужно написать программу, которая могла общаться с некоторым устройством по onewire. Хочу сделать домофонный ключ-отмычку по примерам с этого сайта, но сначала думаю потренироваться на датчике DS18B20. Программирую микроконтроллер atmega8, пользуюсь WinAVR.
Вот код моей программы:

Код: Выделить всё

#define OW_PORT PORTD
#define OW_DDR  DDRD
#define OW_PIN  PIND

char CheckPresence( void )
{//*send 'master reset pulse'
   char tmp;   
   OW_DDR |= (1 << OW);   //set line as output
   OW_PORT  &= ~(1 << OW);         
   _delay_us(500);
   //*releas the line, and read the iButton presence pulse (low level)       
   OW_DDR &= ~(1 << OW);  //set line as input
   _delay_us(80);
   tmp = OW_PIN & (1 << OW );
   _delay_us(100);
   if( tmp)
      return 0;
   else
      return 1;
}

char GetBit( void )
{
   char tmp;
   //send 'initiate bit'
   OW_DDR |= (1 << OW);   //set line as output 
   OW_PORT  &= ~(1 << OW);         
   _delay_us(7);
   //*releas the line, and read the iButton data bit       
   OW_DDR &= ~(1 << OW); //set line as input (release the line)
   _delay_us(5);
   tmp = (OW_PIN & (1 << OW ));
   _delay_us(85);
   //*return the data bit value
   return tmp;     
}

void SendBit( char bit )
{
   //*send 'initiate bit'
   OW_DDR |= (1 << OW);   //set line as output 
   OW_PORT  &= ~(1 << OW);         
   _delay_us(10);
   //*send the data bit
   if( bit )
      OW_DDR &= ~(1 << OW); //set line as input (release the line)
   _delay_us(70);
   //*release the line
   OW_DDR &= ~(1 << OW); //set line as input
   _delay_us(50);
}

void ReadData( char *data )
{
   char tmp, i;     
   //send 'read ROM command'
   i = 0x33;
   for( tmp = 0; tmp < 8; tmp++ ){
      SendBit( i & 0x01 );
      i >>= 1;
   }         
   //get Data
   for( i = 0; i < 8; i++ ) { //8 байт
      *data = 0; //init variable
      for ( tmp = 0; tmp < 8; tmp++ ){
         *data >>= 1;
         *data |= GetBit();
      }
      data++;
   }
}

Проблема в том, что при чтении с датчика температуры идет какой-то мусор. Пожалуйста, подскажите, в чем может быть ошибка ?

Re: Проблемы с Onewire

Добавлено: Ср апр 13, 2011 11:47:23
ARV
ну, как минимум проблема в том, что вы очень вольно обращаетесь с временными интервалами, соблюдать которые необходимо строго по стандарту 1-wire.

возьмите готовую библиотеку для работы. если есть желание - посмотрите, как сделано там. если желания нет - просто используйте ее.

можете поглядеть, как сделал я в своих проектах - исходники я выкладывал на своем сайте для проектов "термостата, который меньше, чем не бывает" :)))

Re: Проблемы с Onewire

Добавлено: Ср апр 13, 2011 21:34:19
AlexL
Благодарю за код. Сегодня попробовал присоединить к своему проекту, все работает. Завтра буду пробовать на железе.
Я посмотрел файлы 1w.h и 1w.c из Вашего проекта. Не смог разобраться с несколькими вещами. Не могли бы Вы объяснить, для чего они нужны?

Код: Выделить всё

#include <avr/pgmspace.h>
Для чего используется эта библиотека ? Если удалить эту строчку, программа нормально компилируется.

Вообще я недавно начал программировать, и не всегда понимаю, зачем нужен был тот или иной фрагмент кода.
Зачем используется тип uint8_t ? Судя по описанию в интернете это "Тип без знака на 8 битов", это все равно что unsigned char ? Такой же вопрос, обязательно ли перед типом некоторых функций писать static ?

Код: Выделить всё

uint8_t __attribute__ ((weak, alias ("_crc_ibutton_update"))) ow_crc(uint8_t crc, uint8_t x);
Зачем нужен код _attribute__ ((weak, alias ("_crc_ibutton_update"))) ?

Функция чтения:

Код: Выделить всё

   ow_reset();
   ow_write_byte(OW_SKIP_ROM_CMD);      // команда "пропустить адрес"
   ow_write_byte(CMD_RD_SCRPAD);      // команда "считать регистры датчика"
       ...чтение...
   ow_write_byte(OW_SKIP_ROM_CMD);      // команда "пропустить адрес"
   ow_write_byte(CMD_START_CONV);      // команда "начать измерение"
   ow_reset();                     // сброс 1-wire
   return result;
Зачем нужен второй блок, после чтения ?

Код: Выделить всё

// первое обращение к датчику вернет ложное значение, но запустит цикл измерения
temp_x100(&t);
Почему первое обращение вернет ложное значение ?

Прошу прощения если вопросов слишком много, но я хотел бы полностью разобраться. Заранее спасибо :).

Re: Проблемы с Onewire

Добавлено: Чт апр 14, 2011 09:14:28
ARV
AlexL писал(а):

Код: Выделить всё

#include <avr/pgmspace.h>
Для чего используется эта библиотека ? Если удалить эту строчку, программа нормально компилируется.
это сделано "на перспективу" - в программной памяти может храниться константа-адрес датчика температуры, чтобы общаться только с ним. для единственного датчика это смысла не имеет, но хидер я оставил "на всякий случай". вы правы - он не необходим.
AlexL писал(а):Зачем используется тип uint8_t ? Судя по описанию в интернете это "Тип без знака на 8 битов", это все равно что unsigned char ?
это стандартный тип C99 - очень рекомендую придерживаться именно этого стандарта, если вы работаете с WinAVR. да, по своей сути это как бы unsigned char, но в зависимости от платформы char может быть и не равен одному байту (т.е. 8 бит), а вот uitn8_t всегда и везде будет равен именно 1 байту без знака.
AlexL писал(а):Такой же вопрос, обязательно ли перед типом некоторых функций писать static ?
со статик вопрос не такой простой. в моем коде наличие static перед некоторыми функциями носит принципиальный характер, т.к. я знаю, что в этом случае оптимизатор сгенерирует самый быстрый код - для 1-wire это важно. а вообще static для функции означает, что она (функция) будет использоваться только в текущем файле-модуле, и не будет видима из других файлов-модулей. это позволяет компилятору активно ее инлайнить и по-всякому оптимизировать. пока не разберетесь во всем этом - лучше не убирайте из моего кода static ниоткуда :)
AlexL писал(а):Зачем нужен код _attribute__ ((weak, alias ("_crc_ibutton_update"))) ?
это просто алиас, т.е. синоним библиотечной функции подсчета CRC. я взял ее в готовом виде из библиотеки, но вы сможете при желании подстваить вместо нее свою функцию - для этого вам надо будет эту строку заремарить и определить свой вариант функции ow_crc() - просто такое наименование короче и удобнее, чем длинное _crc_ibutton_update() :)
AlexL писал(а):Зачем нужен второй блок, после чтения ?
внимательно прочтите все комментарии в коде. функция, возвращающая результат измерения температуры автоматически запускает очередное измерение. т.е. считывает ПРЕДЫДУЩЕЕ, запускает НОВОЕ. это позволяет не тратить время на ожидание измерения (до 0,8 секунды), а получать результат сразу.
AlexL писал(а):Почему первое обращение вернет ложное значение ?
как раз по предыдущей причине: при первом обращении к функции датчик еще не измерял ничего - не было запуска измерения, поэтому функция вернет значение по умолчанию (85) из его регистров. а вот когда вы второй раз обратитесь к функции (спустя некоторое время, естественно) - она врнет уже реально измеренное значение, ведь старт измерения был дан в предыдущий раз :)

всем известный CVAVR поступает строго наоборот: запускает измерение при вызове функции и тупо ждет 0,8 секунды, прежде чем вернуть результат. в итоге вся остальная часть программы "подвисает", а если учесть, что CVAVR-овская функция еще и не любит прерываний во время своей работы - получается вообще катастрофа. я постарался простейшими средствами устранить эти недостатки - ценой неправильного значения в первый вызов. удобно это или нет - вам решать :)

Re: Проблемы с Onewire

Добавлено: Пт апр 15, 2011 20:55:22
AlexL
Огромное спасибо ! С Вашей библиотекой все заработало !
У Вас не найдется исходников для считывания кода устройства датчика ds18s20 и обращения к датчику по его коду ? И можно ли будет использовать те же команды для считывания кодов других 1-wire датчиков ?

Re: Проблемы с Onewire

Добавлено: Пт апр 15, 2011 23:01:51
ARV
внимательно изучайте то, что скачали - там всего достаточно для исполнения ваших желаний. послать команду, считать байты - никакой разницы нет по сранению с измерением температуры - разные команды и количество данных, вот и все. думайте :)

Re: Проблемы с Onewire

Добавлено: Чт апр 21, 2011 05:50:11
Paguo-86PK
ARV писал(а):ну, как минимум проблема в том, что вы очень вольно обращаетесь с временными интервалами, соблюдать которые необходимо строго по стандарту 1-wire.
Хм... :shock:
А если мне такое не подходит? Т.е. какие спец микросхемы использовать, чтобы все интервалы было возложенны на отдельный 1w-bus-контроллер и я не заморачивался в проекте на всякие мелочи?
А то в даташитах 1-вайр всюду диаграммы и алгоритмы crc и т.д. Т.е. мне придётся всё делать самому? :shock: Как в лихое время загрузки с магнитофона бит по биту???

Re: Проблемы с Onewire

Добавлено: Чт апр 21, 2011 08:15:05
ARV
Paguo-86PK писал(а):А если мне такое не подходит? Т.е. какие спец микросхемы использовать, чтобы все интервалы было возложенны на отдельный 1w-bus-контроллер и я не заморачивался в проекте на всякие мелочи?
А то в даташитах 1-вайр всюду диаграммы и алгоритмы crc и т.д. Т.е. мне придётся всё делать самому? :shock: Как в лихое время загрузки с магнитофона бит по биту???

во-первых, единожды создав библиотеку функций, больше париться не придется.
во-вторых, такие библиотеки уже и так созданы - берите и пользуйтесь. одна из них (вообще-то больше) сделана вашим покорным слугой.
в-третьих, есть вариант использования UART/USART/COM-порта для аппаратного формирования всех временных интервалов, что сильно облегчает эту часть программ. правда, для МК я так не делал, т.к. UART обычно нужен для других целей, да и 2 вывода хуже, чем один :) а вот для компьютера самое оно.
наконец, в-четвертых, фирма максим-даллас производит несколько микросхем-мостов для 1-wire, например мост COM/1-wire DS2480, есть и для других интерфейсов. это позволит вам вообще не думать о протоколе 1-wire. зато все фирменные решения максим-далласа весьма дорогие...

так что выбор есть :)