Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: DS18B20 Read time-slot
Форум разработчиков электроники ELECTRONIX.ru > Сайт и форум > В помощь начинающему > MCS51, AVR, PIC, STM8, 8bit
RN3QLQ
Подключаю один датчик 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
Пытаюсь реализовать вот этут библиотеку

DS18B20.c
CODE

#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
CODE


#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 подобным образом?
Владивольт
Цитата
Код
//«отпускает», управление передается датчику
    DDRD &= ~(1<<PD7);//0 - вход
    PORTD &= ~(1<<PD7);//0
    
        bit = (PIND & (1<<PD7));


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

Чем попусту тратить время
Цитата
Код
        _delay_us(45);//задержка 1 мкс ,перед записью следующего бита

-- посвятить эти 45 мкс нескольким чтениям PIND и произвести анализ
RN3QLQ
Владивольт, спасибо! Именно в этом и причина была.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.