Перейти к содержанию
    

DS18b20 и Atmega128

Использую в своем девайсе датчики DS18b20.

Подключаю их на Atmega128. Столкнулся с проблемой

3 датчика работаю нормально но если подключить четвертый то все становитсяя наперекосяк.

Процессор каждый раз видит как будто на шине датчиков не 4 а 10 или 14 или 30. Каждый раз поразному.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Прекрасно изложена суть проблемы - без подробностей...

Какая схема включения?

Как инициализируете контроллер?

Как работаете с датчиком?

Как питаете всё хозяйство?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Прекрасно изложена суть проблемы - без подробностей...

Какая схема включения?

Как инициализируете контроллер?

Как работаете с датчиком?

Как питаете всё хозяйство?

 

 

Схема включения очень проста. Питание берется +5В то же что и питание контроллера

на шину данных вешается подтягивающий резистор 4,7 КОм.

 

Для работы с датчиком использую готовый модуль

#include "iom128.h"
#include "inavr.h"
#include "stdio.h"
#include "stdlib.h"
#include "stdint.h"
#include "string.h"
#include "ds18b20.h"
#include "stdint.h"
#include "timersw.h"



void DelayMs(uint8_t ms)            // Ждать ms    милисекунд
{
uint8_t    i;                        // рабочий регистр
for(i=ms;i>0;i--)
  __delay_cycles(1000000/TCLK);        // Задержка 1мс
}


void Delay01(uint16_t s01)            // Ждать s01*0.1 секунд
{
uint8_t    i;                        // рабочий регистр
for(i=s01;i>0;i--) DelayMs(100);
} 


uint8_t    OW_crc8(uint8_t seed, uint8_t inData)
{
    uint8_t    bitsLeft;
    uint8_t    temp;

    for    (bitsLeft =    8; bitsLeft    > 0; bitsLeft--)
    {
        temp = ((seed ^    inData)    & 0x01);
        if (temp ==    0) seed >>= 1;
        else
        {
            seed ^=    0x18;
            seed >>= 1;
            seed |=    0x80;
        }
        inData >>= 1;
    }
    return seed;
}

//Сброс    шины 1-wire
uint8_t    OW_reset(void)
{
  uint8_t answer;
  
  OW_PORT_SET;                                    // Обеспечить питанием для двух проводного варианта
  OW_DDR_SET;                                    // На вывод
  DelayMs(10);                                    // 10 ms
  
  OW_PORT_CLR;                                    // Reset
  __delay_cycles(510000/TCLK);                    // 510 us

  OW_DDR_CLR;                                    // Освободить шину
  OW_PORT_SET;                                    // Подпорка
   __delay_cycles(50000/TCLK);                    // ~50us

  answer = ((OW_PIN & (1<<OW_DQ))!=0);
  __delay_cycles(430000/TCLK);                     // ~420us для завершения цикла
  OW_DDR_SET;                                    // На вывод
  return (answer);                                // 0-есть устройства, 1-нет устройств
}

//Запись бита
void OW_write_bit(uint8_t bit)
{
  OW_DDR_SET;                                    // Порт на вывод
  OW_PORT_CLR;                                    // Начало вывода бита
  __delay_cycles(2000/TCLK);                    // 2us
  
  if(bit) OW_DDR_CLR;                            // Если "1", то освободить шину
  __delay_cycles(62000/TCLK);                    // +62us
  OW_DDR_CLR;
  OW_PORT_SET;                                    // Завершить цикл
}

//Чтение бита
uint8_t OW_read_bit(void)
{
  uint8_t result;
  
  OW_DDR_SET;                                    // Порт на вывод
  OW_PORT_CLR;                                    // Начало чтения бита
  __delay_cycles(2000/TCLK);                    // 2us
  
  OW_DDR_CLR;                                    // Освободить шину
  OW_PORT_SET;                                    // Подпереть
  __delay_cycles(13000/TCLK);                    // +13us

  result = ((OW_PIN & (1<<OW_DQ))!=0);             // прочитать
  __delay_cycles(43000/TCLK);                    // +45us завершить операцию

  return result;
}

//Запись байта
void OW_write_byte(uint8_t command)
{
    for    (uint8_t i = 0;    i <    8; i++)
     {
         OW_write_bit(command &    0x01);            // передаём бит
         command >>= 1;                            // сдвигаем к следующему
     }
}

//Чтение байта
uint8_t    OW_read_byte(void)
{
  uint8_t    i;
  uint8_t    value =    0;

  for(i    = 0; i < 8;    i++)
    value    |= OW_read_bit() << i;                // читаем один бит и записываем    его    в разряд i

  return(value);
}

//Запуск конвертации температуры (для одного датчика на шине) 
void convert_temp_short(void)
{
    OW_reset();
    OW_write_byte(SKIP_ROM);                    //    skip ROM command (0xCC)
    OW_write_byte(CONVERT_T);                    // convert T (0x44)
}

//Чтение температуры
int16_t    read_scratchpad(uint8_t tip)
{
uint8_t    scratchpad[8];
uint8_t    crc    = 0;

OW_write_byte(READ_SCRATCHPAD);                // читаем scratchpad 0xBE
for    (uint8_t c1    = 0; c1    < 8; c1++)
{
    scratchpad[c1] = OW_read_byte();            // Принять данные с    1 Wire шины
    crc    =  OW_crc8(crc, scratchpad[c1]);        // Посчитать CRC8  для 1 Wire шины
}
crc=OW_crc8(crc, OW_read_byte());
OW_reset();
if (crc == 0)                                    // Проверить CRC8  для 1 Wire шины
{
   if(tip==DS18B20TIP)

      //return ((scratchpad[1] << 4) | (scratchpad[0] >> 4));
return ((scratchpad[1] <<8) | (scratchpad[0] ));
   else
     return ((scratchpad[1] & 0x80) |    (scratchpad[0] >> 1));
}
else return ( ERROR_CRC);                        // Message -80
}

//Чтение температуры (для одного датчика на шине)
int16_t    read_temp_short(void)
{
    OW_reset();
    OW_write_byte(SKIP_ROM);                    // пропусь ROM
    return (read_scratchpad(DS18B20TIP));        // Чтение температуры
}

//Выбор датчика
void MatchRom(uint8_t numb_dev)
{
uint8_t    crc,*addr;
    
crc = 0;                                        // предустановка crc
OW_reset();
OW_write_byte(MATCH_ROM);                        //    match ROM команда (0x55)
// Указатель на начало ROM области данного устройства
for(addr=OW_Rom_Device+numb_dev*7;addr<OW_Rom_Device+numb_dev*7+7;addr++)
{
    OW_write_byte(*addr);                        // вывести байт ROM
    crc = OW_crc8(crc,*addr);                    // посчитать CRC
}
OW_write_byte(crc);                            // вывести байт crc
}

//Запуск конвертации температуры (для конкретного датчика на шине) 
void convert_temp(uint8_t numb_dev)
{
MatchRom(numb_dev);                            // match ROM команда
OW_write_byte(CONVERT_T);                        // convert T (0x44)
OW_PORT_SET;                                    // Обеспечить питанием для двух проводного варианта
OW_DDR_SET;                                    // На вывод
}

//Чтение температуры (для конкретного датчика на шине)
int16_t    read_temp(uint8_t numb_dev)
{
    MatchRom(numb_dev);                            // match ROM команда
    return (read_scratchpad(*(OW_Rom_Device+numb_dev*7)));
}


uint8_t lastDiscrep;                             // last discrepancy
uint8_t *CurrentAddr;


// NEXT
// Эта функция ищет следующее устройство на 1- проводной шине. Если 
// нет больше устройств  на 1- проводной шине, тогда возвращается FALSE.
//
uint8_t Next(void)
{
uint8_t crc;                                    // CRC
uint8_t m = 1;                                    // битовый индекс
uint8_t n = 0;                                    // байтовый индекс
uint8_t k = 1;                                    // битовая маска
uint8_t discrepMarker = 0;                        // "маркер несоответствия" или "развилка" на дереве устройств
uint8_t g;                                        // Рабочий/Выходной бит

crc = 0;                                        // предустановка crc
if(OW_reset()||(lastDiscrep==100))                // Нет устройств (нет ответа) или все устройства перебраны, то выход FALSE
{
   lastDiscrep = 0;                                // Начало поиска
   return FALSE;
}
OW_write_byte(SEARCH_ROM);                        // передать команду SearchROM
do                                                // для всех восьми байтов
{
   g = OW_read_bit() << 1;                        // ответ на "0"
   g |= OW_read_bit();                            // и на дополнение
   if(g ==3) break;                                // нет устройств - завершить
   else
   {
     if(g>0)                                    // все связанные устройства отвечают на 0 или 1 (нет перекрёстка)
       g = g>>1;                                // битовая величина записи для поиска (идём по ветке)
     else    
     {                                            // Два устр-ва ответило на разные биты -- перекрёсток
                                                // если этот перекрёсток - перед последним 
                                                // перекрёстком на предшествующем NEXT, тогда выберите 
                                                // такой же бит как и в прошлый раз
       if(m<lastDiscrep) g = (((*(CurrentAddr+n))&k)>0);
       else    g = (m==lastDiscrep);                // если равен последнему отклику ==1
        if (g==0) discrepMarker = m;            // Выбрать новый перекрёсток
     }
     if(g==1)    (*(CurrentAddr+n)) |= k;        // перепешите бит в ROM[n] с маской k       
     else        (*(CurrentAddr+n)) &= ~k;       
     OW_write_bit(g);                            // вывести
     m++;                                        // следующий бит
     k = k<<1;                                    // сдвинуть маску
     if(k==0)                                    // если маска переполнилась, то - следующий байт ROM
     {                                            // байт n и инициализация маски
       crc = OW_crc8(crc, *(CurrentAddr+n));    // посчитать CRC
       n++; k++;
     }
   }
}while(n<8);                                    // цикл через все байты ROM 0-7

if(m<65||crc){                                 // если поиск был неудачным, тогда
   lastDiscrep=0;                                // очистка last discrepancy
   return FALSE;
}  
else
{
   lastDiscrep = discrepMarker;                    // поиск был удачным, так что установлено lastDiscrep,
   if(lastDiscrep==0) lastDiscrep=100;            // Если перекрёсток был последним, то установить признак выхода в след. NEXT
   else
   {
      CurrentAddr +=7;                            // Следующий адрес
      malloc(7);                                // Зарезервировать память под ROM
   }    
   return TRUE;                                    // указывает что поиск - не завершен пока,
}                                                // некоторые устройства остаются
}


uint8_t OW_cnt_device(void)
{
uint8_t    Cnt_Device;                                // Число устройств на шине

if(!OW_reset())                                // Начинается когда импульс присутствия обнаружен
{
   lastDiscrep = 0;                                // восстановите последнее несоответствие rom поиска глобальное
   Cnt_Device=0;
   OW_Rom_Device=CurrentAddr=malloc(8);            // Зарезервировать память под ROM
   while (Next())                                // Продолжить пока все дополнительные устройства не будут обнаружены
   {
     Cnt_Device++;
   }
}  return(3);
}

 

 

 

 

в теле программы вызываю процедуру поиска датчиков

OW_cnt_device(void)

 

и вот она мне ка раз и возвращает количество датчиков большое.

Пробовал симулировать в Протеусе - все то же самое

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Вы резервируете память malloc(8) только под один слэйв.

 

UPD: разглядел.

      CurrentAddr +=7;                            // Следующий адрес
      malloc(7);                                // Зарезервировать память под ROM

Предпочитаете грабли с тщательно отполированными ручками?

 

А скорее всего на 4-ом слэйве при malloc() просто наезжаете на стэк.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

А что мешает работать прямо по адресам и не использовать неработающую функцию поиска?

Изменено пользователем Dx!

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

в теле программы вызываю процедуру поиска датчиков

OW_cnt_device(void)

 

и вот она мне как раз и возвращает количество датчиков большое.

Пробовал симулировать в Протеусе - все то же самое

Вот мне всегда было не понятна сама суть команды "поиск ROM"(F0h),

ну определил я кол-во датчиков, ну знаю темпеатуру каждого,

НО где какой датчик-то неизвесно.

Проще знать идентификационный номер каждого датчика и место его расположения и

обращаться к каждому датчику индивидуально командой(55h).

 

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

И ещё - а какие адреса у "призраков"? Это может помочь найти грабли - один фиг вам нужно эти адреса запоминать, как заметили выше.

Я эти датчики опрашивал по одному через SKIP ROM для определения адреса.

 

Если геморрой с адресами не нужен, и датчиков не много - можно их по одному повесить, каждый на свою шину.

Изменено пользователем Dx!

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

А что мешает работать прямо по адресам и не использовать неработающую функцию поиска?

Для этого нужно в коде программы прописать эти датчики.

Использую я 4 датчика. И получиться что если датчик сдохнет то нужно перепрошивать проц.

 

Вы резервируете память malloc(8) только под один слэйв.

 

UPD: разглядел.

      CurrentAddr +=7;                            // Следующий адрес
      malloc(7);                                // Зарезервировать память под ROM

Предпочитаете грабли с тщательно отполированными ручками?

 

А скорее всего на 4-ом слэйве при malloc() просто наезжаете на стэк.

 

      malloc(7);                                // Зарезервировать память под ROM

[/code]

 

но функция next вызывается несколько раз и каждый раз когда найдено новое устройство резервируется память

 

А почему я должен наехать на Стэк. Я HEAP большой делаю

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Использую я 4 датчика. И получиться что если датчик сдохнет то нужно перепрошивать проц.

Вам просто намекают, что после обнаружения датчиков нужно еще выполнить и их привязку в пространстве. (возможно, Вы уже решили эту задачу)

но функция next вызывается несколько раз и каждый раз когда найдено новое устройство резервируется память

Я заметил, но чуть позже.

А почему я должен наехать на Стэк. Я HEAP большой делаю

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Вам просто намекают, что после обнаружения датчиков нужно еще выполнить и их привязку в пространстве. (возможно, Вы уже решили эту задачу)

 

Я заметил, но чуть позже.

 

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

 

Вот этого я и опасаюсь - физики процесса.

Хотя думаю, что в самом деле для моей конструкции будет лучше обращаться непосредственно по имени к датчику и не делать поиска.

 

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Хотя думаю, что в самом деле для моей конструкции будет лучше обращаться непосредственно по имени к датчику и не делать поиска.

Или выделить четыре ножки а не одну, если предполагается замена.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Сделал все без поиска. Но все равно 2 датчика работают нормально, как только вешаю еще 2 сразу зависает проц.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

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

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

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

×
×
  • Создать...