SortoVaritu 0 7 ноября, 2010 Опубликовано 7 ноября, 2010 · Жалоба Использую в своем девайсе датчики DS18b20. Подключаю их на Atmega128. Столкнулся с проблемой 3 датчика работаю нормально но если подключить четвертый то все становитсяя наперекосяк. Процессор каждый раз видит как будто на шине датчиков не 4 а 10 или 14 или 30. Каждый раз поразному. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
demiurg_spb 0 7 ноября, 2010 Опубликовано 7 ноября, 2010 · Жалоба Прекрасно изложена суть проблемы - без подробностей... Какая схема включения? Как инициализируете контроллер? Как работаете с датчиком? Как питаете всё хозяйство? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
SortoVaritu 0 7 ноября, 2010 Опубликовано 7 ноября, 2010 · Жалоба Прекрасно изложена суть проблемы - без подробностей... Какая схема включения? Как инициализируете контроллер? Как работаете с датчиком? Как питаете всё хозяйство? Схема включения очень проста. Питание берется +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) и вот она мне ка раз и возвращает количество датчиков большое. Пробовал симулировать в Протеусе - все то же самое Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
xemul 0 7 ноября, 2010 Опубликовано 7 ноября, 2010 · Жалоба Вы резервируете память malloc(8) только под один слэйв. UPD: разглядел. CurrentAddr +=7; // Следующий адрес malloc(7); // Зарезервировать память под ROM Предпочитаете грабли с тщательно отполированными ручками? А скорее всего на 4-ом слэйве при malloc() просто наезжаете на стэк. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Dx! 0 7 ноября, 2010 Опубликовано 7 ноября, 2010 (изменено) · Жалоба А что мешает работать прямо по адресам и не использовать неработающую функцию поиска? Изменено 7 ноября, 2010 пользователем Dx! Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
domowoj 0 7 ноября, 2010 Опубликовано 7 ноября, 2010 · Жалоба в теле программы вызываю процедуру поиска датчиков OW_cnt_device(void) и вот она мне как раз и возвращает количество датчиков большое. Пробовал симулировать в Протеусе - все то же самое Вот мне всегда было не понятна сама суть команды "поиск ROM"(F0h), ну определил я кол-во датчиков, ну знаю темпеатуру каждого, НО где какой датчик-то неизвесно. Проще знать идентификационный номер каждого датчика и место его расположения и обращаться к каждому датчику индивидуально командой(55h). Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Dx! 0 7 ноября, 2010 Опубликовано 7 ноября, 2010 (изменено) · Жалоба И ещё - а какие адреса у "призраков"? Это может помочь найти грабли - один фиг вам нужно эти адреса запоминать, как заметили выше. Я эти датчики опрашивал по одному через SKIP ROM для определения адреса. Если геморрой с адресами не нужен, и датчиков не много - можно их по одному повесить, каждый на свою шину. Изменено 7 ноября, 2010 пользователем Dx! Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
SortoVaritu 0 7 ноября, 2010 Опубликовано 7 ноября, 2010 · Жалоба А что мешает работать прямо по адресам и не использовать неработающую функцию поиска? Для этого нужно в коде программы прописать эти датчики. Использую я 4 датчика. И получиться что если датчик сдохнет то нужно перепрошивать проц. Вы резервируете память malloc(8) только под один слэйв. UPD: разглядел. CurrentAddr +=7; // Следующий адрес malloc(7); // Зарезервировать память под ROM Предпочитаете грабли с тщательно отполированными ручками? А скорее всего на 4-ом слэйве при malloc() просто наезжаете на стэк. malloc(7); // Зарезервировать память под ROM [/code] но функция next вызывается несколько раз и каждый раз когда найдено новое устройство резервируется память А почему я должен наехать на Стэк. Я HEAP большой делаю Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
xemul 0 7 ноября, 2010 Опубликовано 7 ноября, 2010 · Жалоба Использую я 4 датчика. И получиться что если датчик сдохнет то нужно перепрошивать проц. Вам просто намекают, что после обнаружения датчиков нужно еще выполнить и их привязку в пространстве. (возможно, Вы уже решили эту задачу) но функция next вызывается несколько раз и каждый раз когда найдено новое устройство резервируется память Я заметил, но чуть позже. А почему я должен наехать на Стэк. Я HEAP большой делаю Ну если есть такая уверенность, то остаются расползающиеся фронты при увеличении ёмкости на шине, не укладывающиеся в заданные тайминги. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
SortoVaritu 0 7 ноября, 2010 Опубликовано 7 ноября, 2010 · Жалоба Вам просто намекают, что после обнаружения датчиков нужно еще выполнить и их привязку в пространстве. (возможно, Вы уже решили эту задачу) Я заметил, но чуть позже. Ну если есть такая уверенность, то остаются расползающиеся фронты при увеличении ёмкости на шине, не укладывающиеся в заданные тайминги. Вот этого я и опасаюсь - физики процесса. Хотя думаю, что в самом деле для моей конструкции будет лучше обращаться непосредственно по имени к датчику и не делать поиска. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Dx! 0 7 ноября, 2010 Опубликовано 7 ноября, 2010 · Жалоба Хотя думаю, что в самом деле для моей конструкции будет лучше обращаться непосредственно по имени к датчику и не делать поиска. Или выделить четыре ножки а не одну, если предполагается замена. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
SortoVaritu 0 7 ноября, 2010 Опубликовано 7 ноября, 2010 · Жалоба Сделал все без поиска. Но все равно 2 датчика работают нормально, как только вешаю еще 2 сразу зависает проц. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться