iiv 29 28 ноября, 2011 Опубликовано 28 ноября, 2011 · Жалоба Всем привет, имеется атмега328п, хочется к ней прикрутить несколько, от одного до четырех, датчиков температуры DS18B20 по 1-wire. Незадачка в том, что эта атмега должна в реальном времени выполнять кучу другой работы, которую нельзя прерывать 100мкс-750мс ожиданиями протокола 1-wire. В то же время, как я понимаю из прочтения исходников протокола общения с этими датчиками, большую часть времени микроконтроллер должен ждать. Возникает идея, что этот протокол может быть реализован на прерываниях таймера и int0 (я могу повесить 1-wire на эту ножку) и практически не занимать время процессора, но программировать это может быть довольно не тривиально. Скажите, пожалуйста, может кто-то уже такое запрограммировал, и такие исходники существуют в сети? Если да, тыкните, пожалуйста, пальцем где скачать. Если нет, может я в чем-то ошибаюсь и это не так просто, как мне кажется? Знаю, что есть еще решение - поставить на плату тиньку или еще одну ардуину, которая будет 100% занята опросами этой температуры, но очень не хотелось бы это делать. Спасибо ИИВ Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Birden 0 28 ноября, 2011 Опубликовано 28 ноября, 2011 (изменено) · Жалоба Вариантов реализации 1-Wire довольно много - выбирай любой. И ждать там совсем незачем, принцип простой: раз в секунду (например) прочитали температуру, потом сразу же отправили команду на преобразование. К следующей секунде преобразование как раз будет готово. А вообще, прерывания там желательно запрещать только на время приема/отправки одного бита. Изменено 28 ноября, 2011 пользователем birden Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ARV 1 28 ноября, 2011 Опубликовано 28 ноября, 2011 · Жалоба 100 мкс - 750 мкс ждать никогда не нужно с запрещенными прерываниями. запрет прерываний требуется на 15-60 мкс максимум, так что сколько-нибудь заметного влияния на фоновые процессы обмен 1-wire не должен оказать Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Палыч 10 28 ноября, 2011 Опубликовано 28 ноября, 2011 · Жалоба Возникает идея, что этот протокол может быть реализован на прерываниях таймера и int0 (я могу повесить 1-wire на эту ножку) и практически не занимать время процессора, но программировать это может быть довольно не тривиально. Да, такая реализация вполне возможна. Я не представляю: зачем Вам int0 ? Я без него обошелся, одним таймером... Надавно встретилась в инете статья про использование в целях работы по 1-wire USART (если есть свободный). Работает USART фактически как таймер (скорость передачи настраивается так, что время передачи байта - нужное для реализации протокола 1-wire), но, ещё и импульсы на Tx формирует... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
iiv 29 28 ноября, 2011 Опубликовано 28 ноября, 2011 · Жалоба 100 мкс - 750 мкс ждать никогда не нужно с запрещенными прерываниями. запрет прерываний требуется на 15-60 мкс максимум, так что сколько-нибудь заметного влияния на фоновые процессы обмен 1-wire не должен оказать на сколько понимаю, 5-10мкс (или все-таки 60 мкс?) мне надо ждать для передачи одного бита, а передавать надо где-то 16 байт, то есть на момент коммуникации мне надо выделить 1-2 милисекунду. Вот их-то я и не готов выделить, так как в реальном времени у меня с 6 портов идут конвертации с АЦП и на результаты мне надо реагировать незамедлительно. Термодатчики хочу вкрячить на силовые модули, чтобы мониторить нагрев мосфетов во время работы... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ILYAUL 0 28 ноября, 2011 Опубликовано 28 ноября, 2011 · Жалоба Надавно встретилась в инете статья про использование в целях работы по 1-wire USART (если есть свободный). Работает USART фактически как таймер (скорость передачи настраивается так, что время передачи байта - нужное для реализации протокола 1-wire), но, ещё и импульсы на Tx формирует... Изумительно хорошо работает. При этом можно точно определить, когда датчик готов выдать результат на гора. Обычно он делает это быстрее , чем 750мс раз в секунду (например) прочитали температуру Это перебор , если конечно датчик чем-то не нагревать в течении секунды Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Леонид Иванович 0 28 ноября, 2011 Опубликовано 28 ноября, 2011 (изменено) · Жалоба или все-таки 60 мкс? Если делать всё корректно, то 60 мкс. Тайм-слот надо полностью закончить, а только потом разрешать прерывания, иначе передача нуля может затянуться и это будет воспринято как сброс. Ну и после сброса чтение ответа устройства делается примерно через 65 мкс, тут без запрещенных прерываний никак. Можно поделить работу с датчиками на элементарные операции, каждая из которых будет не длиннее 60 мкс. Ведь между тайм-слотами задержка не ограничивается. Я делал что-то подобное, но делил на байты, Вам же нужно поделить на биты: //---------------------------------------------------------------------------- //DSS-90 //Модуль обслуживания термометра DS18B20 //Цифровой датчик температуры DS18B20 подключен по 1-проводному //интерфейсу, который реализован программно. //Для подключения датчика используется порт OWP. //Порт должен быть настроен на ввод, //внутренний подтягивающий резистор должен быть отключен, //используется внешний подтягивающий резистор 4.7 кОм. //Во время измерения обеспечивается сильноточная //подтяжка линии данных (порт переключается на вывод ВЫСОКОГО уровня), //поэтому возможно использование термометра с паразитным питанием. //Должны быть определены следующие макросы: //#define OWP (1 << Pxn) //#define Port_OWP_OUT (DDRx |= OWP) //#define Port_OWP_IN (DDRx &= ~OWP) //#define Pin_OWP (PINx & OWP) //Датчик DS18B20 должен быть запрограммирован в 12-разрядный режим //(биты R0, R1 в регистре конфигурации равны единице, //это заводская установка). //Дискретность измерения температуры составляет 0.1°C. //Из датчика считываются только 2 байта, CRC не проверяется. //Для инициализации модуля один раз в начале программы должна //вызываться функция DS18B20_Init(). Функция DS18B20_Exe() должна //вызываться в основном цикле, она осуществляет запуск преобразования, //формирует в фоновом режиме временную задержку и производит считывание //температуры во внутреннюю переменную Temp. //Поскольку обмен по однопроводной шине довольно медленный (чтение или //запись одного байта занимает порядка 0.5 мс), целиком выполнять //чтение температуры и запуск преобразования за один вызов DS18B20_Exe() //нельзя. Это может нарушить выполнение других задач. Поэтому процесс //обмена с термометром разбит на элементарные операции, каждая из //которых включает в себя обмен не более чем одним байтом. //Значение температуры в любой момент может быть считано с помощью функции //DS18B20_GetT(). Значение представлено в виде 16-разрядного целого числа //со знаком и представляет собой температуру в десятых долях градуса. //До того, как закончится первое преобразование температуры, возвращается //значение T_NORDY. В случае отсутствия ответа термометра возвращается //код ошибки T_ERROR. //---------------------------------------------------------------------------- #include "Main.h" #include "DS18B20.h" //------------------------------ Константы: ---------------------------------- #define TCONV 800 //время преобразования температуры, мс //----------------------------- Переменные: ---------------------------------- static int Temp; //текущая температура static char TState; //состояние процесса измерения //-------------------------- Прототипы функций: ------------------------------ bool TReset(void); //формирование импульса сброса char TByte(char dat); //запись/чтение байта bool TBit(bool B); //запись/чтение бита //--------------------- Инициализация термометра: ---------------------------- void DS18B20_Init(void) { Temp = T_NORDY; //результат измерения не готов TState = 0; //начало процесса } //----------------------- Измерение температуры: ----------------------------- void DS18B20_Exe(bool t) { static int TTimer = 0; //таймер термометра static int T; //код температуры if(t) { if(TTimer) //если интервал таймера не истек, { TTimer--; //ожидание (и декремент таймера) } else //иначе выполнение шага { switch(TState) { case 0: if(TReset()) //команда RESET TState++; //если выполнена успешно, следующий шаг else TState = 0xFF; //если ошибка, переход на задержку break; case 1: TByte(0xCC); //команда SKIP ROM TState++; //следующий шаг break; case 2: TByte(0x44); //команда START CONVERSION TTimer = ms2sys(TCONV); //загрузка задержки преобразования TState++; //следующий шаг break; case 3: if(TReset()) //команда RESET TState++; //если выполнена успешно, следующий шаг else TState = 0xFF; //если ошибка, переход на задержку break; case 4: TByte(0xCC); //команда SKIP ROM TState++; //следующий шаг break; case 5: TByte(0xBE); //команда READ SCRATCHPAD TState++; //следующий шаг break; case 6: T = TByte(0xFF); //чтение TL TState++; //следующий шаг break; case 7: T |= TByte(0xFF) << 8; //чтение TH TState++; //следующий шаг break; case 8: Temp = 10 * T / 16; //вычисление температуры TState = 0; //переход на первый шаг break; default: TTimer = ms2sys(TCONV); //загрузка задержки Temp = T_ERROR; //код ошибки TState = 0; //переход на первый шаг } } } } //--------------------- Генерация импульса сброса: --------------------------- bool TReset(void) { char si; Port_OWP_0; Port_OWP_OUT; //OWP <- 0 Delay_us(500); //delay 500 uS si = __save_interrupt(); __disable_interrupt(); //запрещение прерываний Port_OWP_IN; //OWP <- 1 Delay_us(14); //delay 14 uS if(Pin_OWP) //если OWP = 0, то ошибка { Delay_us(52); //delay 52 uS if(!Pin_OWP) //если OWP = 1, то ошибка { __restore_interrupt(si); //восстанавление прерываний Delay_us(250); //delay 250 uS if(Pin_OWP) //если OWP = 0, то ошибка { return(1); //если ошибок нет, термометр присутствует } } } __restore_interrupt(si); //восстанавление прерываний в случае ошибки return(0); } //-------------- Запись/чтение байта по однопроводной шине: ------------------ char TByte(char dat) { char res; for(char i = 0; i < 8; i++) { res = res >> 1; if(TBit(dat & 1)) res |= 0x80; else res &= ~0x80; dat = dat >> 1; } return(res); } //--------------- Запись/чтение бита по однопроводной шине: ------------------ bool TBit(bool B) { char si; si = __save_interrupt(); __disable_interrupt(); //запрещение прерываний Port_OWP_0; Port_OWP_OUT; //OWP <- 0 Delay_us(2); //delay 2 uS if(B) Port_OWP_IN; //bit = 1, OWP <- 1 Delay_us(13); //delay 13 uS bool owp = Pin_OWP; //чтение порта Delay_us(45); //delay 45 uS Port_OWP_1; //force pullup Port_OWP_OUT; __restore_interrupt(si); //восстанавление прерываний Delay_us(2); //delay 2 uS return(owp); } //------------------------- Чтение температуры: ------------------------------ int DS18B20_GetT(void) { return(Temp); } //---------------------------------------------------------------------------- Изменено 28 ноября, 2011 пользователем IgorKossak [codebox] Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
e-serg 0 28 ноября, 2011 Опубликовано 28 ноября, 2011 · Жалоба на сколько понимаю, 5-10мкс (или все-таки 60 мкс?) можно глянуть тут исходники, они на ассемблере, зато сама программа в реальном времени сканирует клавиатурную матрицу 4х4, с помощью динамической индикации работает со светодиодной матрицей 4х4х2 двухцветные диоды, читает таблетку 1-wire, сама прикидывается подчинееным 1-wire устройством, все одновременно без паразитных подмаргиваний индикации при работе 1-wire интерфейсов. http://electronix.ru/forum/index.php?showt...st&p=672770 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
iiv 29 28 ноября, 2011 Опубликовано 28 ноября, 2011 · Жалоба Если делать всё корректно, то 60 мкс. Тайм-слот надо полностью закончить, а только потом разрешать прерывания, иначе передача нуля может затянуться и это будет воспринято как сброс. Ну и после сброса чтение ответа устройства делается примерно через 65 мкс, тут без запрещенных прерываний никак. Можно поделить работу с датчиками на элементарные операции, каждая из которых будет не длиннее 60 мкс. Ведь между тайм-слотами задержка не ограничивается. Я делал что-то подобное, но делил на байты, Вам же нужно поделить на биты: Огромное Вам спасибо, Леонид Иванович, я чувствовал, что так оно и должно быть, но, не сильно хорошо владея предметом, возможно не совсем понятно задал вопрос... Надеюсь, что в 45мкс задержку смогу положить несколько других важных операций, длительность которых мне полностью известна. Опрашивать по-видимому надо будет 5 датчиков, буду разбираться хватит ли у меня свободных ног для этого... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Палыч 10 28 ноября, 2011 Опубликовано 28 ноября, 2011 · Жалоба Изумительно хорошо работает. Для проектов, где есть свободный UART у Maxim из AN214 можно позаимствовать идею использования UART для реализации 1-wire Bus Master Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ILYAUL 0 28 ноября, 2011 Опубликовано 28 ноября, 2011 · Жалоба Для проектов, где есть свободный UART у Maxim из AN214 можно позаимствовать идею использования UART для реализации 1-wire Bus Master У MAXIM чего только нет. Так например для Ds18x20 отдельный application, но я делал по ATMEL - хорошо расписан USART для 1- wire / И даже где-то встречал русский перевод какого-то из этих applications. Applications.rar Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
pavel-pervomaysk 0 29 ноября, 2011 Опубликовано 29 ноября, 2011 · Жалоба По одному проводу 4 датчика часто читать нельзя, перегреваются они, да и не получится физически, на каждый уйдет примерно 1 сек. Я бы поставил отдельно тиньку и загрузил бы ее этой работой, после этого через UART уже командовать ней. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ARV 1 29 ноября, 2011 Опубликовано 29 ноября, 2011 · Жалоба По одному проводу 4 датчика часто читать нельзя, перегреваются они, да и не получится физически, на каждый уйдет примерно 1 сек.не на каждый уйдет 1 сек, а на все сразу. думаю, пару десятков датчиков за 1 секунду можно успеть опросить :) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
iiv 29 29 ноября, 2011 Опубликовано 29 ноября, 2011 · Жалоба не на каждый уйдет 1 сек, а на все сразу. думаю, пару десятков датчиков за 1 секунду можно успеть опросить :) ага, я уже 5 прикрутил, без основного софта на основе one-wire.cpp и все в секунду укладывается, но вот в параллель-то конечно надо все аккуратно расписать... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ILYAUL 0 30 ноября, 2011 Опубликовано 30 ноября, 2011 · Жалоба ага, я уже 5 прикрутил, без основного софта на основе one-wire.cpp и все в секунду укладывается, но вот в параллель-то конечно надо все аккуратно расписать... Почему параллель? До начала чтения данных с датчиков , Вы работаете со всеми сразу игнорируя ID микросхем, а вот чтение для каждого своё. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться