Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Программная инженерия > Микроконтроллеры, робототехника, схемотехника, 3D принтеры
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 19.04.2019, 02:03   #1
NikEvgMaster
Новичок
Джуниор
 
Регистрация: 19.04.2019
Сообщений: 2
По умолчанию Греются ds18b20, нет ответа. Atmega328p

Не пойму почему не работает программный 1-Wire на 328 меге. Может я там где-то что-то с портами напутал? Диод мигает с частотой в 0.5 Гц, как положено. Дисплей по i2c пашет, часы тоже. Подлючал gnd, 5v, а между ними пин на пин В1 с подтяжкой к нему 5v через резистор 4, потом еще 10 кОм пробовал.

Дописал проверку присутствия устройств на шине, если ответа нет, то мигает диод - мигает бл.... Ответа нет. Что делать?

Текст библиотечного/хэдерного файла 1-WIRE:
Код:
#define DEVICES_ERROR  1

#define CMD_CONVERTTEMP    0x44
#define CMD_RSCRATCHPAD    0xbe
#define CMD_WSCRATCHPAD    0x4e
#define CMD_CPYSCRATCHPAD  0x48
#define CMD_RECEEPROM      0xb8
#define CMD_RPWRSUPPLY     0xb4
#define CMD_SEARCHROM      0xf0
#define CMD_READROM        0x33
#define CMD_MATCHROM       0x55
#define CMD_SKIPROM        0xcc
#define CMD_ALARMSEARCH    0xec
#define uint64_t long long
#define uint8_t char
#define uint16_t int
#define uint32_t long
uint8_t ONE_WIRE_DQ = 1;

void oneWireInit(uint8_t pin) {
  ONE_WIRE_DQ = pin;
  ONE_WIRE_DDR |= (1 << ONE_WIRE_DQ); // выход
  ONE_WIRE_PORT |= (1 << ONE_WIRE_DQ);
  _delay_ms(400);
  ONE_WIRE_DDR &= ~(1 << ONE_WIRE_DQ); // вход
}

/*
 * сброс
 */
uint8_t reset() {
  uint8_t response=0;

  // импульс сброса, минимум 480us
  ONE_WIRE_DDR |= (1 << ONE_WIRE_DQ); // выход
  ONE_WIRE_PORT &= ~(1 << ONE_WIRE_DQ);//0
  _delay_us(480);

  // Когда ONE WIRE устройство обнаруживает положительный перепад, он ждет от 15us до 60us
  ONE_WIRE_DDR &= ~(1 << ONE_WIRE_DQ); // вход
  _delay_us(65);

  // и затем передает импульс присутствия, перемещая шину в логический «0» на длительность от 60us до 240us.
  response = (ONE_WIRE_PIN & (1 << ONE_WIRE_DQ));
  _delay_us(250);
  if (response){                               //ПРОВЕРКА ОТЗЫВА УСТРОЙСТВ
	  PORTC |= (1<<3);
		_delay_ms(200);
		PORTC &= ~(1<<3);
		_delay_ms(200);
		PORTC |= (1<<3);
		_delay_ms(200);
		PORTC &= ~(1<<3);
		_delay_ms(200);
		PORTC |= (1<<3);
		_delay_ms(200);
		PORTC &= ~(1<<3);
		_delay_ms(200);
		PORTC |= (1<<3);
		_delay_ms(200);
		PORTC &= ~(1<<3);
		_delay_ms(200);
		PORTC |= (1<<3);
		_delay_ms(200);
		PORTC &= ~(1<<3);
		_delay_ms(200);
		PORTC |= (1<<3);
		_delay_ms(200);
		PORTC &= ~(1<<3);
		_delay_ms(200);
		PORTC |= (1<<3);
		_delay_ms(200);
		PORTC &= ~(1<<3);
		_delay_ms(200);
		PORTC |= (1<<3);
		_delay_ms(200);
		PORTC &= ~(1<<3);
  }
  // если 0, значит есть ответ от датчика, если 1 - нет
  return response;
}

/*
 * отправить один бит
 */
void writeBit(uint8_t bit) {
  if (bit & 1) {
    //cli();
    // логический «0» на 1us
    ONE_WIRE_DDR |= (1 << ONE_WIRE_DQ); // выход
    ONE_WIRE_PORT &= ~(1 << ONE_WIRE_DQ);//0
    _delay_us(8);
    //sei();
    ONE_WIRE_DDR &= ~(1 << ONE_WIRE_DQ); // вход
    _delay_us(62);
  } else {
    //cli();
    // логический «0» на 1us
    ONE_WIRE_DDR |= (1 << ONE_WIRE_DQ); // выход
    ONE_WIRE_PORT &= ~(1 << ONE_WIRE_DQ);
    _delay_us(62);
    ONE_WIRE_DDR &= ~(1 << ONE_WIRE_DQ); // вход
    //sei();
    _delay_us(8);
  }
}

/*
 * отправить один байт
 */
void writeByte(uint8_t byte) {
  uint8_t i = 8;
  while (i>0) {
    writeBit(byte & 1);
    byte >>= 1;
	i--;
  }
}



/*
 * получить один бит
 */
char readBit (void) {
  uint8_t bit = 0;
  //cli();
  // логический «0» на 1us
  ONE_WIRE_DDR |= (1 << ONE_WIRE_DQ); // выход
  ONE_WIRE_PORT &= ~(1 << ONE_WIRE_DQ);//0
  _delay_us(6);
 
  // освободить линию и ждать 14us
  ONE_WIRE_DDR &= ~(1 << ONE_WIRE_DQ); // вход
  _delay_us(10);

  // прочитать значение
  if (ONE_WIRE_PIN & (1 << ONE_WIRE_DQ)) {
    bit = 1;
  }

  // ждать 45us и вернуть значение
  //sei();
  _delay_us(55);
  return bit;
}


/*
 * получить один байт
 */
uint8_t readByte() {
  uint8_t i = 8, byte = 0;
  while (i>0) {
    byte >>= 1;
    byte |= (readBit() << 7);
	i--;
  }
  return byte;
}

/*
 * читать ROM подчиненного устройства (код 64 бита)
 */
uint64_t readRoom(void) {
  uint64_t oneWireDevice;
  if(reset() == 0) {
    writeByte(CMD_READROM);
    //  код семейства
    oneWireDevice = readByte();
    // серийный номер
    oneWireDevice |= (uint16_t)readByte()<<8 | (uint32_t)readByte()<<16 | (uint32_t)readByte()<<24 | (uint64_t)readByte()<<32 | (uint64_t)readByte()<<40 | (uint64_t)readByte()<<48;
    // CRC
    oneWireDevice |= (uint64_t)readByte()<<56;
  } else {
    return 1;
  }
  return oneWireDevice;
}

/*
 * Команда соответствия ROM, сопровождаемая последовательностью 
 * кода ROM на 64 бита позволяет устройству управления шиной 
 * обращаться к определенному подчиненному устройству на шине.
 */
void setDevice(uint64_t rom) {
  uint8_t i = 64;
  reset();
  writeByte(CMD_MATCHROM);
  while (i--) {
    writeBit(rom & 1);
    rom >>= 1;
  }
}

/*
 * провеска CRC, возвращает "0", если нет ошибок
 * и не "0", если есть ошибки
 */
uint8_t crcCheck(uint64_t data8x8bit, uint8_t len) {
  uint8_t dat, crc = 0, fb, stByte = 0;
  do {
    dat = (uint8_t) (data8x8bit >> (stByte * 8));
    for (int i = 0; i < 8; i++) {  // счетчик битов в байте
      fb = crc ^ dat;
      fb &= 1;
      crc >>= 1;
      dat >>= 1;
      if (fb == 1) {
        crc ^= 0x8c; // полином
      }
    }
    stByte++;
  } while (stByte < len); // счетчик байтов в массиве
  return crc;
}


/*
 * поиск следующего подключенного устройства
 */
uint64_t searchNextAddress(uint64_t lastAddress, uint8_t * lastDiscrepancy) {
  uint8_t searchDirection = 0;
  uint64_t newAddress = 0;
  uint8_t idBitNumber = 1;
  uint8_t lastZero = 0;
  reset();
  writeByte(CMD_SEARCHROM);

  while (idBitNumber < 65) {
    uint8_t idBit = readBit();
    uint8_t cmpIdBit = readBit();

    // id_bit = cmp_id_bit = 1
    if (idBit == 1 && cmpIdBit == 1) {
      return DEVICES_ERROR;
    } else if (idBit == 0 && cmpIdBit == 0) {
      // id_bit = cmp_id_bit = 0
      if (idBitNumber == *lastDiscrepancy) {
        searchDirection = 1;
      } else if (idBitNumber > *lastDiscrepancy) {
        searchDirection = 0;
      } else {
        if ((uint8_t) (lastAddress >> (idBitNumber - 1)) & 1) {
          searchDirection = 1;
        } else {
          searchDirection = 0;
        }
      }
      if (searchDirection == 0) {
        lastZero = idBitNumber;
      }
    } else {
      // id_bit != cmp_id_bit
      searchDirection = idBit;
    }
    newAddress |= ((uint64_t) searchDirection) << (idBitNumber - 1);
    writeBit(searchDirection);
    idBitNumber++;
  }
  *lastDiscrepancy = lastZero;
  return newAddress;
}

/*
 * поиск устройств
 */
void searchRom(uint64_t * roms, uint8_t * n) {
  uint64_t lastAddress = 0;
  uint8_t lastDiscrepancy = 0;
  uint8_t err = 0;
  uint8_t i = 0;
  do {
    do {
      lastAddress = searchNextAddress(lastAddress, &lastDiscrepancy);
      if(lastAddress != DEVICES_ERROR) {
        uint8_t crc = crcCheck(lastAddress, 8);
        if (crc == 0) {
          roms[i++] = lastAddress;
          err = 0;
        } else {
          err++;
        }
      } else {
        err++;
      }
      if (err > 3) {
        return;
      }
    } while (err != 0);
  } while (lastDiscrepancy != 0 && i < *n);
  *n = i;
}



/*
 * пропустить ROM
 */
void skipRom() {
  reset();
  writeByte(CMD_SKIPROM);
}
NikEvgMaster вне форума Ответить с цитированием
Старый 19.04.2019, 02:04   #2
NikEvgMaster
Новичок
Джуниор
 
Регистрация: 19.04.2019
Сообщений: 2
По умолчанию

Майн:
Код:
#define F_CPU				16000000UL
#define ONE_WIRE_PORT      PORTB
#define ONE_WIRE_DDR       DDRB
#define ONE_WIRE_PIN       PINB
//#include <asf.h>
#include <avr/io.h>
#include <util/delay.h>
#include <stdlib.h>
#include <math.h>
//#include <avr/interrupt.h>

//#include "сonfig.h"
#include "OwnWire.h"

#include "OLED_Function.h" //включает функции для работы дисплея
#include "drawing.h"	   //включает функции по прорисовке на дисплее определенных элементов, а также массивы шрифтов
#include "function_clock.h"



char Rel1 = 5;//переменные для хранения вкл/выкл реле
char Rel2 = 7;
char Rel3 = 9;
char Rel4 = 11;
char Rel5 = 13;
char D_time = 4;//переменная для хранения значения день- ночь

char hoursH = 0;//переменные для сохранения байтов с часов и вывода на экран
char hoursL = 0;
char minutesH = 0;
char minutesL = 0;
char colon = 10;//:
char secondsL = 0;
char secondsH = 0;

char int_t1 = 28;//переменные для хранения уставок температур и времени в формате +/- ХХ
char int_t2 = 99;
char int_t3 = 0;
char ext_t = 0;

char seconds = 0; //непереработанные данные с часов
char minutes = 0;
char hours = 0;
char days = 0;
char monthes = 0;
char years = 0;
char weekday = 0;

char hour_transf=0;//переработанные часы

char int_t1H = 0;//старшие и младшие разряды температур
char int_t1L = 0;
char sign1 =0;
char int_t2H = 0;
char int_t2L = 0;
char int_t3H = 0;
char int_t3L = 0;
char ext_tH = 0;
char ext_tL = 0;

char temperatura1=0;//с часов
char temperatura2=99;
char temperatura3=33;
char temperatura4=00;//уличная t

//char h=23; //уставки для записи времени в ds3231
//char m=00;
//char s=0;

//=========================================================
char getTemp(uint64_t ds18b20s) { // must contain 64 bit
	char temperatureL=0;
	char temperatureH=0;
	char retd = 0;


	setDevice(ds18b20s);
	writeByte(CMD_CONVERTTEMP);

	_delay_ms(750);

	setDevice(ds18b20s);
	writeByte(CMD_RSCRATCHPAD);

	temperatureL = readByte();
	temperatureH = readByte();

	retd = ((temperatureL>>4)&0b00001111)|((temperatureH<<4)&0b01110000);		//прокатит, если положительная температура

return retd;}
//==========================================================

int main(void){
	//board_init();
	DDRC |= (1<<0)|(1<<1)|(1<<2)|(1<<3);
	PORTC &= ~((1<<0)|(1<<1)|(1<<2)|(1<<3));
	
	
	static_elements();
	//ds3231_init();				//инициализация часов ds3231
	//ds3231_write_time(h,m,s);		//запись времени в часы
	
	//====================
	oneWireInit(1);
	reset();
	char n = 3;
	long long roms[n];					//нужно вместить 64 бита
	searchRom(roms, &n);
	_delay_ms(2000);
	//====================
	
	while (1)
	{
		//=======================================
		temperatura2 = getTemp(roms[0]);
		temperatura3 = getTemp(roms[1]);
		temperatura4 = getTemp(roms[2]);
		_delay_ms(1000);
		
		//======================================
		
		ds3231_read_temper(&int_t1H,&int_t1L, &sign1, &temperatura1);//передал адреса переменных, куда часы сохранят температуру и знак
		ds3231_read_time(&seconds,&minutes,&hours,&days,&monthes,&years,&weekday);
		
		minutesL = minutes&0b00001111;
		minutesH = ((minutes&0b01110000)>>4);
		hour_transf = (((hours & 0xF0) >> 4)*10)+(hours & 0x0F);
		hoursL = hours&0b00001111;
		hoursH = ((hours&0b01110000)>>4);
		secondsL = seconds&0b00001111;
		secondsH = ((seconds&0b01110000)>>4);
		
		drawing_clock(hoursH,hoursL,minutesH,minutesL,colon);
		
		temper_transform(temperatura2,&int_t2H,&int_t2L);//по указателю
		temper_transform(temperatura3,&int_t3H,&int_t3L);
		temper_transform(temperatura4,&ext_tH,&ext_tL);
		
		if(temperatura1<int_t1) {		//реле1 в зависим от t1
			Rel1=6;
			PORTC |= (1<<2);
		}
		else {
			Rel1=5;
			PORTC &= ~(1<<2);
		}
		
		drawing_temperatures(ext_tH,int_t1H,ext_tL,int_t1L,int_t2H,int_t3H,int_t2L,int_t3L);
		
		if((hour_transf>0 && hour_transf<7) || (hour_transf==23)){//в ночное время вкл бойлер на 0 пине порта C
			D_time=15;
			PORTC |= (1<<0);
			Rel5 = 14;
		}
		else {							//днем горит солнышко и бойлер выкл
			D_time=4;
			PORTC &= ~(1<<0);
			Rel5 = 13;
		}
		
		drawing_relay (Rel1,Rel2,Rel3,Rel4,Rel5,D_time);//вывод реле и времени дня
		PORTC |= (1<<3);
		_delay_ms(1000);
		PORTC &= ~(1<<3);
		_delay_ms(1000);
		PORTC |= (1<<3);
		_delay_ms(1000);
		PORTC &= ~(1<<3);
		_delay_ms(1000);
		PORTC |= (1<<3);
		_delay_ms(1000);
		PORTC &= ~(1<<3);
		_delay_ms(1000);
		PORTC |= (1<<3);
		_delay_ms(1000);
		PORTC &= ~(1<<3);
		_delay_ms(1000);
		PORTC |= (1<<3);
		_delay_ms(1000);
		PORTC &= ~(1<<3);
		_delay_ms(1000);
		PORTC |= (1<<3);
		_delay_ms(1000);
		PORTC &= ~(1<<3);
		_delay_ms(1000);
		PORTC |= (1<<3);
		_delay_ms(1000);
		PORTC &= ~(1<<3);
		_delay_ms(1000);
		PORTC |= (1<<3);
		_delay_ms(1000);
		PORTC &= ~(1<<3);
	}
}
NikEvgMaster вне форума Ответить с цитированием
Старый 19.04.2019, 14:54   #3
digitalis
Старожил
 
Аватар для digitalis
 
Регистрация: 04.02.2011
Сообщений: 4,529
По умолчанию

Если долго не ответят (тут Atmel-щиков мало), можно попробовать
https://radiokot.ru/forum/viewtopic.php?f=57&t=21695
Просто почитать тему; если прояснения не произойдет - зарегиться и спросить. Народ в основном доброжелательный, скорее всего помогут.
Сам я Atmel-щик, но DS-кой этой не занимался и для Мег пишу на асме, не люблю я Си для МК.
digitalis вне форума Ответить с цитированием
Старый 11.09.2020, 07:08   #4
askmix
Новичок
Джуниор
 
Регистрация: 11.09.2020
Сообщений: 1
По умолчанию

Возможно поздно ответил, но: во-первых датчикам незачем греться (либо испорченные, либо не правильно подключенные), во-вторых проверяй железо на сторонней "испытаной" программе.
askmix вне форума Ответить с цитированием
Старый 11.09.2020, 11:51   #5
zvygin1964
Старожил
 
Аватар для zvygin1964
 
Регистрация: 19.06.2013
Сообщений: 2,463
По умолчанию

Согласен.
Репутация: полный "0"
zvygin1964 вне форума Ответить с цитированием
Старый 04.07.2021, 23:13   #6
AlexInch
Новичок
Джуниор
 
Регистрация: 04.07.2021
Сообщений: 4
По умолчанию

Возможно, я ещё более поздно ответил. Но лучше поздно, чем никогда.
---
Насколько я понял, написанная выше программа программирует пин процессора на выход
и выдаёт сигналы датчику DS18B20. Если это так, то это ошибка и датчики могут
греться и выйти из строя вместе с пином процессора.
----
я делал так:
1. Спрограммируем пин "на ввод" в регистре направления, а в регистр данных пина занесём 0.
2. Когда надо выдать 0 датчику, программируем в регистре направления пин "на вывод" .
На пине появится 0.
3. когда надо выдать 1 датчику, программируем в регистре направления пин "на ввод" .
Подтягивающий резистор обеспечит подъём уровня к 1.
Т.е. программа должна манипулировать только регистром направления, иначе на шине
может быть аппаратный конфликт.
---
Кстати, эти датчики бывают ещё и разных видов. Это можно узнать по сигнатуре в ROM
и алгоритм добычи температуры будет (увы !) различаться.

Последний раз редактировалось AlexInch; 04.07.2021 в 23:27.
AlexInch вне форума Ответить с цитированием
Старый 05.07.2021, 10:37   #7
digitalis
Старожил
 
Аватар для digitalis
 
Регистрация: 04.02.2011
Сообщений: 4,529
По умолчанию

Очень своевременно, всего чуть больше 2 лет прошло.
Метод получения 2-направленной линии, конечно, нормальный. Мне его в своё время подсказали для I2C. Лет 30 назад
----------------
Судя по языку, новичок ТС - не из России?

Последний раз редактировалось digitalis; 05.07.2021 в 10:40.
digitalis вне форума Ответить с цитированием
Старый 05.07.2021, 12:20   #8
AlexInch
Новичок
Джуниор
 
Регистрация: 04.07.2021
Сообщений: 4
По умолчанию

Цитата:
Сообщение от digitalis Посмотреть сообщение
Очень своевременно, всего чуть больше 2 лет прошло.
Метод получения 2-направленной линии, конечно, нормальный. Мне его в своё время подсказали для I2C. Лет 30 назад
----------------
А вдруг кому-нибудь пригодиться ? Автор темы не отписался о достигнутых успехах.
---
Про 30 лет это я не очень понял.
30 лет назад AVR не было - они появились приблизительно в 1999-2000 году.
У микроконтроллеров ранних времён так порты не программировались (насколько я знаю).
AlexInch вне форума Ответить с цитированием
Старый 05.07.2021, 21:50   #9
digitalis
Старожил
 
Аватар для digitalis
 
Регистрация: 04.02.2011
Сообщений: 4,529
По умолчанию

Так время медленно движется - мне показалось, что 30 лет. А всего-то 25 В конце 90-х я активно переводил свои дивайсы с ST62ХХ на АВР-ки. А управление портами не менялось в них с их рождения. Потом были нюансы. Например, запись бита в PINA (вроде бы бессмысленное по логике занятие) приводило к инверсии соотв. бита в PORTA (режим Т-триггера). Но основа не менялась.
digitalis вне форума Ответить с цитированием
Старый 06.07.2021, 14:02   #10
AlexInch
Новичок
Джуниор
 
Регистрация: 04.07.2021
Сообщений: 4
По умолчанию

Цитата:
Сообщение от digitalis Посмотреть сообщение
Так время медленно движется - мне показалось, что 30 лет. А всего-то 25 В конце 90-х я активно переводил свои дивайсы с ST62ХХ на АВР-ки
да ? Стало быть, молодеешь с каждым годом.
А мне всегда казалось, что с возрастом время летит всё быстрее и быстрее.
Это в школе время тянулась, как резинка. А сейчас посмотрел в окно два раза - 1-й раз осень,
2-й - уже весна.
А я переводил на AVR проекты с MCS51. А бывало, и наоборот. Так у 51-х вообще просто - у них
опен коллектор/опен сток в портах. Допускает "монтажное или" со всем, чем надо. Всё получается само собой.
AlexInch вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Неправильно работает функция rand() на микроконтроллере ATMEGA328P Marcus75 Микроконтроллеры, робототехника, схемотехника, 3D принтеры 8 14.11.2019 13:34
Cчитывание измеренной температуры с датчика DS18B20 в Excel, используя библиотеку RSAPI.DL aizhan0212 Микроконтроллеры, робототехника, схемотехника, 3D принтеры 57 17.09.2017 22:25
Помощь с программой тестом на Delphi. Не знаю как сделать чтобы был выбор ответа и определение верного/не верного ответа и итог? KiberVioNet Lazarus, Free Pascal, CodeTyphon 7 30.09.2015 09:02
жду ответа вовик 82 Помощь студентам 1 27.05.2011 11:15