kostya_unix Опубликовано 19 февраля, 2019 Поделиться Опубликовано 19 февраля, 2019 Здравствуйте форумчане. При изучении датчика DS18B20 и разбора протокола 1-wire столкнулся с такой проблемой. В функции инициализации ( в частности определения присутствия датчика на шине), при выставлении временных задержек (по даташиту: PORTC (к которому подключен вывод датчика DQ) 490 мкс импульс сброса (PORTC = 0), переводим PORTC на вход, ожидаем 68 мкс для того, что бы шина успела подтянутся к 1 (через сопротивление 4,7 кОм, "ловим" импульс присутствия датчика, т.е. он должен "просадить" шину в ноль. И эту просадку (ноль) должна зафиксировать ранее созданная переменная для последующей обработки (присутствует датчик или нет. Собственно с этого вопросы и начались. Если все установлено как пишется в уроках ( потенциал сопротивления между плюсом о шиной данных датчика 4,7 кОм, временные интервалы тайм пласта инициализации (по даташиту), то переменная не фиксирует ответ (просадку к 0) от датчика, НО если увеличить сопротивление с 4,7 кОм до 6,8 кОм и вместо ожидания 68 мкс установить ассемблеровскую вставку NOP, тогда датчик определяется (отвечает просадкой к 0) и программно датчик виден (если вывод DQ на "горячую" вынуть из макетной платы, в программе срабатывает условие if(); В чем причина такого никак не могу взять в толк. Работаю в AVR_studio на C, м.к. ATmega 16, грешил на неисправность датчика, но потом купил второй такой же(предварительно проверив его на исправность в магазине). Буду признателен за помощь и конструктивную критику. PS: прошелся по все 30 страницам заголовков форума, именно про такую проблему так и не нашел. Это код функции инициализации: unsigned char OK_Flag; void DS18B20_init(void) { DDRB |= (1<<PB0); // просадили шину на 0 PORTB &= ~(1<<PB0); _delay_ms(500); PORTB &= ~(1<<PB0); DDRB &= ~(1<<PB0); // 0 перевели порт на вход для приема сигнала с датчика //_delay_us(68); //делаем задержку для "подъема" логической еденицы(через сопротивление) asm volatile ("nop"); OK_Flag = (PINB &(1<<PB0)); _delay_us(422); return OK_Flag; //возвращаем значение переменно в программу } int main(void) { set_port_led(); while(1) { DS18B20_init(); if (!(OK_Flag == 0)) { PORTA &= ~(1<<PA0); //если датчик отвечает(исправен),зеленый свет выключен. } else { PORTA |= (1<<PA0); } } } 0 Ссылка на комментарий Поделиться на другие сайты Поделиться
snn_krs Опубликовано 19 февраля, 2019 Поделиться Опубликовано 19 февраля, 2019 8 hours ago, kostya_unix said: _delay_ms(500); Может быть микросекунд ? 0 Ссылка на комментарий Поделиться на другие сайты Поделиться
20% скидка на весь каталог электронных компонентов в ТМ Электроникс!Акция "Лето ближе - цены ниже", успей сделать выгодные покупки!Плюс весь апрель действует скидка 10% по промокоду APREL24 + 15% кэшбэк и бесплатная доставка!Перейти на страницу акции Реклама: ООО ТМ ЭЛЕКТРОНИКС, ИНН: 7806548420, info@tmelectronics.ru, +7(812)4094849
kostya_unix Опубликовано 19 февраля, 2019 Автор Поделиться Опубликовано 19 февраля, 2019 7 часов назад, snn_krs сказал: Может быть микросекунд ? Да. Спасибо. Исправил (_delay_us(68);). Но пока все по прежнему. Сегодня постараюсь приобрести новый м.к и заменить. Может в порыве вдохновения подпалил подтягивающие сопротивления внутри него.... 0 Ссылка на комментарий Поделиться на другие сайты Поделиться
Выбираем схему BMS для корректной работы литий-железофосфатных (LiFePO4) аккумуляторов Обязательным условием долгой и стабильной работы Li-FePO4-аккумуляторов, в том числе и производства EVE Energy, является применение специализированных BMS-микросхем. Литий-железофосфатные АКБ отличаются такими характеристиками, как высокая многократность циклов заряда-разряда, безопасность, возможность быстрой зарядки, устойчивость к буферному режиму работы и приемлемая стоимость. Но для этих АКБ, также как и для других, очень важен контроль процесса заряда и разряда, а специализированных микросхем для этого вида аккумуляторов не так много. Инженеры КОМПЭЛ подготовили список имеющихся микросхем и возможных решений от разных производителей. Подробнее>> Реклама: АО КОМПЭЛ, ИНН: 7713005406, ОГРН: 1027700032161
kostya_unix Опубликовано 22 февраля, 2019 Автор Поделиться Опубликовано 22 февраля, 2019 Еще раз всем здравствуйте. Продолжаю бороться с инициализацией DS18B20. Купил вчера два новых м.к. ATmega16 и ATmega8. Пробовал как один так и другой и все безрезультатно. Верней не то, что бы совсем безрезультатно (так же как описывал проблему в самом начале( при _delay_us(68); не видит датчик, а если использую asm volatile ("nop"); тогда датчик определяется)). Пробовал на частотах от 1 до 8 мГц. Питание подвал как от блока питания, так и непосредственно с USB_программатора. Осталось попробовать ECLIPSE под Linux, может, что то с AVRStudio? Не могу никак взять в толк...... 0 Ссылка на комментарий Поделиться на другие сайты Поделиться
Alex Опубликовано 22 февраля, 2019 Поделиться Опубликовано 22 февраля, 2019 Код покажите. Трудно помочь, ориентируясь на одни лишь догадки. 0 Ссылка на комментарий Поделиться на другие сайты Поделиться
IMXO Опубликовано 22 февраля, 2019 Поделиться Опубликовано 22 февраля, 2019 зачем это Цитата void DS18B20_init(void) { .... ....return OK_Flag; //возвращаем значение переменно в программу } ???? Цитата Функция типа void применение ключевого слова void является явное объявление функций, которые не возвращают значений. такие функции не могут применяться в выражениях, и указание ключевого слова void предотвращает их случайное использование не по назначению. 0 Ссылка на комментарий Поделиться на другие сайты Поделиться
kostya_unix Опубликовано 24 февраля, 2019 Автор Поделиться Опубликовано 24 февраля, 2019 Спасибо всем за участие. Вот код программы (функцию немного изменил ( для чистоты эксперимента)). #define F_CPU 8000000UL // указываем частоту #include <avr/io.h> #include <util/delay.h> void set_port_led(void) { DDRD = 0b00000001; PORTD =0b00000000; } void DS18B20_init(void) { DDRC |= (1<<PC0); // просадили шину на 0 PORTC &= ~(1<<PC0); _delay_us(490); // время просадки на 0 DDRC &= ~(1<<PC0); // 0 перевели порт на вход для приема сигнала с датчика //_delay_us(68); //делаем задержку для "подъема" логической еденицы(через сопротивление) //и ожидаем сигнал присутствия датчика (датчик просаживает на 0 шину //данных. asm volatile ("nop"); if (!(PINC &(1<<PC0)) == 0) // если не равен нулю { PORTD |= (1<<PD0); //красный светодиод горит (датчик отсутствует) } else { PORTD &= ~(1<<PD0); //не горит } _delay_us(422); } int main(void) { set_port_led(); while(1) { DS18B20_init(); } } 0 Ссылка на комментарий Поделиться на другие сайты Поделиться
Armenn Опубликовано 24 февраля, 2019 Поделиться Опубликовано 24 февраля, 2019 On 19.02.2019 at 9:49 AM, kostya_unix said: для того, что бы шина успела подтянутся к 1 По скольким проводам подключаете датчик? Два или три? 0 Избегайте тех, кто старается подорвать вашу веру в себя. Эта черта свойственна мелким людям. Великий человек, наоборот, внушает чувство, что вы можете стать великим. (Марк Твен) Ссылка на комментарий Поделиться на другие сайты Поделиться
kostya_unix Опубликовано 25 февраля, 2019 Автор Поделиться Опубликовано 25 февраля, 2019 Только что, Armenn сказал: По скольким проводам подключаете датчик? Два или три? По трем проводам. Красный на плюс, черный минус, желтый передача данных (подтянут через сопротивление к питанию). Датчик в герметичном корпусе. 0 Ссылка на комментарий Поделиться на другие сайты Поделиться
Armenn Опубликовано 25 февраля, 2019 Поделиться Опубликовано 25 февраля, 2019 Без сопротивления 4,7к что происходит? 0 Избегайте тех, кто старается подорвать вашу веру в себя. Эта черта свойственна мелким людям. Великий человек, наоборот, внушает чувство, что вы можете стать великим. (Марк Твен) Ссылка на комментарий Поделиться на другие сайты Поделиться
kostya_unix Опубликовано 26 февраля, 2019 Автор Поделиться Опубликовано 26 февраля, 2019 (изменено) 41 минуту назад, Armenn сказал: Без сопротивления 4,7к что происходит? Здравствуйте Armenn. Спасибо за соучастие в решении моей проблемы! После того как отсоединяешь сопротивление 4,7 кОм контроллер реагирует на отключение сигнального провода датчика. Но светодиод горит тускло, точней не то что бы тускло, а с определенной (большой) частотой включается и выключается. НО в моих попытках докопаться до истины, появились сдвиги. Как и писал ранее, переписал код инициализации датчика в eclipse, и все заработало так как и должно. И с сопротивлением 4,7к и с "правильным" использованием _delay_us(); (asm "nop" не использовал). Вот как то так..... Сейчас пытаюсь понять почему в AVR_studio прошивка не работала так как надо (может быть оптимизация кода в studio имеет место быть?). Буду дальше изучать как DS18D20, так и протокол 1-wire. Еще раз спасибо большое всем, кто помогал мне. Изменено 26 февраля, 2019 пользователем kostya_unix 0 Ссылка на комментарий Поделиться на другие сайты Поделиться
kostya_unix Опубликовано 28 февраля, 2019 Автор Поделиться Опубликовано 28 февраля, 2019 После смены среды разработки продолжил изучение функции инициализации датчик ( формирование импульса присутствия) и некоторого исправления (уточнения) моего кода выложенного ранее . Опытным товарищам продолжение этой темы может показаться не интересным, но это может избавить начинающих от некоторых проблем или внести дополнительную ясность. Итак вот что узнал..... Т.к. все подключенные к шине устройства имеют выходы с открытым стоком, то для формирования логической 1 на шине используется подтягивающее сопротивление (4,7 кОм) Для инициализации всех подключенных ведомых устройств (датчиков), м.к. сначала формирует импульс сброса, логический ноль на шине данных, не менее 480 мкс, для того что бы после формирования положительного перепада датчики смогли ответить импульсом присутствия. После импульса сброса от м.к. временем нарастания единицы можно пренебречь (1 мкс.) в моем коде это было ошибочно обозначено как: _delay_us(68); //делаем задержку для "подъема" логической единицы(через сопротивление) и ожидаем сигнал присутствия датчика (датчик просаживает на 0 шину данных). Когда датчик определил положительный перепад (от ноля к единице), он ожидает от 15 до 60 мкс и затем формирует импульс присутствия устанавливая на шине данных логический ноль на время от 60 до 240 мкс. Так что импульс присутствия может начаться, самое позднее через 60 мкс от завершения импульса сброса и может закончится, самое ранее, через (15+60) = 75 мкс от завершения импульса сброса м.к. Для считывания импульса присутствия от датчика, выбираем среднее значение (60~70) = 68 мкс. Общее время импульса присутствия датчика не менее 480 мкс (68 мкс+412 мкс) 0 Ссылка на комментарий Поделиться на другие сайты Поделиться
Berg Опубликовано 28 февраля, 2019 Поделиться Опубликовано 28 февраля, 2019 480 60 420 проблем не замечал 0 Ссылка на комментарий Поделиться на другие сайты Поделиться
kostya_unix Опубликовано 27 мая, 2019 Автор Поделиться Опубликовано 27 мая, 2019 Всем здравствуйте. На днях вывел первые показания температуры с DS18B20 на LED_индикатор (пока правда без знака + или -). Долго шел к этому результату, не забрасывал изучение. Советовался только с вами форумчанами (больше нескем было). Спасибо большое всем кто помогал, кто участвовал в обсуждении моего вопроса. По возможности буду и дальше информировать о дальнейшем ходе изучения. Продолжение будет в изучении определения знака температуры., считывания ROM кода датчика( с выводом на дисплей) ну и так далее. 0 Ссылка на комментарий Поделиться на другие сайты Поделиться
kostya_unix Опубликовано 7 июня, 2019 Автор Поделиться Опубликовано 7 июня, 2019 Здравствуйте всем. Вчера разобрался с расчетом отрицательной температуры..... Это окажется полезным особенно начинающим в разборе этих расчетах. И так..... Для начинающих (как я) формулы в примерах не всегда понятны (хотя работают на 100%), по причине несовершенного владения битовыми сдвигами. И что бы было более понятно и наглядно: T_L = dt_readbyte(); // считываем младшие 8 бит ( из 16 передаваемых датчиком значений температуры) T_H = dt_readbyte(): // считываем старшие 8 бит. для положительной температуры: temperatura = (((T_H<<8) | T_L) / 16) ; для отрицательной температуры: temperatura = ((65536 - temperatura)/16); // 65536 это максимально возможное значение 16 бит информации с датчика, и из этого // максимального значения мы вычитаем реальные значения датчика в промежуток времени. Пример: с датчика в момент времени мы получили значение (при условии, что мы определили знак температуры ( if (!((T_H & 128) ==0)); т.е. температура отрицательная) FECCh и если перевести в десятичное значение: 65228, тогда при этом решении (65536 - 65228) мы получаем 308 и разделив его на 16 (т.е сдвинув в право на 4 (>>4) , мы и получаем искомое значение отрицательной температуры. Ну вот как то так...... Если что-то не так в моем комментарии прошу более опытных пользователей меня поправить. Думаю, что от этого выиграют все. 0 Ссылка на комментарий Поделиться на другие сайты Поделиться
ARV Опубликовано 7 июня, 2019 Поделиться Опубликовано 7 июня, 2019 (изменено) В вашем подходе много чего не так. Есть вещи несущественные, а есть принципиальные. Код не показан целиком, так что частично буду гадать. 1. Побайтное чтение температуры настораживает: разве вы не считываете все 9 байтов scratchpad-ОЗУ датчика? Разве вы не считаете CRC этих 9-и байт? 2. Метод станных манипуляций с байтами (сдвиги и т.п.) совершенно лишний: датчик выдает температуру в формате int16_t, т.е. 16-битное целочисленное значение в долях градуса. А вот величина доли зависит от режима работы датчика, и в 12-битном варианте составляет 1/16 градуса. То есть считанные 2 байта представляют собой обычное число int, которое надо разделить на 16, чтобы получить температуру сразу со знаком в градусах. Только делать это можно лишь в случае, если CRC всех 9 байтов встроенной блокнотной памяти корректна. Изменено 7 июня, 2019 пользователем ARV 0 Если забанить всех, кто набрался смелости думать независимо, здорово будет на форуме - как на кладбище: тишина, птички поют... Ссылка на комментарий Поделиться на другие сайты Поделиться
kostya_unix Опубликовано 8 июня, 2019 Автор Поделиться Опубликовано 8 июня, 2019 22 часа назад, ARV сказал: В вашем подходе много чего не так. Есть вещи несущественные, а есть принципиальные. Код не показан целиком, так что частично буду гадать. 1. Побайтное чтение температуры настораживает: разве вы не считываете все 9 байтов scratchpad-ОЗУ датчика? Разве вы не считаете CRC этих 9-и байт? 2. Метод станных манипуляций с байтами (сдвиги и т.п.) совершенно лишний: датчик выдает температуру в формате int16_t, т.е. 16-битное целочисленное значение в долях градуса. А вот величина доли зависит от режима работы датчика, и в 12-битном варианте составляет 1/16 градуса. То есть считанные 2 байта представляют собой обычное число int, которое надо разделить на 16, чтобы получить температуру сразу со знаком в градусах. Только делать это можно лишь в случае, если CRC всех 9 байтов встроенной блокнотной памяти корректна. Вы знаете, я еще не очень хорошо разбираюсь во всех командах датчика ( изучаю самостоятельно). Датчик у меня один. Я подаю команду на преобразование температуры (0x44). Собственно с этими данными и работаю. Если Вас не затруднит, подскажите пожалуйста как считать все 9 байт с датчика. Я так понимаю, что без массива тут не обойтись? Заранее благодарен. Привожу функцию с помощью которой общаюсь с датчиком. signed int dt_check(void) { DS18B20_reset(); // презагружаем (сброс\присутствие) датчик. dt_sendbyte(204); // (0xCC) (skip rom) пропускаем идентификацию, т.к. датчик один dt_sendbyte(68); // (0x44) измерить температуру _delay_ms(750); // такая задержка нужна для 12-ти битного ПРЕОБРАЗОВАНИЯ (это максимальная задержка) DS18B20_reset(); // презагружаем (сброс\присутствие) датчик. Инициализация нужна для того, что бы // датчик понял, что ему сейчас будет послана команда. dt_sendbyte(204); // (0xCC) (skip rom) пропускаем идентификацию dt_sendbyte(190); // (0xBE) (convert t) отправляем команду на чтение показаний с датчика T_L = dt_readbyte(); // читаем младший байт регистра температуры T_H = dt_readbyte(); // читаем старший байт регистра температуры tt = (((T_H<<8)|T_L)*10); // общий результат полученого значения (кода) с датчика // вывод знака при положительной и отрецательной температуре if ((T_H & 128) ==0) { // положительная температура znack = 32;// знак пробел при положительной температуре } else { // отрицательная температура tt = (65536-tt); // формула расчета отрицательной температуры znack = 45;// знак минус } return tt; } 0 Ссылка на комментарий Поделиться на другие сайты Поделиться
ARV Опубликовано 8 июня, 2019 Поделиться Опубликовано 8 июня, 2019 2 часа назад, kostya_unix сказал: как считать все 9 байт с датчика Да как угодно. Размется, с массивом удобно: сделал цикл с чтением в массив, и все. Но можно и без массива (аж 9 байт ОЗУ скономите) - так, как вы, байт а байтом читать разными командами. Но это не красиво... 0 Если забанить всех, кто набрался смелости думать независимо, здорово будет на форуме - как на кладбище: тишина, птички поют... Ссылка на комментарий Поделиться на другие сайты Поделиться
Starichok Опубликовано 8 июня, 2019 Поделиться Опубликовано 8 июня, 2019 8 часов назад, ARV сказал: Но можно и без массива (аж 9 байт ОЗУ скономите) а массив, по-твоему, занимает НОЛЬ байт? 0 Мудрость приходит вместе с импотенцией... Когда на русском форуме переходят на Вы, в реальной жизни начинают бить морду. Ссылка на комментарий Поделиться на другие сайты Поделиться
Alex Опубликовано 8 июня, 2019 Поделиться Опубликовано 8 июня, 2019 Дак и речь то об том, что БЕЗ МАССИВА сэкономят. PS: @Starichok , что то ты сдавать стал 0 Ссылка на комментарий Поделиться на другие сайты Поделиться
ARV Опубликовано 8 июня, 2019 Поделиться Опубликовано 8 июня, 2019 @Starichok, своих надо знать в лицо я на таких простых темах никогда не ошибаюсь. 0 Если забанить всех, кто набрался смелости думать независимо, здорово будет на форуме - как на кладбище: тишина, птички поют... Ссылка на комментарий Поделиться на другие сайты Поделиться
Starichok Опубликовано 9 июня, 2019 Поделиться Опубликовано 9 июня, 2019 видимо, ночью я неправильно понял смысл сказанного... но что-то и с утра мне плохо соображается. если без массива, то куда будут помещены прочитанные 9 байт? в чем тут экономия? зы. вчера довелось быть на дне рождения. может, поэтому плохо соображается... 0 Мудрость приходит вместе с импотенцией... Когда на русском форуме переходят на Вы, в реальной жизни начинают бить морду. Ссылка на комментарий Поделиться на другие сайты Поделиться
kostya_unix Опубликовано 9 июня, 2019 Автор Поделиться Опубликовано 9 июня, 2019 1 час назад, Starichok сказал: видимо, ночью я неправильно понял смысл сказанного... но что-то и с утра мне плохо соображается. если без массива, то куда будут помещены прочитанные 9 байт? в чем тут экономия? зы. вчера довелось быть на дне рождения. может, поэтому плохо соображается... Здоровья вам (после вчерашнего). 0 Ссылка на комментарий Поделиться на другие сайты Поделиться
kostya_unix Опубликовано 9 июня, 2019 Автор Поделиться Опубликовано 9 июня, 2019 Большое спасибо всем, кто участвует в решении моего вопроса. Сразу оговорюсь, что изучаю микроконтроллеры самостоятельно, не имея предварительных навыков программирования, но имея много "прыти" и желания. У меня вопрос возник (как во время чтения даташит_а на датчик, так и во время просмотров кодов работы с датчиком на сайтах).... В даташит_е есть такие строки: Если DS18B20 включен с внешним питанием, ведущий может контролировать конвертирование температуры (после команды [0х44]) по состоянию шины. На шине будет присутствовать логический «0» когда происходит температурное преобразование. И логическая «1», когда конвертирование выполнено. То есть, можно ли пренебречь паузой в _delay_ms(750); (так как по умолчанию разрядность выставлена в 12 бит) и пользоваться только проверкой завершения конвертации? 0 Ссылка на комментарий Поделиться на другие сайты Поделиться
Starichok Опубликовано 9 июня, 2019 Поделиться Опубликовано 9 июня, 2019 дело в том, что при отработке паузы с помощью _delay_ms(750) МК больше НИЧЕГО в это время делать не может. это пустая трата процессорного времени. точнее, МК во время отработки паузы может обрабатывать прерывания. можно делать такую проверку. а можно и не делать. например, у меня полный приборный цикл равен 1 секунде. но я точно знаю (и ты это знаешь), что 1 секунду преобразование температуры гарантированно закончится. поэтому я без проверки считываю новую температуру и запускаю новую конвертацию. что должен делать твой прибор, я не знаю. могу только сказать, что окончательное решение ты должен выбрать сам. вариантов тут несколько. 1. тупо делать задержку с помощью delay. 2. тупо сидеть в цикле и по кругу проверять на завершение конвертации. этот вариант потребует те же самые 700-750 мс бесполезной потери времени. 3. делать, как я - 1 раз в секунду без проверки считывать новую температуру и запускать новую конвертацию. может, чья-то фантазия придумает еще другие способы... 0 Мудрость приходит вместе с импотенцией... Когда на русском форуме переходят на Вы, в реальной жизни начинают бить морду. Ссылка на комментарий Поделиться на другие сайты Поделиться
Рекомендуемые сообщения
Присоединяйтесь к обсуждению
Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.
Примечание: Ваш пост будет проверен модератором, прежде чем станет видимым.