PIC мк. Эксперимент №16. One-wire на примере DS18b20.

Задача: Измерение температуры с помощью датчика DS18b20

Исходный материал: PIC16f628a, DS18b20, MAX232 level converter, devboard, proteus.

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

Наша цель – получить температуры с минимальными телодвижениями, поэтому читаем даташит и обращаем внимание лишь на существенные моменты. Первый из которых – организация питания. В данном случае я не испытывал проблем с подачей питания, поэтому будем использовать стандартную схему питания:

sch

Линия данных должна быть обязательна подтянута к питанию через резистор (в даташите рекомендуют 4.7 кОм). Курим даташит дальше – смотрим на организацию памяти:

Всего 9 байт памяти:

  1. младший байт значения температуры
  2. старший байт значения температуры
  3. триггер срабатывания по максимуму
  4. триггер срабатывания по минимуму
  5. конфигурационный регистр
  6. внутренние нужды
  7. внутренние нужды
  8. внутренние нужды
  9. CRC

Из это кучи нас интересуют 0, 1 и 4 байт (и то 4 постольку поскольку).

4 байт – конфигурационный регистр:

В нем мы можем перезаписывать только 6 и 5 биты отвечающие за разрешение измерений. По дефолту датчик измеряет с 12 битным разрешением, что соответствует точности 0.0625 градуса. Возможны также следующие варианты:

  • 9 бит – 0.5 градуса
  • 10 бит – 0.25 градуса
  • 11 бит – 0.125 градуса

Ниже представлена таблица значений битов и значений получаемого разрешения:

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

Посмотрим, что собой представляет непосредственно значение температуры в первых двух байтах:

В младшем байте 4 младших бита отвечают за дробную часть, целое значение берется из старших бит младшего и трех младших бит старшего байта. Биты S отвечают за знак значения (Обратите внимание, что для конвертации отрицательных значений температуры, нужно применять другие правила конвертации двоичного кода в десятичный) – если биты S = 1 — температура отрицательна, ну и соответственно наоборот.

Рассмотрим базовые процедуры для работы с one-wire, любая система команд по протоколу начинается с инициализации:

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

предварительно объявим такое дело:

#define STATE TRISB4
#define PIN RB4

 

static bit INIT(void){
static bit b;
STATE = 1;
STATE = 0;         //Проваливаем линию
__delay_us(500);   //Ждем 500 мкс
STATE = 1;         //Переключаемся на вход
__delay_us(65);    //Ждем 65 мкс
b = PIN;           //Смотрим чего там на линии
__delay_us(450);   //Дожидаемся до положенного временного интервала
return b;          //Возвращаем 0 или 1
}

Функция возвращает 0 если устройство присутствует на шине и 1 если устройства не обнаружено. Дальше нам надо сварганить функцию для записи в микросхему:

Чтобы передать устройству 0, нужно опустить линию минимум на 60 мкс, для передачи 0 – проваливаем шину минимум на 1 мкс, а затем отпускаем и выдерживаем нужное время. Учитываем то, что биты должны передаваться младшим вперед:

void TX(unsigned char cmd){

unsigned char temp = 0;
unsigned char i = 0;
temp = cmd;
for (i=0;i<8;i++) {
                  if (temp&0x01) {
                                 STATE = 0;              //передаем 1
                                 __delay_us(5);
                                 STATE = 1;
                                 __delay_us(70);
                                 } else {                //передаем 0
                                        STATE = 0;
                                        __delay_us(70);
                                        STATE = 1;
                                        __delay_us(5);
                                        }
                                 temp >>= 1;
                 }
}

Теперь по чтению:

Для успешного чтения микроконтроллер сначала должен опустить шину хотя бы на секунду, а дальше переключиться обратно на вход и смотреть чего там происходит. Чтобы снять корректное значение нужно выждать по крайней мере 15 мкс от начала (чтобы не попасть на значение во время перезарядки емкостей).

UPDATE: Предыдущее высказывание неверно, и виной этому моя невнимательность, нам нужно не выждать 15 мкс, а успеть за эти 15 мкс снять значение от датчика.

Поэтому я предлагаю из старой функции убрать 10 микросекундную задержку:

unsigned char RX() {

unsigned char d = 0;
unsigned char i = 0;
for (i=0;i<8;i++){
                 STATE = 0;                 //прижимаем линию
                 __delay_us(6);
                 STATE = 1;
                 //__delay_us(10);            //дожидаемся больше чем 15 мкс --убираем нафиг, т.к. это идет в разрез с даташитом
                 d>>=1;                     //освобождаем место под новый бит
                 if (PIN == 1) d |= 0x80;   //если 1 то записываем 1
                 __delay_us(70);            //ждем до положенного времени
                 }
return d;
}

Этих трех функций достаточно для работы с протоколом 1-wire. Для того чтобы снять показания температуры нам нужно выполнить ряд команд (для случая одного датчика на шине):

  1. инициализация
  2. 0xCC – пропускаем идентификацию
  3. 0х44 – запуск конвертации температуры
  4. ждем необходимое время(750 мс для 12 битного разрешения)
  5. повторная инициализация
  6. 0xCC – пропускаем идентификацию
  7. 0хBE – читаем регистры

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

void get_temp() {
static bit init;

unsigned char temp1;
unsigned char temp2;
init = INIT();
             if (!init) {                 //успешно инициализировались?
                        TX(0xCC);
                        TX(0x44);
                        __delay_ms(150);  //ждем 750 мс
                        __delay_ms(150);
                        __delay_ms(150);
                        __delay_ms(150);
                        __delay_ms(150); }
              init = INIT();              //повторная инициализация
              if (!init) {
                         TX(0xCC);
                         TX(0xBE);        //команда на чтение
                         temp1 = RX();    //читаем младший байт
                         temp2 = RX();    //читаем старший байт
                          }

temp_drob = temp1 & 0b00001111;           //Записываем дробную часть в отдельную переменную
temp_drob = ((temp_drob*6)+2)/10;         //Переводим в нужное дробное число
temp1 >>= 4;
sign = temp2 & 0x80;                      //определяем знак температуры
temp2 <<= 4;
temp2 &= 0b01110000;
temp2 |= temp1;                           //помещаем все в одну переменную

if (sign) {                               //если минус
            temperature = 127-temp2;      //глобальная переменная
            temp_drob = 10 - temp_drob;   //глобальная переменная
           }   else temperature = temp2;
}

Чтобы проверить работоспособность я собрал схему на макетке и вывел информацию через уарт:

void main() {
unsigned char input = 0;

init_comms();
get_temp();
printf("\ftemperatura -- ");
if (sign) printf("-"); else printf("+");
printf("%d", temperature);
printf(".%d", temp_drob);

while(1){
        input = getch();
        if (input == 50) {
                         get_temp();
                         printf("\r\ntemperatura -- ");
                         if (sign) printf("-"); else printf("+");
                         printf("%d", temperature);
                         printf(".%d", temp_drob);
                         }
       }
}

Вот что получилось:

Исходники обновленного проекта лежат на репе. Что и как обновилось если кому интересно может посмотреть на комменты мая 2014 года :)

PIC мк. Эксперимент №16. One-wire на примере DS18b20.: 114 комментариев

  1. Это стандартный макрос компилятора Hi-Tech. Организует задержку на заданное количество микросекунд. По аналогии для милисекунд существует макрос __delay_ms(). Более подробно можно о этих макросах почитать в мануале компилятора.

    PS. Для использования этих макросов в коде должно присутствовать определение частоты кварца
    #define _XTAL_FREQ 4000000 //здесь указывается нужная частота

    Ответить

  2. Хочу собрать термометр,прочитал статью начал собирать все до кучи.В функции void TX при компиляции пишет что переменная cmd не используется.Что тут делать?
    Warning [1090] D:\Electronica\Project\termometr\termometr.c; 111. variable “_cmd” is not used

    Ответить

  3. В вашем коде есть несколько неоднозначных моментов:
    1. Строки:

    float temperature = 0;
    float temp_drob = 0;
    

    не имеют особого смысла, т.к. функции возвращают целочисленные значения + у вас нет глобальной переменной sign, которая отвечает за знак температуры, предлагаю такой вариант переменных:

    unsigned char temperature = 25  //инициализация с нормального значения температуры
    unsigned char temp_drob = 0;
    bit sign = 0;
    unsig
    

    2.

    void main ()
    {
    INIT();
    TX(cmd);
    RX();
    get_temp()
    }
    

    В частности строка TX(cmd); – я не понимаю как ее пропустил компилятор, такая переменная нигде в коде не объявлялась.
    3. Чтобы проверить работоспособность достаточно вызвать функцию get_temp(), внутри нее используются все остальные, а потом в уарт выпихнуть значение переменной temperature и temp_drob

    Ответить

  4. Доброго времени суток!
    собрал схему согласно Вашей статьи, программку написал, но датчик не отвечает и не распознается, т.е.
    …….
    if (INIT())
    то послать на через USART 1
    else
    послать ноль…

    по этому поводу возникло два вопроса: 1 не мог ли датчик сгореть (включал его точно так как в даташите и у Вас в статье)
    2 несоответствие временной задержки.

    насчет второго уже голову сломал, т.к. по теории в расчете на 1мц получается приходится времени: (4 такта / 4000000 Гц) = 1 мкс или как в моём случае 4/20000000=0.2мкс
    а! в программе Proteus получается, что совершенно по другому.
    если не трудно то можете привести другой пример временных задержек?

    Ответить

  5. Нашел решение!!!!
    в программе выше изложенной, а точнее

    static bit INIT(void){
    static bit b;
    STATE = 1;
    STATE = 0; //Проваливаем линию

    тут вместо STATE 1-го необходимо заменить на PIN = 0;

    Ответить

  6. Доброе утро, Вы нашли неверное решение: для успешной процедуры инициализации необходимо, чтобы датчик сам провалил линию в 0, а в вашем случае этого произойти не может, так как вы железно подтянули линию микроконтроллером к земле. Дальше программа естественно тоже работать не будет. Если не работает мой код, то:
    1. Надо проверить схему подключения.
    2. Надо попробовать другой датчик (может этому уже конец пришел).
    3. Попробовать поиграться с задержками.

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

    Ответить

  7. sarge отправил на Ваш почтовый ящик текст программы.
    заранее скажу что я не использовал задержку, которую Вы предложили – __delay_us() и __delay_ms() т.к. при компиляции показывает ошибку

    Error[482] : symbol “_DelayMs” multiply defined in “C:\HTSOFT\project\DS18b20(2)\DS18b20.obj”
    Error[482] : symbol “_DelayMs” multiply defined in “C:\HTSOFT\project\DS18b20(2)\DS18b20.obj”
    Error[499] : undefined symbol:
    ___delay_us (C:\HTSOFT\project\DS18b20(2)\DS18b20.obj)

    Ответить

  8. Ошибку показывает потому, что у вас нет макроса:

    #define _XTAL_FREQ 4000000 //ну или другая ваша частота

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

    Ответить

  9. через счетчик MPLAB StopWatch

    строчку “#define _XTAL_FREQ 4000000 //ну или другая ваша частота”
    пробовал с ней, тоже самая ошибка :(((((
    а можете пример написать работы с этим таймером, с шапкой в том числе?

    Ответить

  10. )))) хм думаю Вы правы
    тут еще одну встроенную задержку нашел, она находится в директории
    C:\Program Files\HI-TECH Software\PICC\9.50\samples\delay
    можете что ни будь про неё рассказать?

    Ответить

  11. Ну это не встроенная задержка, это просто образец функции в папке с примерами. Вообще неважно каким образом будет делаться задержка, можете и на встроенных таймерах все это сделать, просто у меня сделано макросами, и чтобы что-то сказать мне надо заново все проделать, а мне этого совсем не хочется.
    Да и таймеры у меня обычно заняты более важными делами, тут и макросы отлично справляются.

    Ответить

  12. Работает!)))
    дело в том, что у меня частота кварца 20МГц, а не 4, и по этому получалось, что должным образом задержка не обеспечивалась.
    Не знаю по каким причинам но __delay_us() и __delay_ms() не распознавал компилятор, по этому воспользовался
    C:\Program Files\HI-TECH Software\PICC\9.50\samples\delay
    а временную задержку уже подгонкой подобрал..
    меня еще одна строчка заинтересовала:
    printf(“%d”, temperature); –это тоже является макросом MPLAB, я так понимаю.
    Можете рассказать что нибудь про него по детальней, а то в интернете ссылаются на команды С++.

    Ответить

  13. “printf(«%d», temperature); —это тоже является макросом MPLAB, я так понимаю.” ой! ошибся HI – TECH

    Ответить

  14. не, это стандартная функция С библиотеки stdio.h, в данном случае она выводит строку через уарт, но в целом ничем не отличается от обычной printf, так что про нее читать можно в любом источнике

    Ответить

  15. здравствуйте уважаемый sarge. Помогите пожалуйста написать прошивку для устройства которое будет работать следующим образом. DS18B20 будет установлен на радиаторе, при температуре радиатора выше 40 гр на одном из портов ввода-вывода лог1 , а при понижении температуры до 30 лог0. Спасибо!

    Ответить

    sarge Ответил:

    Добрый день,
    Ваша задача выглядит довольно просто:
    1. Заводим таймер с нужным интервалом проверки
    2. При прерывании по таймеру берем значение температуры функцией (get_temp())
    3. Если температура больше или равна 40 и статус = 0, то на выход 1
    иначе, если температура меньше или равна 30 и статус = 1, то на выход 0.

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

    Ответить

  16. Спасибо. При компиляции ругается на cmd. Датчик инициализировать я смог сам. Сейчас задача стоит получение от него значения температуры для дальнейшего сравнения.

    Ответить

    sarge Ответил:

    Ну показывайте код. Так я не могу сказать почему он ругается :)

    Ответить

  17. Добрый вечер! Стоит передо мной задача как у melekhov’a. Пока пытаюсь смоделировать в протеусе, камень 12F629. Все функции кроме main() слизаны отсюда, get_temp() крутится в основном цикле. Но температура всегда 0, в чем проблема?
    [spoil]
    int temperature;//целая часть
    int temperature_fraction;//дробная часть
    bit init;
    bit sign;//знак
    void init_uc();
    void get_temp(void);

    void main(){
    init_uc();
    while(1){
    get_temp();
    if(temperature > 50) start_funs = 1;
    if(temperature < 40) start_funs = 0;
    }
    }

    void init_uc(){
    temperature = 25;
    temperature_fraction = 0;
    CMCON = 0xFF;
    GPIO = 0;
    TRIS0 = 0;
    TRIS1 = 0;
    OPTION=0b00001000; //Устанавливаем предделитель TMR0 1:1
    WPU=0b00010100;
    IOCB=0b00000000;
    }[/spoil]

    Ответить

    sarge Ответил:

    На линии 1-wire в протеусе изменения какие-либо происходят если осциллом посмотреть? Или еще лучше сразу снимите график и оцените все ли правильно происходит.

    Ответить

    150BillionSteps Ответил:

    Посмотрел осциллографом. Первый цикл проходит как надо, но с датчика приходит не та температура (74 – установлено, а приходит 58). На последующих циклах осциллограф рисует все время прямую. Температура приходит так 47, 127, 0, 0..0…Я отправил Вам на почту свой проект, буду очень благодарен, если посмотрите. На макетке не заработало.

    Ответить

    sarge Ответил:

    1. В архиве нет файла для протеуса.
    2. Обычно макрос __delay_ms() работает до определенной максимальной цифры (255 вроде).
    3. Зачем опрашивать датчик каждую секунду?

    Ответить

    150BillionSteps Ответил:

    1. Файл-проект для протеуса *.pdsprj? Я отправил его повторно, но он был в архиве.
    2. __delay_ms(2000) работал у меня в том числе и на железе. Поменял на пять __delay_ms(200), результат тот же.
    3. Но ведь это не принципиально, все необходимые задержки вроде есть в get_temp(). МК питаться будет от сети.
    Кстати, закомментировал вот эту часть кода
    if (sign) { //если минус
    temperature = 127-temp2; //глобальная переменная
    temperature_fraction = 10 – temperature_fraction; //глобальная переменная
    }
    и температура стала приходить другая, это удивительно, ведь я всегда устанавливал положительную температуру и эти инструкции не должны выполняться. Старший бит от DS18B20 0b00000XXX.

    Ответить

    sarge Ответил:

    Мой протеус 7 не открывает pdsprj файлы.
    У меня тут сейчас со временем большой напряг, поэтому я хотел бы, чтобы вы перекинули свой код на 628 камень и проверили по уарту например, адекватно ли температура отображается.
    Если надо могу прислать свой проект с файлами протеуса под 628а.

    Ответить

    150BillionSteps Ответил:

    Да, оправьте, пожалуйста, на giper-utesov@yandex.ru.

    Ответить

  18. Здравствуйте sarge. Очень нравится ваш сайт, в статьях всё очень подробно описано!
    Разбираю ваш код, столкнулся с проблемой.
    в Datasheet DS18B20 описано :DS18B20 будет формировать (ответ на слот времени чтения от
    устройства управления) логический «0» когда происходит температурное преобразование. И
    логическую «1», когда конвертирование выполнено.

    у вас в коде:

    TX(0xCC);
    TX(0x44);
    __delay_ms(150); //ждем 750 мс
    __delay_ms(150);
    __delay_ms(150);
    __delay_ms(150);
    __delay_ms(150); }
    init = INIT(); //повторная инициализация
    if (!init) {
    TX(0xCC);
    TX(0xBE); //команда на чтение
    temp1 = RX(); //читаем младший байт
    temp2 = RX(); //читаем старший байт
    }
    Объясните пожалуйста повторной инициализацией вы проверяете выполнено конвертирование или нет?
    Если да то мне не понятно, ведь тогда получается что если “0” то
    TX(0xCC);
    TX(0xBE); //команда на чтение
    а в Datasheet всё наоборот.

    Ответить

    sarge Ответил:

    Фух, уже столько времени прошло, если я правильно вспомнил, то в даташите есть такая строчка

    All transactions on the 1-Wire bus begin with an initialization sequence. The initialization sequence
    consists of a reset pulse transmitted by the bus master followed by presence pulse(s) transmitted by the
    slave(s).

    Оттуда же:

    It is very important to follow this sequence every time the DS18B20 is accessed, as the DS18B20 will not
    respond if any steps in the sequence are missing or out of order

    Под транзакциями понимается последовательность из двух команд. Так что я вроде как просто следовал даташиту и проверял не завис ли девайс.
    Успешность конвертирования я не проверяю.

    Ответить

    Александр Ответил:

    Понятно,так как не проверяете успешность конвертирования поэтому у вас стоит задержка в 750ms как описано вDatasheet чтобы датчик успешно конвертировал.
    Просто меня смутило то, что когда я убрал задержку 750ms всё продолжало успешно работать.
    Спасибо! Буду дальше разбираться.

    Ответить

  19. Добрый день! Прошу рассказать или ткунть пальцем, где самому почитать. Про хитрое преобразование двоичного кода показаний с термодатчика в десятичное число. Несколько не понятны мне те семь строчек со здвигом и & (поразрядное и) кажется. Так если не напрягаться то просто бы слизал ваш код, но мне на будущее придется делать преобразование двоичного кода в шеснадцатеричный.

    Ответить

    sarge Ответил:

    Ээ, в даташите :)

    Ответить

  20. Добрый вечер . В описании функции приема байта есть коментарий , что после подсаживания шины ждем больше 15 микросекунд а затем смотрим что там у нас 1 или 0. Так вот по факту изучив даташит. Состояние шины нужно смотреть сразу, и не более чем через 15 мкс.
    Из- за этого коментария потратил лишний час :(

    Ответить

    sarge Ответил:

    Все правильно в комментарии, посмотрите на картинку внимательно, мы изначально проваливаем шину на некоторое время ( 6 мкс у меня ), переводим состояние пина на вход и ждем еще как минимум 10 мкс (в сумме 16 мкс) и проверяем что у нас там 0 или 1.
    То же и на картинке.
    Так в чем ваш вопрос или вам просто хотелось высказаться?

    Ответить

    Alexey Ответил:

    И это конечно тоже. Но пока не убрал задержку на экране были все нули.

    Ответить

    Alexey Ответил:

    На картинке master read 0 slot внизу показано время где нужно роверить состояние на входе Master samples. Там видно, что нужно проверить за время не более 15 мкс. А пишу для того, что наверняка найдетсся еще не один товарищ который будет повторять опыты с вашего сайта. Но не просто тупо копируя исходники, а читая коментарии и напрягая Мозг :)

    Ответить

    sarge Ответил:

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

    Ответить

  21. А как реализовать опрос двух трех датчиков по одной линии внятных примеров я ненашел, если не трудно может раскажете ?Спасибо.

    Ответить

    sarge Ответил:

    Я с несколькими датчиками на одной шине не работал, поэтому сказать с уверенностью ничего не могу. Но мне всегда казалось, что этот не особо сложно, посылаем нужный алдрес и все. Копать по ходу нужно в сторону команды Search ROM.
    P.S. Вот если вы разберетесь и согласитесь выложить ваш пример работы и функций сюда с вашим авторством естественно, то статья будет более полной :)

    Ответить

    alexwise Ответил:

    В инете нашел некоторое непонятное описание, не могу понять ведь при команде сброса ответят все датчики, в чем прикол? то что нужно rom читать это я знаю, но получается что нужно подключить датчик, прочитать rom, запомнить, подключить следующий и т.д. и работать с этими rom-ами по очереди хотя официальное описалово гласит что интерфейс поддерживает так сказать горячее подключение без дополнительной инициализации всех датчиков. Я хочу попробовать сделать псевдо умный дом на этой линии как не как до 300 метров при определённых условиях можно вытянуть. Один ведущий и несколько ведомых, соединение с ПК, программы для ПК примитивную хочу попробовать написать на HIASM, может кто знаком? Может с помощью вашего сайта, Вас, здешних обитателей попробовать сделать проект псевдо народный открытый умный дом?

    Ответить

    alexwise Ответил:

    Есть некоторые идеи для реализации проекта но один Я наверное не потяну.

    Ответить

    sarge Ответил:

    Я думал, что с серч ром делается один раз, чтобы узнать адреса всех девайсов, а дальше уже использовать хитрые команды, чтобы вызывать конкретный датчик (Match ROM вроде).
    Алгоритм поиска датчиков есть в апнотах – http://www.maximintegrated.com/app-notes/index.mvp/id/187

    Идею общего проекта лучше продвигать в сообществах (хабр или лучше easyelectronics), а здесь обитателей немного.

    Ответить

  22. В первой функции инициализации вроде как ошибка:

    static bit INIT(void){
    static bit b;
    //*************************************************************
    STATE = 1;
    STATE = 0; //Проваливаем линию
    //*************************************************************
    __delay_us(500); //Ждем 500 мкс
    STATE = 1; //Переключаемся на вход
    __delay_us(65); //Ждем 65 мкс
    b = PIN; //Смотрим чего там на линии
    __delay_us(450); //Дожидаемся до положенного временного интервала
    return b; //Возвращаем 0 или 1
    }

    по идее тама должно быть:

    STATE = 0; // направление ножки на выход
    PIN = 0; //Проваливаем линию

    ???

    Ответить

    sarge Ответил:

    Достаточно просто изменить IO, выход сам провалится в 0, если не оговорено иное.

    Функция проверенная не один раз в железе, все работает :)

    Ответить

    zloyleva Ответил:

    Но можно так как и я написал? Вроде ошибки не должно быть?

    Ответить

    sarge Ответил:

    По идее можно.

    Ответить

  23. А что означает эта функция?

    input = getch(); // getch()???
    if (input == 50) {

    Ответить

    sarge Ответил:

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

    Ответить

    zloyleva Ответил:

    а в этой проге что она делает? И “50” это что? (заранее извините – только начинаю осиливать Си)

    Ответить

    sarge Ответил:

    50 – ascii код клавиши 2

    запускаете проект, в терминале высвечивается менюшка, можно нажимать на клавиши и тестировать температуру и перезапускать замер

    Ответить

  24. Может это только у меня так, но врядли, не думаю что может зависеть от версии компилятора или протеуса.
    Заметил нюанс в алгоритме пересчета температуры. Если полученная с датчика температура отрицательна и при этом не является целым числом, т-е имеет какую-либо дробную часть, значение температуры считается верно, если же дробной части нет, занижается на единицу.
    Т-е если на датчике -1.1 – на экране -1.1
    если на датчике -1.0 – на экране уже 0. Причем именно 0, ноль после запятой в этом случае не отображался.
    Если считаете нужным, могу поместить сюда свою версию исправленной функции, где все работает как надо.
    Или вы специально разместили именно в том виде, чтобы копи-пейстом не обошлось и был повод включить голову? :)

    Ответить

    sarge Ответил:

    Нет, не специально, но про косячок с отрицательными температурами знаю давно, лень было разбираться т.к. юзаю его в проектах где температура вряд ли опуститься ниже +10 градусов :)

    По поводу исправленной функции – было бы замечательно, кидайте в комментарии, я закину в статью и помечу, что у функции ваше авторство.

    Ответить

    Dim Ответил:

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

    void get_temp() {
    static bit init;
    unsigned char temp1;
    unsigned char temp2;
    unsigned int temp3; //требуется для корректного пересчета температуры согласно даташиту
    init = INIT();						//инициализация
                 if (!init) {                 //успешно инициализировались?
                            TX2(0xCC);
                            TX2(0x44);
                            DelayMs(150);  //ждем 750 мс
                            DelayMs(150);
                            DelayMs(150);
                            DelayMs(150);
                            DelayMs(150); }
                  init = INIT();              //повторная инициализация
                  if (!init) {
                             TX2(0xCC);
                             TX2(0xBE);        //команда на чтение
                             temp1 = RX2();    //читаем младший байт
                             temp2 = RX2();    //читаем старший байт
                              }
     
    temp_drob = temp1 &amp; 0b00001111;           //Записываем дробную часть в отдельную переменную
    temp_drob = ((temp_drob*6)+2)/10;         //Переводим в нужное дробное число
    temp3=temp2;							  //добавляем старший байт в переменную для расчета температуры
    temp3&lt;=10) {temp_drob=0;} //устранение пропадания нуля
               }   else temperature = temp3/16; //здесь можно было и не менять но так правильней
    return;
    }
    
    

    Ну и конечно огромное спасибо Вам за ваш труд и отдельное – за наличие обратной связи в форуме :)

    Ответить

    sarge Ответил:

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

    Ответить

    sarge Ответил:

    1. вы по ходу if потеряли.
    2. Зачем temp3 если вы не используете temp2?
    3. А что произойдет если мы в 0 в вашей функции, каким образом переменная temperature получит правильное значение?

    Ответить

    sarge Ответил:

    Еще вопрос, как вы проверяли код, у меня в протеусе завышает на 0.9, то есть

    датчик = -1.0, показывает -0.1

    Ответить

    sarge Ответил:

    Эх заняли вы меня на вечер сегодня :), пошерстил по своим проектам и посмотрел как для меня логично исправить эту ситуацию.

    Функцию получения температуры я переписал в следующем виде:

    unsigned int get_temp() {
    static bit init;
    unsigned char temp1;
    unsigned char temp2;
    
    unsigned int temperature;
    init = INIT();
    if (!init) {
    //printf("init");
    TX(0xCC);
    TX(0x44);
    __delay_ms(150);
    __delay_ms(150);
    __delay_ms(150);
    __delay_ms(150);
    __delay_ms(150); 
    //printf("init");
    } //else printf("bug");
    init = INIT();
    if (!init) {
    TX(0xCC);
    TX(0xBE);
    
    temp1 = RX();
    temp2 = RX();
    
    }
    temp_drob = temp1 & 0b00001111;    
    //temp_drob = ((temp_drob*6)+2)/10;              
    temp1 >>= 4;
    signloc = (temp2 & 0x80) >> 7;
    temp2 <<= 4;
    temp2 &= 0b01110000;
    temp2 |= temp1;
    
    if (signloc) { 
    				if (temp_drob > 0)
    				{
    					temperature = (127-temp2); 
                		temp_drob = ((temp_drob*6)+4)/10;
                		temp_drob = (10 - temp_drob) | 0x80;
                	} else	
                			{
                				temperature = 128-temp2;
                				temp_drob |= 0x80;
                			}	
               	  }
               	   else 
               			{
               				temperature = temp2;
               				temp_drob = ((temp_drob*6)+2)/10;
               			}	
    
    return temperature<<8 | temp_drob;
    
    }
    
    

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

    По идее если ввести переменные с плавающей точкой, то все можно сделать гораздо красивее, но я оставлю это уже вам :)

    Весь проект целиком можно глянуть здесь

    Ответить

    Dim Ответил:

    Настрочил довольно много, потом присмотрелся – в фрагменте кода от моего имени все не совсем так, как я писал, видимо что-то сбилось во время отправки.
    Могу снова попробовать прислать его комментом, но может лучше по почте? Мой адрес у вас полагаю есть, по крайней мере при отправке комментов я его ввожу в форму.
    Могу сразу и проект в протеусе с исходником программы прислать, она простейшая, все видно глазами за минуту.

    Ответить

    Dim Ответил:

    Ну а пока не списались, в порядке тренировки мозгов, возьмем случай когда с DS18B20 приходит значение температуры -1.
    Тогда temp2=0b11111111, temp1=0b11110000
    temp3=0b1111111111110000
    поскольку значение отрицательно, проводим поразрядную инверсию (~), после которой temp3=0b0000000000001111
    temp3+1=0b0000000000010000
    0b0000000000010000/16.0 = 1
    что является значением температуры без десятых и без знака :)

    Ответить

    Dim Ответил:

    А вот случай

    Ответить

  25. Упс, пардон, предыдущее самоотправилось, промазал.
    А вот случай когда на датчике 0:
    temp3=0
    значение положительное, значит считаем по формуле temp3/16
    0/16=0

    Ответить

    sarge Ответил:

    В моей версии новой, что конкретно не устраивает вас? :)
    На репе весь проект лежит, в том числе и под протеус, в виде отдельной библиотеки, которую можно подрубить к любому проекту. Все работает.

    Вообще все эти левые формулы пересчета мне ни разу не нравятся, если хотим сделать что-то универсальное, то надо модифицировать примерно в таком виде:
    1. Установить переменную, отвечающую за разрешение датчика
    2. В зависимости от разрешения пересчитывать дробную часть в виде x = byte_value*разрешение датчика (по дефолту 0.0625 градуса) для плюсовых температур
    x = 10 – byte_value*разрешение датчика (насчет 10 не уверен).
    В случае 0 и отрицательного значения просто добавляем 1 к целочисленному значению.

    Да, когда добавляете код, сразу берите его в теги (кв скобка)code(кв скобка)

    Ответить

    Dim Ответил:

    Если честно, в новой версии не разобрался, ниасилил, многа букаф. То, кусок чего я пытался кинуть, моя первая в жизни прога на си, потому вам мою понять было бы намного проще чем мне вашу :)
    Но что касается формулы пересчета, в том и дело, что не левая она. Как я внезапно осознал, Ds18b20 выдает результат в виде дробного числа с фиксированной точкой, отрицательного или положительного. Не мной этот формат вывода придуман и даже не далласом. А для перевода этого формата представления в другие есть стандартные формулы пересчета, придуманные думаю что задолго до моего рождения… Именно они и универсальны.

    Ответить

    sarge Ответил:

    Дык если хватает памяти я про это и говорю, берем себе и умножаем полученное число на разрешение и добавляем к 0 или отнимаем.

    Распишите ваш алгоритм действий словами по пунктам, и вместе оценим что проще и проанализируем, а то в коде вашем выше пробелов много.

    Ответить

    Dim Ответил:

    temp_drob = temp1 & 0b00001111; //Записываем дробную часть в отдельную переменную
    temp_drob = ((temp_drob*6)+2)/10; //Переводим в нужное дробное число
    temp3=temp2; //добавляем старший байт в переменную для расчета температуры
    temp3<=10) {temp_drob=0;}//чиним ноль
    } else temperature = temp3/16;

    Ответить

  26. [CODE]
    temp_drob = temp1 & 0b00001111; //Записываем дробную часть в отдельную переменную
    temp_drob = ((temp_drob*6)+2)/10; //Переводим в нужное дробное число
    temp3=temp2; //добавляем старший байт в переменную для расчета температуры
    temp3<=10) {temp_drob=0;}//чиним ноль
    } else temperature = temp3/16;
    [/CODE]

    Ответить

  27. Да что ты будешь делать.
    В общем, объявляем переменную unsigned int.
    Загоняем в старший ее байт старший байт полученного с датчика значения, в младший – полученный младший байт.
    Проверяем на минус, если его нет, целое значение температуры равно содержимому этой переменной деленному на 16.
    Если минус есть, побитово инвертируем ее содержимое, прибавляем единицу и делим на 16.

    Ответить

    sarge Ответил:

    а с плюсом, что делать, если есть такая хорошая простая формула для минуса, то надо и для плюса по человечески сделать же? :)

    Ответить

    Dim Ответил:

    С плюсом, просто содержимое этой переменной делим на 16, без затей :)

    Ответить

    sarge Ответил:

    Ок, опробую вечером.

    Ответить

    sarge Ответил:

    Хотя стоп, а с дробным значением что делать? Остаются те же формулы пересчета полагаю? :)

    Тогда ваш алгоритм мало чем от моего отличается (деление на 16 это фактически сдвиг вправо на 4 позиции), у меня просто функция возвращает инт переменную, причем она уже содержит бит с температурой. Просто пришлось добавить проверку 0, но у вас она так же есть.

    Ответить

    Dim Ответил:

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

    Ответить

  28. добрый день!
    изучаю листинг вернее то что в коментах
    не понятно кусок кода
    signloc = (temp2 & 0x80) >> 7;
    в моем понимании это определение знака температуры если это так что это работать не будет по моему мнению
    байт MS=11111XXX или MS=00000XXX
    после строки signloc = (temp2 & 0x80) >> 7;
    signloc будет всегда равна нулю!!!

    Ответить

    sarge Ответил:

    Ну как же, берем байт 0b1xxxxxxx к примеру
    после операции 0b1xxxxxxx & 0x80 у вас остается 0b10000000
    теперь сдвиг вправо на 7 позиций, и ваша 1 перемещается на место младшего бита.
    То что непонятно всегда ведь можно проверить в коде, и даже не обязательно с мк:
    https://dl.dropboxusercontent.com/u/82053027/Capture1.PNG

    Ответить

    reg33 Ответил:

    да проглядел ….показалось что 0х08 а тогда вроде как можно
    signloc=temp2&0x80 без сдвига даст true для if()

    Ответить

    sarge Ответил:

    А вот так можно, да.

    Ответить

  29. Здравствуйте sarge!
    Изучая Ваши листинги неоднократно встречал использование Вами команды printf(). В книжках по Си говорится, что это команда вывода информации на экран монитора. Если я правильно понял, таким образом Вы выводите на экран некоторую отладочно-служебную информацию.
    Великолепный прием! Но, как только я снимаю REM с любой команды в Вашем листинге, тут же получаю ошибку компиляции:

    Warning [361] U:\Pic\Proj\Termometr\Exp16\onewire.c; 106.1 function declared implicit int
    …….. …….. …..
    Serial number: HCPICP-654321 (PRO)
    Error [1098] ../../common/printf.c; 14. conflicting declarations for variable “_printf” (…\Termometr\Exp16\onewire.c:106)

    Библиотека stdio.h в файле main.c подключена.
    Идея очень интересна, но как ей воспользоваться? Подскажите, пожалуйста.

    Ответить

    sarge Ответил:

    Доброго времени суток,

    Два встречных вопроса:
    1. Подключен ли у вас usart.h, usart.c ?
    2. Пробовали ли вы код оригинал, который лежит на репе?

    Очень похоже что вы пытаетесь пользоваться уартом без уарта.

    Ответить

    Paulwasw Ответил:

    Здравствуйте уважаемый sarge!
    Проанализировал ситуацию с проектом. Файлы usart.h и usart.c к проекту подключены (в окне Project MPLAB). Файлы с кодом взяты с репы, несколько причесал на свой вкус отступы табуляции. На всякий случай заменил свежими без редактирования. Как только убираю REM со строк с printf() – сразу ошибка компиляции. Попробовал запустить Ваш проект (тот, что в архиве One-wire_DS18B20.rar), он несколько иной. Убрал REM там – все компилируется!!!
    Кажется, я все понял. По наивности я считал, что если в файле main.c присутствует строка
    #include , значит заголовочный файл подключен к проекту и его содержимым можно пользоваться. Как сказал персонаж из Простоквашино, “Фиг-вам, индейское жилище!”. Если указанная строка присутствует в main.c, то и использовать команду printf() можно только в этом файле, а в файле onewire.c нельзя! А если нужно, то следует разместить директиву препроцессора и в этом файле тоже! Наверное, типичная ошибка начинающего.
    После исправления ошибки все заработало. А если я соберу реальную схему и подключу ее к ПК через RS-232, на реальном экране я увижу сообщения, аналогичные Proteus? Нужно ли при этом запускать терминальную программу на ПК?
    И еще один вопрос, если можно. В Вашем коде использован весьма элегантный прием проваливания/отпускания шины – через TRISA. Вот только когда PIC выдает на шину 0, этот ноль должен быть на выводе RA. А специальной команды установки этого нуля в тексте я не увидел. Расчет на состояние по умолчанию? Везде говорят, что на это лучше не надеяться, а устанавливать уровни принудительно. Я прав или ошибаюсь?

    Ответить

    sarge Ответил:

    Хорошо, что с принтом разобрались, да нужно инклюды ставить везде где пользуетесь командами.

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

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

    Ответить

  30. Dobroe vremya sutok . proboval izuchit primer ds18b20 .pri proverke na proteuse pokazivaet temperaturu ,esli izmenite temperaturu pokazaniya ne izmenyaetsya (ne obnovlyaetsa pokazaniya ) ,esli vikluchaete i vkluchite proteus potom pokazivaet temperaturu, esli esho izmenite temeraturu izmeneniya net.

    Ответить

    sarge Ответил:

    Вы по ссылке на полный проект ходили? Там лежат все файлы в том числе и для моделирования в протеусе.
    Только что попробовал – все меняется и работает без перезапуска протеуса.

    Ответить

  31. nikak ne poluchaetsya , posle izmeneniya temperaturi ne meneyaetsa pokazania , spustya 2-3 minut najimaete knopku 2 pokazivaet novuyu znacheniyu .
    https://bitbucket.org/embedgs/diymicro.ru/src/95fd908f9d99/PicLab/?at=master programma ne kompiliruetsa ,pokazivaet soobsheniya :Error [499] ; 0. undefined symbol:
    _get_temp(ds18b20.obj)

    Ответить

    sarge Ответил:

    Во-первых, ссылка на проект:
    https://bitbucket.org/embedgs/diymicro.ru/src/95fd908f9d994ccc8b029f040e54a90ed93bf95b/PicLab/E16_OneWire/?at=master

    Во-вторых: подключите проект целиком в mplabX, похоже что вы не подключаете заголовочные файлы.

    P.S. Только что попробовал, добавил в код пару строк, теперь еще надпись Starting вываливается сначала – все откомпилилось и запускается, и показания меняются по каждому нажатию кнопки 2.
    P.P.S. Проблема с вашей стороны, код уже неоднократно тестировался, причем не только на симуляторах, но и в железе.

    Ответить

  32. vkluchil vse fayli .otkompilirovalas bez oshibok ,proveril rabotaet . hotel sprosit pochemu pokozaniya posle izmenenii temperaturi ne obnovlyaetsya avtomaticheski , a tolko posle najatii knopki 2 ? SPASIBO

    Ответить

    sarge Ответил:

    Все просто – так написано в коде :)

    Ответить

  33. добрый день!
    в своем коде за основу работы с датчиком взял ваш код…..в принципе все за исключением организации индикации. Так вот у меня слдующая проблема при моделировании в протеусе первый раз датчик инициализируется затеем считываю с него показания и отдаю на индикацию затем при входжении в следующий цикл вернее в фукции INIT (); при переходе от строчки STATE 0; к строке __delay_us (500); на шине DQ появляется 5 вольт и все и никакой дальнейщей реакции не происходит при последующих циклах . я правильно понимаю что перед каждым опросом датчика надо проходить процедуру инициализации

    Ответить

    sarge Ответил:

    Добрый день,

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

    Ответить

    сергей Ответил:

    Добрый день!
    Так и не получилось снять информацию с датчика. Предыдущий пост был не совсем корректным у меня pic16f676 . Собрал схемку в протеусе ну как ранее писал при первом опросе датчик отдает
    temp1 =0x80;
    temp2 =0x80;

    а при повторной инициализации при переходе от строчки STATE 0; к строке __delay_us (500); на шине DQ появляется 5 вольт.
    А ваш проект у меня в mplabx не хочет собираться. Говорит
    error: Configuration “default” builds with “hi-tech-picc”, but no toolchains of that type are installed.
    Errors have occurred while loading one or more configurations.
    If a specific error is not shown above, this may happen when you import a project from another computer.
    + You can add language tools in Tools->Options embedded tab.
    + You can change which language tool to use in the project properties dialog.
    я новичок и только начинаю разбираться и не совсем понял что от меня компилятор требует.

    Ответить

    sarge Ответил:

    Похоже что мплабх не знает где находится Hi-tech PICC.
    Показывайте весь проект с файлом протеуса.

    Ответить

    сергей Ответил:

    был в командировке так что пришлось приостановить изучение весь проект был на домашнем ПК
    вот собственно проект. на данном этапе интересует собственно считывание информации с датчика. Индикация пока не отлажена (вернее она работает при измерения напряжения то биш отлажена но для индикации температуры пока нет)

    https://drive.google.com/file/d/0B7PZJa0xZaSAd1h0RTh1bldQZFE/view?usp=sharing

    с уважением, сергей.

    Ответить

    сергей Ответил:

    блин файл протеуса не залил так что перезаливаю с файлом протеуса https://drive.google.com/file/d/0B7PZJa0xZaSAcVNMbnBXdU9YVVk/view?usp=sharing

    с уважением, сергей.

    Ответить

    sarge Ответил:

    уточните пожалуйста текущий статус, что не работает и как надо чтобы работало и т.д.

    Ответить

    сергей Ответил:

    ну собственно проблема в следующем.
    не получается считать температуру. По началу после первого цикла опроса датчик при последующих иинциализациях датчика протеус упорно говорит что на ноге QD присутствует 5В. Почесав репу дописал строку обнуления порта RC3=0;
    unsigned char INIT(void)//static bit INIT (void) //функция инициализации темп датчик
    {//unsigned char b;//static bit b;
    RC3=0; // обнуляем приемный порт
    STATE=1;
    STATE=0; // проваливаем линию
    __delay_us (500);
    STATE=1; //переключаемся на вход
    __delay_us (65);
    b=PIN; //смотрм чего там на линии
    __delay_us (450); //выжидаем интервал
    return b; // возврашаю ноль или один
    }
    в итоге вроде как опросы идут судя по логу
    PROSPICE 8.04.00 (Build 21003) (C) Labcenter Electronics 1993-2015.
    Loaded netlist ‘C:\Users\RYABEN~1\AppData\Local\Temp\LISA9709.SDF’ for design ‘proect V_A pic16f676.pdsprj’
    PIC12 model release 8.3.00 (Build 20025) simulating PIC16676 device. [U1]
    [DS1822] 9 byte of Persistent EEprom created. [U3_U1]
    Loaded 128 bytes of persistent EEPROM data. [U1]
    Loading HEX file ‘test_dev.X\dist\default\production\test_dev.X.production.hex’. [U1]
    Read total of 1832 bytes from file ‘test_dev.X\dist\default\production\test_dev.X.production.hex’. [U1]
    [D1WIO] Device Information [U3_I1]
    [D1WIO] Family Code:………………28H [U3_I1]
    [D1WIO] Serial N. 48-bit:…000000B8C530H [U3_I1]
    [D1WIO] CRC-8 Code:……………….8EH [U3_I1]
    [D1WIO] Overdrive Support:…………No [U3_I1]
    [DS1822] CONVERT T [44H] command. [U3_U1]
    [DS1822] New data converted. [U3_U1]
    [DS1822] READ SCRATCHPAD [BEh] command. [U3_U1]
    [DS1822] CONVERT T [44H] command. [U3_U1]
    [DS1822] New data converted. [U3_U1]
    [DS1822] READ SCRATCHPAD [BEh] command. [U3_U1]
    [DS1822] CONVERT T [44H] command. [U3_U1]

    но блин неважно какая температура на датчике не была он всегда отдает младший и старший байты
    temp1=0x80;
    temp2=0x80;
    собственно на этом пока буксую

    Ответить

    sarge Ответил:

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

    Вы неправильно переписали функцию RX(), там должно быть d>>=1, а не просто d>>1;
    У меня выводит значение температуры в эти переменные, причем правильное.

    P.S. Еще смотрите аккуратно с таймером, я его пока вырубил, чтобы он не мешал, но я чувствую там могут быть тоже проблемы.

    Ответить

    сергей Ответил:

    ну щас попробую собственно я осваиваю камень опыт в схемотехнике у меня достаточно большой а вот с камнями дело имел только с готовыми прошивками. Начал учится все что сделано было так кнопка с антидребезгом была написана потом прикрутил прерывания потом прикрутил динамическую индикацию потом не хвалило пинов поставил микру дешифратор потом освоил АЦП и вот чет на датчике споткнулся в принципе для понимания я закоментил ненужные вещи типа кнопки и прочее. Так что вроди иду по наростающей…… Таймер у меня делает только одно раз в 1024 слушает не нажата ли кнопка и если нажата по просто обрабатывает ее ну собственно и все. Щас попробую исправить замечания.
    За ранее большое спасибо!

    Ответить

    сергей Ответил:

    да и еще вопрос чем было мотивировано обьявление переменной как static? ее почему то протеус не видит.

    Ответить

    sarge Ответил:

    Честно говоря не помню.
    Возможно в хайтече нельзя объявить тип переменной bit без статика, но это так, обрывочные воспоминания, не уверен совсем в них.

    Ответить

  34. Переношу оп Вашей просьбе сюда.
    В протеусе пока не собирал, но вот что нашел в процессе поиска решения (взято отсюда – http://forum.chipmk.ru/index.php/topic/863-%d1%83%d0%bf%d1%80%d0%b0%d0%b2%d0%bb%d0%b5%d0%bd%d0%b8%d0%b5-%d0%b2%d1%8b%d1%85%d0%be%d0%b4%d0%be%d0%bc-pic12f629-%d0%bf%d1%80%d0%b8-%d0%b2%d0%bd%d0%b5%d1%88%d0%bd%d0%b5%d0%b9-%d0%bf%d0%be%d0%b4%d1%82%d1%8f%d0%b6%d0%ba%d0%b5/page__p__13833__hl__ds18b20__fromsearch__1#entry13833 ):

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

    Вспомнил один из своих проектов, там надо было прочитать порты, после этого заработало : GPIO=GPIO;
    Поэтому решил добавить в Ваш код тоже самое после изменения направления порта, т.е. после STATE = 1 ил 0; добавил GPIO=GPIO;
    Увы, пока без изменений.

    Ответить

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

Можно использовать следующие HTML-теги и атрибуты: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code class="" title="" data-url=""> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre class="" title="" data-url=""> <span class="" title="" data-url="">

Этот сайт использует Akismet для борьбы со спамом. Узнайте как обрабатываются ваши данные комментариев.