Перейти к содержанию
    

DS18B20 Read time-slot

Подключаю один датчик 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;
}

 

Подскажите, может задержки не те? Грешу только на эту функцию

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Пытаюсь реализовать вот этут библиотеку

 

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 подобным образом?

Изменено пользователем RN3QLQ

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

//«отпускает», управление передается датчику
    DDRD &= ~(1<<PD7);//0 - вход
    PORTD &= ~(1<<PD7);//0
    
        bit = (PIND & (1<<PD7));

 

возможно, "отпускаемая" цепь не успевает вернуться к высокому уровню,

ёмкость с подключением второго чипа увеличилась.

 

Чем попусту тратить время

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

-- посвятить эти 45 мкс нескольким чтениям PIND и произвести анализ

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

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

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...