RN3QLQ 0 19 января, 2017 Опубликовано 19 января, 2017 · Жалоба Подключаю один датчик DS18B20 к Atmega128. Инициализация, SkipROM, ConverT все эти функции работают - температура на дисплее. Подсоединяю на шину второй датчик. Инициализация проходит, послылается команда SearchROM(0xF0) и при чтении тайм-слотов приходят нули на обоих слотах и никак это дело не изменить. кусок кода чтения битов: unsigned char read_bit_data(void) { unsigned char bit; DDRD |= (1<<PD7);//1 - выход PORTD &= ~(1<<PD7);//0 _delay_us(15);//задержка 15 мкс //«отпускает», управление передается датчику DDRD &= ~(1<<PD7);//0 - вход PORTD &= ~(1<<PD7);//0 bit = (PIND & (1<<PD7)); _delay_us(45);//задержка 1 мкс ,перед записью следующего бита return bit; } Подскажите, может задержки не те? Грешу только на эту функцию Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
RN3QLQ 0 20 января, 2017 Опубликовано 20 января, 2017 (изменено) · Жалоба Пытаюсь реализовать вот этут библиотеку DS18B20.c #include "ds18b20.h" #include "led.h" #include <util/delay.h> #include <stdint.h> #include <avr/interrupt.h> uint8_t data[kol_vo][8]; /*Функция поиска датчиков, возвращает кол-во найденых датчиков*/ uint8_t ds18b20_search(void) { //локальные переменные для поиска датчиков uint8_t p = 1; // // переменная для цикла считыввания кода uint8_t bit = 0x01;// начальная позиция бита uint8_t New_conflict = 0; ; //переменная для новой позиции бита uint8_t last_conflict = 0; //переменная для старой позиции бита uint8_t i,j,n=0; uint8_t crc8, data_crc,u; for (i = 0; i < kol_vo; i++) //обнулим массив { for (j = 0; j < 8; j++)//8-м байт { data[i][j] = 0x00; } } j=i=0;//обнуляем переменные unsigned char bit1, bit2; //переменные для сравнения битов двух тайм слотов do { New_conflict = 0; n++; init_devise(); // импульс сброса send_command(0xf0); // команда поиска // сигнал сброса и команда поиска необходимо подавать для каждого датчика while (p <= 64) // пока не будут прочитаны все 64 бита { bit1 = read_data();//первый тайм-слот bit2 = read_data();//второй тайм-слот if (bit1 && bit2) // сравниваем полученные биты , если обе единицы Display(000);// датчиков нет на линии else if ((bit1) && (!bit2))// датчикоа нет на линии data[i][j] |= bit;//записываем бит else if((!bit1) && (bit2)) data[i][j] &= ~bit; else if((!bit1) && (!bit2))//Конфликт оба 0 { //сдесь будем сравнивать позиции битов, в номерах которых произошли конфликты в переменной N_conflict if (p == last_conflict)//если текущая позиция бита в котром произошел конфликт == позиции в предыдущем исчеслении (скорей всего 0-ая позиция), то запишем в адресс 1 data[i][j] |= bit; else if (p > last_conflict)// если номер позиции больше, номера предыдущего опроса, то запишем 0 и номер позиции конфликта обновим { data[i][j] &= ~bit; New_conflict = p; } //если вдруг текущий номер позиции меньше, номера позиции предыдущего исчесления(Если вдруг текущий бит, при конфликте, при очередном исчеслении не дошел еще до номера //конфликта предыдущего исчесления, содержит 0 , то это будет считаться новым конфликтом) else if (!(data[i][j] & bit)) New_conflict = p; } // Далее запишем соответствующий бит, который при следующем исчеслении включит соответствующие устройства if(data[i][j] & bit) { //Display(123); cli(); //Запретим общие прерывания DDR_DS |= _BV(PIN_DS);//1 - выход PORT_DS &= ~_BV(PIN_DS);//0 _delay_us(15);//задержка 15 мкс //«отпускает» DDR_DS &= ~_BV(PIN_DS);//0 - вход PORT_DS &= ~_BV(PIN_DS);//0 _delay_us(45);//задержка 46 мкс ,берем чуть больше sei();// разрешаем прерывания } else //передаем 0 { cli(); //Запретим общие прерывания DDR_DS |= _BV(PIN_DS);//1 - выход PORT_DS &= ~_BV(PIN_DS);//0 _delay_us(120);//задержка 120 мкс //«отпускает» DDR_DS &= ~_BV(PIN_DS);//0 - вход PORT_DS &= ~_BV(PIN_DS);//0 _delay_us(1);//задержка 1 мкс ,перед записью следующего бита sei();// разрешаем прерывания } p++;//увеличиваем на 1 bit <<= 1;//сдвигаем влево if (!bit) //сдвиг проходит все 8 бит и значение равно 0 { data[i][j++]; bit = 0x01; } }//выходит из цикла после обработки 64-х битов last_conflict = New_conflict; p = 1; if (last_conflict != 0) data[i++][j]; j = 0; bit = 0x01; } while (last_conflict != 0); // пока номер бита конфликта не равен 0, если равен то все датчики найдены Display(n);// выводим количество найденых датчиков _delay_ms(2000); //Датчики найдены, адреса занисаны, необходимо проверить правильность перданной информации i = 0;//обнулим, начнем проверрку с 0-х индексов j = 0; while(i != kol_vo)//обрабатываем количество устройствначинаем с последнего устройства { crc8 = 0; for(j = 0; j < 7; j++) { unsigned char bit_crc; //локальная переменная data_crc = data[kol_vo][j]; for (u = 0 ; u < 8; u++) { bit_crc = ((crc8 ^ data_crc) & 0x01); if (bit_crc == 0) crc8 >>= 1; else { crc8 ^= 0x18;// 11000 , по модулю т.е. там где0 и 1 будут 1 crc8 >>= 1; //сдвгаем влево crc8 |= 0x80;//+ 1000 0000 } data_crc >>=1; } } if (crc8 == data[kol_vo][j]) // если последний байт четности равныто хорошо { i++; Display(kol_vo); _delay_ms(1000); j = 0; } else { Display(9.7); _delay_ms(1000);} } } /* Считывание преобазованной температуры*/ float read_ds18b20(void) { //static uint8_t i1; uint8_t i,j,crc8, data_crc,u,temp,temp_int, temp_float; for (i = 0; i< kol_vo; i++) //начинаем с первого датчика { uint8_t temperature[9]; init_devise();//импульс сброса и присутствие send_command(0x55);//комманда соответствия // после передадим код устройства к которому обращаемся for (j = 0; j < 8 ; j++) { unsigned char data_byte; // переменная для передачи кода data_byte = data[i][j]; send_command (data_byte); //передаем побайтово код устройства } send_command (0x44);//комманда преобразования while (!read_data()) ;// выполняется цикл до тех пор пока на линии не установится 1 init_devise();//импульс сброса и присутствие send_command(0x55);//комманда соответствия for (j = 0; j < 8 ; j++) // опять передаем адресс устройствак которому будем обращаться { unsigned char data_byte; // переменная для передачи кода data_byte = data[i][j]; send_command (data_byte); //передаем побайтово код устройства } send_command (0xbe);//комманда чтение памяти for (j = 0; j <= 8; j++) //считываем первые два байта температуры { unsigned char i;//локальная переменная для внутреннего цикла unsigned char data_temp = 0x00; for (i = 0; i < 8; i++) { data_temp >>= 1; if (read_data()) //если 1, то устанавливаем старший бит 1 data_temp |= 0x80; } temperature[j] = data_temp; } init_devise(); //проверяем целостность информации измеренной температуры crc8 = 0; for(j = 0; j < 8; j++) { unsigned char bit_crc; //локальная переменная data_crc = temperature[j]; for (u = 0 ; u < 8; u++) { bit_crc = ((crc8 ^ data_crc) & 0x01); if (bit_crc == 0) crc8 >>= 1; else { crc8 ^= 0x18;// 11000 , по модулю т.е. там где0 и 1 будут 1 crc8 >>= 1; //сдвгаем влево crc8 |= 0x80;//+ 1000 0000 } data_crc >>=1; } } if (crc8 == temperature[j]) // если последний байт четности равныто хорошо { //Display(123); //_delay_ms(100); } else { Display(444); _delay_ms(100); } if ((temperature[1]&128) == 0) ;//i1=1;//PORTB &= ~_BV(PB3); // то плюс , зажигаем красный диод else { temp = ((unsigned int)temperature[1]<<8) | temperature[0]; temp = ~temp + 1; temperature[0] = temp; temperature[1] = temp>>8; //i1=-1;//PORTC |= _BV(PC3); //то минус , зажигаем зеленый диод }; temp_int = ((temperature[1]&7)<<4)|(temperature[0]>>4); //выводим целое знач. температуры //выделяем с помощью битовой маски дробную часть temp_float = (temperature[0]&15); //преобразуем в целое число //temp_float = (temp_float << 1) + (temp_float << 3);// Умножаем на 10 //temp_float = temp_float * 0.0625;//(temp_float >> 4);//делим на 16 или умножаем на 0.0625 Display((temp_float*0.0625) + temp_int); _delay_ms(1000); temp_int = 0; temp_float = 0; } } uint8_t init_devise(void) { cli(); DDR_DS |= _BV(PIN_DS);//1 - выход PORT_DS &= ~_BV(PIN_DS);//0 _delay_us(480);//задержка 480 мкс //«отпускает» DDR_DS &= ~_BV(PIN_DS);//0 - вход PORT_DS &= ~_BV(PIN_DS);//0 _delay_us(70);//задержка 70 мкс ,берем чуть больше после перепада if (!sost) ;//Display(111);//присутствует; else Display(000);//нету _delay_us(410);//остальная задержка для окончания импульса присутствия sei();// разрешаем прерывания } uint8_t send_command (unsigned char command) { unsigned char i; //unsigned char command = 0xf0;//комманда поиска for (i=0; i < 8; i++) { if (command & 0x01) // если позиция бита 1, то передаем 1 { cli(); //Запретим общие прерывания DDR_DS |= _BV(PIN_DS);//1 - выход PORT_DS &= ~_BV(PIN_DS);//0 _delay_us(15);//задержка 15 мкс //«отпускает» DDR_DS &= ~_BV(PIN_DS);//0 - вход PORT_DS &= ~_BV(PIN_DS);//0 _delay_us(45);//задержка 46 мкс ,берем чуть больше sei();// разрешаем прерывания } else //передаем 0 { cli(); //Запретим общие прерывания DDR_DS |= _BV(PIN_DS);//1 - выход PORT_DS &= ~_BV(PIN_DS);//0 _delay_us(120);//задержка 120 мкс //«отпускает» DDR_DS &= ~_BV(PIN_DS);//0 - вход PORT_DS &= ~_BV(PIN_DS);//0 _delay_us(1);//задержка 1 мкс ,перед записью следующего бита sei();// разрешаем прерывания } command >>= 1;//сдвигаем вправо для обработки следующего бита } } unsigned char read_data(void) { unsigned char bit; cli(); //Запретим общие прерывания DDR_DS |= _BV(PIN_DS);//1 - выход PORT_DS &= ~_BV(PIN_DS);//0 _delay_us(15);//задержка 15 мкс //«отпускает», управление передается датчику DDR_DS &= ~_BV(PIN_DS);//0 - вход PORT_DS &= ~_BV(PIN_DS);//0 bit = sost; _delay_us(45);//задержка 1 мкс ,перед записью следующего бита sei();// разрешаем прерывания return bit; } DS18B20.h #ifndef ds18b20_h #define ds18b20_h #include <stdint.h> #define PORT_DS PORTB #define DDR_DS DDRB #define PIN_DS PB2 #define kol_vo 2 //количество подключенных датчиков #define sost (PINB & 0x04) // номер пина который надо проверить //unsigned char data [kol-vo][8];// массив для хранения даных датчиков (глобальная для передачи данных) float read_ds18b20(void); ; // Чтение преобразованной уже температуры uint8_t ds18b20_search(void); uint8_t send_command (unsigned char command);//обьявляем функцию пердачи комманды unsigned char read_data(void); //читаем данные с датчика uint8_t init_devise(void);//обьявляем функцию #endif и никак не выйти из бесконечного цикла функции поиска кодов устройств ds18b20_search(), т.к. тайм-слоты всегда приходят 0 и 0. Есть ли у кого-ниудь опыт реализации общения с датчиками DS18B20 подобным образом? Изменено 21 января, 2017 пользователем RN3QLQ Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Vladivolt 0 21 января, 2017 Опубликовано 21 января, 2017 · Жалоба //«отпускает», управление передается датчику DDRD &= ~(1<<PD7);//0 - вход PORTD &= ~(1<<PD7);//0 bit = (PIND & (1<<PD7)); возможно, "отпускаемая" цепь не успевает вернуться к высокому уровню, ёмкость с подключением второго чипа увеличилась. Чем попусту тратить время _delay_us(45);//задержка 1 мкс ,перед записью следующего бита -- посвятить эти 45 мкс нескольким чтениям PIND и произвести анализ Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
RN3QLQ 0 21 января, 2017 Опубликовано 21 января, 2017 · Жалоба Владивольт, спасибо! Именно в этом и причина была. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться