Jump to content

    
Sign in to follow this  
SortoVaritu

DS18b20 и Atmega128

Recommended Posts

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

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

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

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

 

Share this post


Link to post
Share on other sites

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

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

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

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

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

Share this post


Link to post
Share on other sites
Прекрасно изложена суть проблемы - без подробностей...

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

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

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

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

 

 

Схема включения очень проста. Питание берется +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)

 

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

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

 

Share this post


Link to post
Share on other sites

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

 

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

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

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

 

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

Share this post


Link to post
Share on other sites

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

Edited by Dx!

Share this post


Link to post
Share on other sites
в теле программы вызываю процедуру поиска датчиков

OW_cnt_device(void)

 

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

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

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

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

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

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

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

 

 

Share this post


Link to post
Share on other sites

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

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

 

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

Edited by Dx!

Share this post


Link to post
Share on other sites
А что мешает работать прямо по адресам и не использовать неработающую функцию поиска?

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

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

 

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

 

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

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

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

 

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

 

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

[/code]

 

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

 

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

Share this post


Link to post
Share on other sites
Использую я 4 датчика. И получиться что если датчик сдохнет то нужно перепрошивать проц.

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

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

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

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

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

Share this post


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

 

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

 

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

 

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

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

 

 

Share this post


Link to post
Share on other sites
Хотя думаю, что в самом деле для моей конструкции будет лучше обращаться непосредственно по имени к датчику и не делать поиска.

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

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Sign in to follow this