Шина 1-wire, пример термометра на DS18B20 и микроконтроллере AVR, WH1602, ЖКИ

Шина 1-Wire была запатентована компанией Dallas Semiconductor, и была призвана наладить полудуплексную связь всего по одному сигнальному проводу. Также возможны варианты использования паразитного питания по линии данных (потому что во все микросхемы 1-Wire встроен конденсатор номиналом 800пФ).

Т.е. для связи с устройством 1-Wire требуется всего 2 провода, один сигнальный, второй – заземление. Компания Dallas (и позже купившая ее Maxim) выпускают много всякий устройств с шиной 1-Wire. Это всякие термометры, календари, датчики, память, отдельно хочу отметить электронные таблетки iButton успешно используемые в устройствах идентификации. В свое время у меня долго не слаживалось поработать по шине 1-Wire, то не было с кем связываться, то не хотелось и казалось сложным, а то и просто не заработало.

В конце концов, погоняв код в VMLab понял, что эта шина очень чувствительна к таймингам и к номиналу резистора, подтягивающего линию данных. Первым результатом успешной работы с 1-Wire у меня стал цифровой термометр на базе датчика DS18B20 и микроконтроллера ATmega8, данные о температуре выводились на символьный ЖКИ WH1602A. О чем я хочу написать заметку.
Рассмотрим шину 1-Wire поподробнее.

Каждое устройство 1-Wire имеет уникальный ROM код, так называемый адрес. На шине должно быть одно ведущее устройство (master) и одно или несколько ведомых (slave). Количество ведомых ограничено адресным пространством и емкостью шины. При начале обмена данных, ведущий должен проверить наличие на шине хоть кого-то. Для этого мастер на протяжении 480мкс должен удержать логический ноль на шине (так называемый Reset pulse), «отпустить» шину минимум на 60мкс и посмотреть какой уровень присутствует на линии данных. Если это низкий уровень – на шине есть устройство 1-wire. Если высокий – шина пуста. Это так называемый Presence pulse.
присутствие DS18B20
Далее следует передать байт-команду устройствам. Для этого ознакомимся с принципом передачи данных по 1-Wire. Передача байта разбита на так называемые временные слоты (60-120мкс), один временной слот служит для передачи одного бита. Данные передаются последовательно, начиная с младшего бита. Для передачи битов от ведущего к ведомому используется верхняя (на картинке) схема:
чтение/запись DS18B20
Для передачи логического 0, ведущий должен удержать на шине нулевой потенциал на протяжении всего временного слота (60-120мкс), а после отпустить шину, для сигнализации окончания временного слота. Для передачи логической 1, ведущий должен удержать шину в нулевом положении чуть более 1мкс (но не больше 15мкс), а после отпустить шину на весь оставшийся временной слот.

Для передачи данных в обратном направлении, от ведомого в ведущему используется нижняя (на картинке) схема. Микроконтроллер удерживает низкий уровень на протяжении чуть более 1мкс, после чего отпускает шину и ждет примерно 30мкс и проверяет состояние на шине, если там высокий уровень – то передана логическая единица, если низкий – то передан логический ноль.
В принципе все просто, но вот с этими задержками и возникают трудности. Теперь рассмотрим схему, по которой можно выжать данные о температуре из DS18B20. Сначала проверим наличие DS18B20 на шине с помощью Presence pulse. После дадим команду 0хсс (игнорировать ROM код, т.е. все следующая команда предназначена всем ведомым на шине) и 0х44 (начать преобразование), после чего выжидаем пока датчик преобразует температуру в код и после команда 0хсс, 0хbe (выдать температуру) принимаем 2 байта кода температуры. Вообще такой подход не универсален, если на шине присутствует несколько устройств, то получиться каша. Для того, чтобы не было каши, используют ROM код, и устройство откликается только на свой ROM. В случае с iButton, ROM код написан прямо на корпусе устройства. С DS18B20 такого не наблюдается и приходиться считывать ROM с помощью команды 0х33. Но возникает проблема, как считать ROM код, если на шине 2 устройства и не один из их ROM неизвестен. Для этого существует специальный алгоритм, про который можно почитать в даташите DS18B20. Здесь его описывать не буду, потому что у меня только одно устройство 1-wire на шине, а сам алгоритм громоздкий и писать его без цели не хочется. Как разживусь на 2-й датчик DS18B20 – так и напишу про алгоритм нахождения ROM кодов 
Для работы с 1-wire предлагают частично использовать аппаратный UART, но так не спортивно, тратить ценный UART на какой-то 1-Wire, который можно реализовать на любой ножке микроконтроллера?? Поэтому напишем функции работы с 1-Wire, привязанные к заданной ножке порта, например к PB0. Только сперва рассмотрим схему подключения DS18B20 к микроконтроллеру ATmega8.

Микроконтроллера тактируется от внутреннего RC генератора на 4МГц. Резистор R1 – подтягивающий на 6,8кОм, R2 – ограничительный на 1кОм, R3 – 17 Ом, потенциометр VR1 – 10кОм. Конденсаторы С5,С7 – электролиты, по 100 и 200мкф соответственно. С4,С6 – керамика на 0.1мкф.
Теперь рассмотри функции работы с DS18B20:

  1. #define MASK 0x01
  2. unsigned char present_ds18b20(void)
  3. { unsigned char res;
  4.  
  5. DDRB|=MASK;
  6. _delay_loop_2(475); //Pause 480mks
  7.  
  8. DDRB&=~MASK;
  9. _delay_loop_2(65); //Pause 70mks
  10.  
  11. if ((PINB&MASK) == 0x00) res=1; //if present, res=1
  12. else res=0; // else 0
  13. _delay_loop_2(405); //pause 410mks
  14. return res;
  15. }
  16.  
  17. void send_ds18b20(unsigned char command)
  18. { unsigned char i, data;
  19.  
  20. data=command;
  21.  
  22. for(i=0;i<8;i++)
  23. {
  24. if ((data&0x01)==0x01) { //Send 1 on SDA
  25. DDRB|=MASK;
  26. _delay_loop_2(2); //pause 6mks
  27. DDRB&=~MASK;
  28. _delay_loop_2(60);//pause 64mks
  29. }
  30. else { //Send 0 on SDA
  31. DDRB|=MASK;
  32. _delay_loop_2(55);//pause 60mks
  33. DDRB&=~MASK;
  34. _delay_loop_2(2);//pause 10mks
  35. }
  36. data=data>>1;
  37. }
  38. }
  39.  
  40. void receive_ds18b20(void)
  41. { unsigned char i;
  42.  
  43. temperature_sign=0;
  44. for(i=0;i<16;i++)
  45. {
  46. DDRB|=MASK;
  47. _delay_loop_2(2); //Pause 6mks
  48. DDRB&=~MASK;
  49. _delay_loop_1(6); //Pause 9mks
  50.  
  51. if ((PINB & MASK)==0x00) temperature&=~_BV(i);//If 0 on SDA
  52. else {
  53. temperature|=_BV(i); //IF 1 on SDA
  54. if (i==12) temperature_sign=1;//IF its sign
  55. }
  56. _delay_loop_2(50); //Pause 55mks
  57. }
  58. }

Здесь я не использовал привычную конструкцию _BV(SDA), потому что вычисление результата функции занимает время и влияет на формируемые задержки. Поэтому использую константу MASK. Думаю что назначения функций рассказывать не стоит, названия говорят сами за себя. Фрагмент обмена данными (Presence pulse и команды 0хсс, 0х44), захвачен с помощью моего логического анализатора:

Работу же самого термометра можно просмотреть на видео:

Скачать полный код проекта для AVR Studio 4.

delays правильно выставлены?

Есть вопрос (а может и замечание) по delays при чтении из датчика. Если верить читать родной даташит, то в нем написано: "Output data from the DS18B20 is valid for 15µs after the falling edge that initiated the read time slot. Therefore, the master must release the bus and then sample the bus state within 15µs from the start of the slot."
Т.о., если мой ангицкий меня не подводит, то мы должны успеть прочитать бит в течении 15мс, а не по истечении. И как написано в том же даташите, то надо как можно сильнее сократить время на пуллдаун и на пуллап.
Поправьте, если я не прав.

в протеусе не работает

смоделировал в протеусе не работает

А можно больше информации что

А можно больше информации что именно не работает и как была составлена схема проекта?
Что залито в виде прошивки?

Проблема в протеусе

Смоделировал схему в протеусе 7.10 с LM016L. Сначала ничего не получилось))). Добиться хоть чего-то получилось только повесив D0-D3 дисплея на VCC. С датчика данные читаются, но на дисплее кракозябры (соответствующие сегменты изменяются при изменении температуры, но с кодировкой какая-то беда.
files.mail.ru/SGKFMR

возникла проблема с ATmega88PA

завалялся у меня уменя такой датчик температуры, всё никак руки недоходили, а тут увидел этут статью, и вспомнил что у меня ещё и ЖКИ такой же есть)
но не тут то было, перекомпилировал код под ATmega88PA, запустил её от кварца на 4 МГц, но на дисплее в первой строке постоянно бегают всякие непонятные символы, по странному стечению обстоятельств я начал тыкать пальцем в кварц, и в один прекрасный момент увидел надпись " no sensor "
обидно то что 88-я мега имеет внутрений генератор только на 8 МГц, в проэкте я поменял частоту на 8 МГц, запустил всё заново, но символы опять хаотично бегают... с чем это может быть связано? не совместимость МК ?

Не понял твоей проблемы. Если

Не понял твоей проблемы.
Если кварц внутренний в Меге 88 только на 8МГЦ почему не поставишь делитель частоты, там же в фьюзах есть такая возможность. Если не выйдет можно решить покупкой внешнего кварца на 4МГц. С беганиной символов левых может быть такая история. ЖКИ не успевает выполнить посланные ему команды инициализации и команды управления ЖКИ. Из-за этого он может непредсказуемо себя вести.

делитель частоты в фьюзах

делитель частоты в фьюзах есть только на 8 (бит CKDIV8)
кварц на 4 МГц у меня есть, и МК от него заводится. пробовал запускать другую прогу, работает, но с этой проблемы...
если в AVR studio в настройках проэкта и в самой проге задать другую частоту? или этот способ не прокатит?

Прокатит если программа

Прокатит если программа задержки использована стандартная. Из набора delay.h а если сам писал то не даст ничего. Может купить кварц будет самым простым решением?

ещё раз повторюсь, у меня

ещё раз повторюсь, у меня есть кварц на 4 Мгц, но я его выпаивал, если он не сдох от перегрева, что мало вероятно, потому что други проги от него работают. весь проэкт я качал из этой статьи... не поленюсь, куплю 8 мегу и поробую на ней. ЖК стопудово рабочий. когда тыкаю пальцем в кварц, иногда показывает надпись " no sensor " что уже радует. кондёры на кварце по 18 пФ, всё должно работать...
короче я не заю в чем пожет быть проблема...

"...когда тыкаю пальцем в

"...когда тыкаю пальцем в кварц, иногда показывает надпись " no sensor "..."
Это как называется? Может проверил бы контакты и соединения, раз при нажатии пальцем все же иногда проскакивает то что надо?
Замени кварц,
замени контроллер,
замени датчик.
Определи что не правильно работает. Если результат один и тот же при заменен какждого из элементов значит вывод - проблема в программе. (Но так как ты видишь Видео работы, и готовый откомпилированный проект, вариант с программой отпадает).

Знаки ???? вместо комментариев

Что-то у меня вот такая беда отображается в исходнике:
void lcd_dat (unsigned char lcd) //????? ??????? ?? ??? ? ??????? ???????
AVR Studio 4.14 Build 589

А комментарии помогли бы разобраться, как вместо LCD 7-ми сегментную LED индикацию прилепить.

Это комментарий на кириллице

Это комментарий на кириллице написан.
Попробуй его скопировать куда-то, в текстовый документ или в вордовский файл.

В блокноте тоже самое. (

Я файл ds18b20.c открываю в блокноте, а там тоже самое. И это на двух компах так. Тут в комментариях ниже у кого-то тоже самое попадается.

продолженеи задумки -делюсь соображениями (сорри за поток созна

выдалось свободное время - хочу приделать кнопку, чтобы можно было выводить исторический минимум и максимум.
сейчас у меня сегменты управляются через PORTD0-3 - хочу высвободить на кнопку порты прерываний.

и в обработчике прерывания вызывать процедуру для отображения на несколько секунд минимального/максимального значения.
сразу же вертелась мысль прямо в этой процедуре ожидать повторного нажатия кнопки - но ведь тогда опять будет вызов прерывания.

наверное, в прерывании буду менять статус (нажата впервые/повторно), и от этого статуса вызывать процедуру отображения минимума/максимума. но тогда вопрос - как ее похитрее реализовать, чтоб при повторном нажатии кнопки отображался второй экстремум, делалась некая задержка на пару секунд, а потом отображалась текущая температура, а не первый экстремум...

глянул в код: если в вызываемой в обработчике процедуре просто переприсовить значения temperature_sign и temperature, а потом тупо сделать двухсекундную задержку, и если повторное нажатие кнопки будет происходить когда микропроцессор зашел в первую процедуру и выполнил присвоение, то будет то что надо.

остались вопросы по избавлению от дребезга и хранению значений.
какие еще "подводные камни" видны?

А я бы выводил параллельно

А я бы выводил параллельно текущую и минимальную/максимальную температуру.

Если такое вариант не нравится: то в прерывании сделать что-то такое:

  1. for (i=0;i<1000;i++)
  2. if ((PINX&0x01)==0x00) {
  3. pause(100);
  4. if ((PINX&0x01)==0x00) {
  5. while ((PINX&0x01)==0x00)
  6. ;
  7. вызвать процедуру отображения минимума.
  8. }
  9. }

Т.е. если в течении цикла for будет нажата кнопка, то pause(100); отсечет дребезг, а процедура вывода будет вызвана после отжатия клавиши.

С дребезгом также можно бороться конденсатором 0,1мкФ

конденсатор параллельно

конденсатор параллельно кнопке повесил - особой разницы не почувствовал.
если делать паузы в прерывании - это сразу видно на экране, типа некрасиво)
в итоге сделал в прерывании изменение переменной статуса (минимум, максимум, текущая температура)
а в функции вывода - проверку, что выводить.
иногда не срабатывает (ну то есть вывод там все равно раз в секунду меняется -поэтому кажется что кнопка не срабатывает), но вполне терпимо.
сейчас вот думаю, не приделать ли (а если приделать - то как попроще) еще и часы/дату - чтобы не просто минимум и максимум, а с временем и датой)))
но вроде актуальнее попробовать присобачить второй датчик... и попробовать с паразитным питанием. не думаю, что выводить на витой паре на 20 метров - хорошая затея..

В спецификации 1-wire говорят

В спецификации 1-wire говорят что можно до 300 метров :)

упростил все до безобразия

микроконтроллер работает на 8МГц, отключил все прерывания, повесил лишь один светодиод, который будет светиться при обнаружении датчика.

в основной программе оставил цикл, вызывающий present_ds:

  1. while (1)
  2. {present_ds18b20();
  3. for (i=0;i<8;i++) pause (32000); };

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

  1. unsigned char present_ds18b20(void)
  2. { unsigned char res;
  3. PORTD&=~PORTD_MASK; //включаем 0 на пине датчика
  4. DDRD|= PORTD_MASK; //(включаем пин на выход!)
  5. _delay_loop_2(928); //пауза 480мкс - reset pulse
  6.  
  7. DDRD&=~PORTD_MASK; // (порт на вход)
  8. _delay_loop_2(140); //пауза 70мкс - ждем presence pulse
  9.  
  10. if ((PIND&PORTD_MASK) == 0x00) //смотрим значение
  11. {
  12. res=1; PORTD|=0x10; //зажигаем светодиод
  13. pause(30000);
  14. } else
  15. {res=0; PORTD&=~0x10; //гасим светодиод
  16. pause(30000); }
  17. _delay_loop_2(820);// пауза 410
  18. return res;
  19. }

этого достаточно, чтобы играться с задержками, ведь верно?
сейчас я почему-то попадаю в первую ветку if, даже когда датчик физически отключен.
как это можно объяснить?

кажется, допёр

в единицу на входе подтягивает резистор - я отключал весь пин целиком, поэтому закономерно попадал в present_ds1820 в первую ветку (0=0)
сейчас дошел до того, что датчик определяется (если вынимаю сам датчик, на пине все равно 5В, но светодиод гаснет)
но определяется лишь если не была запущена init_timer:

  1. void init_timer (void)
  2. {
  3. TIMSK=(1<<TOIE0); //Enable timer overflow interrupt
  4. TCCR0A=0x00;
  5. TCCR0B=0x03; //setting the prescaler
  6. }

при этом в present_ds1820 я в самом начале делаю cli();, а перед выходом - sei();

но самое интересное - при выполненной инициализации таймера датчик не определяеся следующим образом:
на экране отображается знак "нету датчика", но светодиод не гаснет (хотя в ту часть ветки попадаем - нету датчика же рисуется!)
то есть похоже светодиод включается где-то в другом месте. но где?

из прерываний есть только по таймеру:

  1. ISR (TIMER0_OVF_vect)
  2. {
  3. PORTB=0xff; // cathodes - ON, digits OFF 3f
  4.  
  5. PORTD=~_BV(counter);
  6. PORTB=~data[counter]; //Write code
  7. counter=(counter+1)%4; //Increment digit counter
  8.  
  9. TCNT0=0x00; //Clear timer
  10. }

и где тут может быть ошибка? похоже что в ISR меняются не только первые четыре пина PORTD? только почему?

еще занятнее

теперь у меня, судя по всему, первый раз после включения устройства датчик обнаруживается. и даже устройство отправляет что-то куда-то))
а в последующих обращениях к present_ds1820 датчик уже не обнаруживается - чем это может объясняться?
и загадка со светодиодом, который при инициированном таймере больше не гаснет при извлечении датчика - тоже остается неразгаданной.

кстати, присобачил счетчик - по массиву codes с конфигурацией сегментов, ну и заодно узнал, что бывает при обращении к несуществующему элементу массиву. рисовал занятные штуки, а потом 00, дольше ждать не стал - перегрузил предыдущую прошивку. интересно, чем чревато? а когда счетчик int, и ему пытаются присвоить значение больше положенного?

а точно при настройке

а точно при настройке свободно болтающегося пина на вход на нем образуется 5В?
потому что у меня не образуется :-(

Если подключен внутренний

Если подключен внутренний подтягивающий резистор (тот который внутри МК) - то да, будет 5В. Если пин в свободном полете DDRB=0x00; PORTB=0x00 - то может быть все что угодно.

то есть при DDRB=0x00 все

то есть при DDRB=0x00 все равно имеет смысл делать PORTB=0xFF?
в моем случае я "отключал датчик" снятием на бредборде перемычки у ноги микроконтроллера. при этом пин выставлялся на вход, но внутренний подтягивающий резистор на нем, похоже, был выключен. я так понял, что в схеме термометра его роль выполнял резистор при подключении датчика. так вот, я перемычкой отлючал и его, неудивительно, что present_ds обнаруживала некий датчик и без перемычки - там был ноль (замерял вольтметром и жутко удивлялся почему). потом стал извлекать сам датчик (внешний резистор оставался в схеме) - тогда все работало как надо...

короче, случился упс, нужна помощь

и я не знаю как отлаживать..
не видит у меня устройство датчика.
хотя переделал код под себя, скомпилировал (единственное - поругался на первую строчку:

main.c:1:1: warning: "F_CPU" redefined
:1:1: warning: this is the location of the previous definition
avr-gcc -Wall -Os -DF_CPU=4000000 -mmcu=attiny2313 -o main.elf main.o
rm -f main.hex

но я в мейке переделал на 4000000, фьюзы пробовал ставить и на 4MHz +0ms (CKSEL=0010 SUT=00) и на 4MHz
(CKSEL=0010 SUT=10)
пробовал сопротивление и 4,7, и 5,7, и 6,7кОм
видимо, сказываются прерывания на таймер? пробовал немного поиграть с цифрами в delay_loop - но там слишком много можно пробовать...
где взять такой замечательный логический анализатор? это USB осциллограф? )

мой вольтметр показывает стабильные 4,91В на средней ножке и 4,95-4,96В на правой ножке

тихо сам с собою я веду беседу...

короче, с дилэями разобрался вроде бы (не знаю, какой там только оверхед, но вроде протокол допускает болтанку в несколько микросекунд - а в комментариях все равно странно все это)
в present_ds18b20 в конструкции if я сделал проверку - найдено ли что-нибудь на шине (если найдено - загорается один сегмент, не найдено - другой сегмент, пауза), и еще сделал выключение-включение прерываний на входе и выходе из функции.
пока что у меня ничего не находится (горит второй).
интересно другое. в present_ds18b20 убрал строки, переводящие пин в режим входа, оставил только ту, что на выход. вроде по уму там должен быть ноль (отключил датчик на время), смотрю вольтметром - а там 5В. не могу понять, это что, сгоревший порт?
просмотрел внимательно - нигде его в 1 не ставлю. подскажите, плиз. вот код:

  1. #define PORTD_MASK 0x40
  2. unsigned char present_ds18b20(void)
  3. { unsigned char res;
  4. //cli();
  5. PORTD&=~PORTD_MASK; //выставляем наш бит в 0
  6. // DDRD&=~PORTD_MASK; //порт на вход (+5В)
  7. _delay_loop_2(960); //пауза 480мкс
  8. DDRD|= PORTD_MASK; //bitwise OR (порт на выход!)
  9.  
  10. _delay_loop_2(960); //пауза 480мкс
  11. // DDRD&=~PORTD_MASK; //bitwise AND (&=) + bitwise NOT (~) (порт на вход)
  12. _delay_loop_2(110); //пауза 70мкс
  13.  
  14.  
  15. if ((PIND&PORTD_MASK) == 0x00)
  16. {
  17. res=1; //???? ?? ???? ???????? ?????? ???????
  18. data[3]=codes[11];
  19. pause(30000);
  20. }
  21. else
  22. {res=0; //?? ?????????? 1, else 0
  23. data[2]=codes[2];
  24. pause(30000);
  25. }
  26. _delay_loop_2(810); //???? 410???
  27.  
  28. //sei();
  29. return res;
  30. }

в while идет if present_ds18b20()
и никаких изменений регистра нет.

По работе с 1 wire я не спец,

По работе с 1 wire я не спец, будет Серега думаю ответит.

что я делаю не так?

блин. дожили. не получается 0 выставить на ноге: подцепил к pd4 через сопротивление мелкий светодиод на минус
в самой программе цикл сделал while0, убрал все манипуляции с регистром D кроме

DDRD=0x1f; // выходы на 0-4 пинах
PORTD=0x00; //устанавливаю нули везде
//контрольный выстрел
PORTD=~_BV(4); //ставлю нуль на pd4

и все равно светодиод горит, и на самой ноге 5В!!! что я делаю не так???

По отладке 1-wire посоветую

По отладке 1-wire посоветую использовать программку VMLab, она мне очень здорово помогла отлаживать задержки при разработке.

Также хорошо помог логический анализатор, правда его нужно покупать. У меня такой 6-lab.com/news/3-projectnews/19-logic-u-pro

Также при работе с 1-wire надо точно знать тактовую частоту. Мой совет - начни с малого. Отключи прерывания, выставь оптимизацию O0, выставь тактовую частоту 4МГц, попробуй программу минимально модифицировать. Т.е. датчик к PB0, и если находится - то пускай включает светодиод.

Про траблы с портом - очень похоже что ты его спалил. Попробуй следующий код вместе с светодиодом для проверки работоспособности:

DDRD=0xff;

while (1)
{
PORTD=0xff;
pause(10000);
PORTD=0x00;
pause(10000);
}

нашел некую crossstudio for

нашел некую crossstudio for avr 2.0 - но какие-то уж чересчур сложные все эти инструменты :-(
и не хватает инклюдов для запуска...
и с o0 пока не пойму - ведь это где-то в makefile должно указываться?

По идее да. Я уровень

По идее да. Я уровень оптимизации указываю в AVR Studio в настройках проекта.

интересное дельце! в

интересное дельце! в настройках таймера указал прискейлер 256 (индикатор моргает бегущей строкой, тестовый светодиод горит), зато судя по индикатору у меня в самом начале работы устройства стал обнаруживаться сам датчик! (шесть раз моргает левый разряд, на который я сообщаю об обнаружении датчика)
но потом опять терялся и безвозвратно
но самое интересное, что датчик там не был подключен!!! откуда он там видит 0? подключил датчик - та же фигня.

в коде единственное место, где я изменяю этот разряд - в ds_present

if ((PIND&PORTD_MASK) == 0x00)
{
res=1; //???? ?? ???? ???????? ?????? ???????
data[3]=codes[11]; //(рисуем слева букву П)

pause(30000);
}

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

фу, порты вроде живые. в

фу, порты вроде живые.
в while сделал паузы 65535
прерывания включены, divideclockby8 выключено - лампочка горит. включаю divideclickby8 - лампочка горит

выключаю прерывания (//sei();), divideclockby8 вылючено - быстро моргает, включаю divideclockby8 - начинает моргать медленно (раз в секунду).

а вывод из этого опыта правильный сделать не могу :-))

самое интересное, что в прерываниях у меня

  1. void init_timer (void)
  2. {
  3. TIMSK=(1<<TOIE0); //Enable timer overflow interrupt
  4. TCCR0A=0;
  5. TCCR0B=2; //setting the prescaler
  6. }
  7.  
  8.  
  9. ISR (TIMER0_OVF_vect)
  10. {
  11. PORTB=0xff; // cathodes - ON, digits OFF 3f
  12.  
  13. PORTD=~_BV(counter);
  14. PORTB=~data[counter]; //Write code
  15. counter=(counter+1)%4; //Increment digit counter
  16.  
  17. TCNT0=0x00; //Clear timer
  18. }

больше прерываний в коде нет. а тут вроде меняются только первые четыре пина у D
(На всякий случай еще init_timer показал - она вызывается перед включением прерываний.

не пойму, почему при включенных прерываниях у меня светодиод горит, а не моргает, как я того хочу?

уже порыскал по интернетам в

уже порыскал по интернетам в поисках информации об анализаторе :-)
нашел вот такой
saleae.com/logic/specs/
для меня хорошо в нем то, что он работает с программой saleae logic, родная версия которой есть и под мак. впрочем, я совсем не уверен, что продавец захочет отправлять его из штатов в россию. да и наверное в России можно найти или его копию, или нечто не хуже по характеристикам и за меньшие деньги?

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

частоту вроде бы учел (задержки выставлял из описания delay loop 2 из basic_delay.h (там вроде четыре операции за одну итерацию, плюс учитывал фьюзы на 8МГц) Кстати, не уверен что правильно выставлен фьюз что-то про divide clock by 8 internally...
а что есть оптимизация O0?

завтра разгребусь с делами - попробую проверить порт этим циклом.
интересно, что портд у меня используется для управления общими анодами индикаторов, и вроде бы работает исправно (последний раз переделал на первые четыре пина), и тот пин, на который я повесил светодиод - вроде бы только что до этого управлял разрядом..

Логический анализатор

Логический анализатор работает по простой схеме: сколько-то раз в секунду (частота задается) он считывает свои входа, и данные шлет в ПК, который их обрабатывает и выдает юзеру красивые графички на монитор.

Если не уверен насчет фьюзов - проверь.

Оптимизация - фишка компилятора, при включении которой компилятор может оптимизировать код по таким параметрам как скорость выполнения и размер программы в флэш-памяти. Есть несколько уровней, но обычно используют либо O0 - без оптимизации, либо Os - максимальная оптимизация. При включении оптимизации - компилятор переделывает все функции задержки так, что они выполняются за несколько тактов МК, тем самым нарушая длительность задержек.

Если говоришь, что порт исправен - значит может быть паленый датчик, или где-то в коде трабла. (например, в программе ты говоришь, что PORTD=0x00; а в прерывании по таймеру у тебя стоит PORTD=0xff;)

интересно, а с украины в москву пришлют? :-)

на сайте 6-lab.com несколько разных версий (logic u, logic u isl, logic u pro) - пока плохо понимаю в чем отличия и какой лучше приобрести.
судя по тому, что там используется то же ПО (saleae logic) - похоже они выпускают эти анализаторы по лицензии как раз от этих перцев, впрочем, полной уверенности у меня нет, как и насчет того, будет ли этот софт работать с этими анализаторами - кстати, вам можно проверить - софт под разные платформы на том сайте лежит). но я так понял, его же можно будет использовать и для баловства с PWM, и для многих других задач...

насчет фьюзов - у меня стоит галка enable SPIEN (spien=0). и есть возможность поставить галку divide clock by 8 internally (ckdiv8=0).впрочем, ставил и так, и эдак - датчик все равно не обнаруживался.

насчет оптимизации кода - очень интересно! считаю, об этой тонкости следовало рассказать в самой статье! посмотрю, какие ключи у avrdude для отключение оптимизациий. наверное, они могут влиять и на продолжительность пустого цикла for?

код вроде бы проверял несколько раз, прерывания смотрел. в прерывании по таймеру, сколько я могу судить, мой пин не трогается (хотя тоже может быть какая-то тонкость существует?) такое ощущение, что в ноль не выставляется.

и да, хотел спросить - можно ли каким-то образом узнать о неисправности датчика (кроме как включить его в заведомо работающую схему?)

Доставят, они этим деньги

Доставят, они этим деньги зарабатывают. Ради одного ШИМа логический анализатор смысла брать нету, самая его фишка - анализ протоколов обмена, таких как spi, uart, usb. Экономит время, не приходится побитно разбираться какие данные передаются. Плюс есть возможность смотреть на задержки.

Отличия в приборах небольшие, на сайте у них все написано.
isl - с гальваноразвязкой.
pro - есть один аналоговый канал, можно использовать как осцилл, для серьезных работ его недостаточно, но фронты смотреть можно.

Насчет фьюзов советую открыть даташит, они где-то вконце описаны. Фьюз SPIEN никогда не трогай, МК перестанет по SPI шиться.

1-wire девайс вроде только в рабочей схеме можно проверить. Подключи к DS18b20 только питание и резистор, посмотри что на линии данных у него твориться.

а еще почему R1 такой

а еще почему R1 такой номинал, хотя в ДШ везде указан 4,7К?

Потому что это не критично и

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

а в самой статье сказано, что

а в самой статье сказано, что датчик очень требователен к номиналу резистора...

Обычно номинал подтяжки может

Обычно номинал подтяжки может очень варьировать, от пары килоом до сотни. А словами "очень трабователен" - хотел обратить внимание на это, чтобы народ не тулил 100 кОм и потом не удивлялся, почему не работает.

понятно. кстати, интересно,

понятно. кстати, интересно, как оно будет работать на паразитном питании...
попробую для начала разобраться с двумя датчиками...

приступил к этому проекту -

приступил к этому проекту - в какой кодировке сделаны комментрии в файле ds18b20.c?
(перепробовал все кириллические - не помогает)

DDRB|=MASK;DDRB&=~MASK;
- я хочу использовать для датчика pd3, при этом остальные пины portd используются. как правильно в этом случае изменять маску (чтобы не задеть другие пины)? хочу использовать семисегментные с прерыванием по таймеру для вывода значений (не уверен что получится с таймингами - к тому же в даташите ds1820 (или вообще по 1-wire) читал, что из-за капризности в смысле временных интервалов писать программы для работы с 1wire следует только на ассемблере...

почему в комментариях про delay в некоторых местах разница в 5 мкс, а в других - 3, 4 или 8мкс. как-то это сбивает с толку.

и что означают следующие строчки? константы?
#define RS 2
#define E 3
#define TIME 10

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

злостный офтопик про предыдущий проект: начал тут рисовать плату в eagle - понял, что разводить те же четырехразрядные индикаторы - чересчур сложно (или по верху гонять, проводами, или делать двухстороннюю - но такое, боюсь, вообще не осилю)
наверное, откажусь от этих индикаторов, возьму вместо них пару светодиодов (отображать включение нагрузки в разных направлениях), и наверное имеет смысл сделать оптическую развязку на симисторы?
подключать оптрон и кнопки планирую через rj11. ну и колодку для силовых проводов (симистор же должен фазу размыкать, правильно? - то есть надо предусмотреть каким-то образом стационарное подключение к сети, а не с простой вилкой)

win1251 вроде маска =

win1251 вроде

маска = _BV(номер пина на котором висит ds18b20);

Дефайны в начале - константы для работы с ЖКИ

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

забыл отправить))

ура, гуру вернулся!
в смысле, если не хочу помереть от электрошока - лучше с развязкой?
поеду наверное на неделе за недостающими деталями nach Moskau, посмотрю что из себя представляет вольтмастер...
в Eagle кое-что нарисовал. наверное, нужен текстолит потолще для моих целей.
попробую на днях заняться разведением дорог - посмотрим что из этого выйдет.
и еще, совсем нет уверенности что чертежи eagle будут соответствовать реальным деталям, так что скорее всего надо будет распечатать на бумаге, и накидать для начала на бумагу все это, перепроверить правильность расстояний и всего такого, и уже потом ЛУТить.
а как защищать порты, если хочу вынести кнопки на два-три метра? каким образом и что именно заземляется? от какой именно статики нужно защищаться?

Всегда ставь опторазвязку там

Всегда ставь опторазвязку там где есть мощная нагрузка, оно недорого стоит, но спасает от неприятностей.

Попробуй юзать небольшие 1206 перемычки (резисторы сопротивлением 0 Ом), а между ними проводники бросать. Ими часто спасаюсь от необходимости делать вторую сторону.

Перед тем как ЛУТить - распечатай плату и просто повтыкуй в бумагу детали.

Попробуй без экранирования, если будут лезть помехи - подключи экранированным кабелем и обязательно заземли экран с двух сторон.

А гуру - это сильно, я всего-лишь любитель.

целая куча вопросов после внимательного изучения кода

а что есть SDA?
что мы понимаем под "отпустить"? речь о том, что приходит с другой стороны?

и что за хитрая штука "логический анализатор"?

DDRB вроде бы устанавливает направление регистра B на вход или выход. или установить на выход - автоматически означает, что на нем со стороны микроконтроллера будет логический ноль?
вроде бы 6 и 9 строчки оставляют другие биты на месте, это хорошо.
в 12 строке не понял, что есть PINB, точнее, где он задан? судя по дш это и весь регистр. а в чем отличие PINB от PORTB?

сейчас еще заметил, а в чем отличия delay_loop2 от delay_loop1?

и еще, не совсем понимаю, что происходит при temperature&=~_BV(i) и при temperature|=_BV(i);
тут затрагиваются только i бит? остальные без изменений?

зачем в теле аж четыре раза повторяется
pause(3200*TIME);
или это остатки от прежних упражнений?

зачем нужна такая пауза после преобразования? и зачем мы второй раз скипаем ром?

SDA - линия данных Отпустить

SDA - линия данных

Отпустить - выставить на порту лог. 1, при из-за подтягивающих резисторов напряжение на шине подымается от 0 до 5В.

Логический анализатор - что-то типа дофигаканального осциллографа, который может считывает только лог. 0 или лог. 1.

"DDRB вроде бы устанавливает направление регистра B на вход или выход. или установить на выход - автоматически означает, что на нем со стороны микроконтроллера будет логический ноль?"

Нифига не понял, что ты хотел этим спросить.

PINB используется для считывания из порта. PORTB - для записи в порт

"и еще, не совсем понимаю, что происходит при temperature&=~_BV(i) и при temperature|=_BV(i);
тут затрагиваются только i бит? остальные без изменений?"

Да, побитно считываем температуру.

"зачем в теле аж четыре раза повторяется
pause(3200*TIME);
или это остатки от прежних упражнений?"

Что-то вроде большой паузы.

"зачем нужна такая пауза после преобразования?"

Читать даташит, внимательно. Особенно пункт про требуемое время для преобразования температуры.

"и зачем мы второй раз скипаем ром? "

Таким способом обращаемся ко всем устройствам на шине (мне лень было делать считывание ROM-кода и с помощью его обращаться к датчику).

самое подходящее в этом

самое подходящее в этом проекте - попробовать выводить на экран разные слова для разных ibutton, скажем, на пять секунд.
заодно узнаем по какой схеме подключать ibutton probe к тому же температурному датчику и какими командами считывать ROM

Угу, думаю как-то сделать

Угу, думаю как-то сделать считывание ROM'a, главное чтобы руки дошли :)

А какие еще данные кроме ROM

А какие еще данные кроме ROM кода можно достать из датчика?
Как посылать команды в датчик?