DS1621 в Proteus (Atmega88) Решено

Обсуждаем контроллеры компании Atmel.
Ответить
Land
Прорезались зубы
Сообщения: 217
Зарегистрирован: Ср янв 11, 2012 11:55:51

DS1621 в Proteus (Atmega88) Решено

Сообщение Land »

Доброго всем котам.
Суть проблемы. DS1621 не отзывается на команды по i2c. Есть схема, где на шине i2c висит два устройства (адреса разные). DS3231 и DS1621. С часами вопросов нет, время пишется/читается корректно. Т.е. i2c реализован корректно. С DS1621 совершенные непонятки. В Протеусе сканер i2c показывает, что на любую команду (типа посылки адреса и т.п.) устройство отвечает NACK.
Изображение
в Протеусе вроде как все правильно подключено:
Изображение
код работы с DS1621 выглядит следующим образом:

Код: Выделить всё

// Адрес устройства

#define DS1621_ADR	0x48

// Адреса регистров

#define DS1621_READ_TEMPR		0xAA	// Адрес регистра чтения температуры
#define DS1621_READ_COUNTER		0xA8	// Адрес регистра reads the value Count_Remain
#define DS1621_RAED_SLOPE		0xA9	// Адрес регистра reads the value Count_Per_C
#define DS1621_START_CONVERT	0xEE	// Адрес регистра begins a temperature conversion
#define DS1621_STOP_CONVERT		0x22	// Адрес регистра stops temperature conversion
#define DS1621_ACCES_TH			0xA1	// Адрес регистра high temperature limit value into TH register
#define DS1621_ACCES_TL			0xA2	// Адрес регистра low temperature limit value into TH register
#define DS1621_ACCES_CONFIG		0xAC	// Адрес регистра configuration data to configuration register

// Funcion to init DS1621
//****************************************************************** 
void ds1621_init(void)
{
	//BYTE temp = 0;
	i2c_init();	
	i2c_start();
	i2c_send_byte(DS1621_ADR);
	i2c_send_byte(DS1621_ACCES_CONFIG);
	i2c_send_byte(0x01); //в LSB конфигурационного байта пишем 1 — преобр. по запросу.
	i2c_restart();
	i2c_send_byte(DS1621_ADR);
	i2c_send_byte(DS1621_START_CONVERT);	
	i2c_stop();
}
// get temperature ----------------------------------------------
char getTemperatura(void)
{
  //uint8_t actualtemperatura;
  i2c_start();
  i2c_send_byte(DS1621_ADR); 
  i2c_send_byte(DS1621_READ_TEMPR);
  temperatura = i2c_read_byte(NACK);
  i2c_restart();
  i2c_send_byte(DS1621_ADR);
  i2c_send_byte(DS1621_START_CONVERT);
  i2c_stop();
}
Собственно второй день в затыке и даже не представляю, куда копать :shock: Может есть у кого идеи?
Последний раз редактировалось Land Вс сен 18, 2022 20:57:07, всего редактировалось 1 раз.
Реклама
veso74
Поставщик валерьянки для Кота
Сообщения: 1916
Зарегистрирован: Сб май 05, 2012 20:24:52
Откуда: KN34PC, Болгария
Контактная информация:

Re: DS1621 в Proteus (Atmega88)

Сообщение veso74 »

0xAA возвращает два байта: t_msb и t_lsb.
i2c_restart(); не использовал, из любопытства: можете показать.
Бы предпочел стандартный повторный i2c_start(); // repeat start condition
Реклама
Land
Прорезались зубы
Сообщения: 217
Зарегистрирован: Ср янв 11, 2012 11:55:51

Re: DS1621 в Proteus (Atmega88)

Сообщение Land »

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

Код: Выделить всё

void i2c_restart(void)
{
	ONE_SDA();
	I2C_DELAY();
	ONE_SCL();
	I2C_DELAY();
	
	NULL_SDA();
	I2C_DELAY();
	NULL_SCL();
	I2C_DELAY();
}
А какой вообще адрес дожен быть у Ds1621? В даташите написано следующее:
A control byte is the first byte received following the START condition from the master device. The
control byte consists of a 4-bit control code; for the DS1621, this is set as 1001 binary for read and write
operations. The next 3 bits of the control byte are the device select bits (A2, A1, A0).
у меня получается: 1001 и 000 = 0x48 (1001000) Но нашел реализации, где адрес равен 0x90 (10010000) и на этот адрес DS1621 откликается (правда температуру считать не получается)
В чем подвох?
veso74
Поставщик валерьянки для Кота
Сообщения: 1916
Зарегистрирован: Сб май 05, 2012 20:24:52
Откуда: KN34PC, Болгария
Контактная информация:

Re: DS1621 в Proteus (Atmega88)

Сообщение veso74 »

В зависимости от компилятора: I2C на 7 / 8 бит с/без [R/W]

Код: Выделить всё

ADDR_I2C = 0b1001[A2][A1][A0][R/W] 
Уточните 7 / 8 бит / или дайте инфо для исп. компилятора.
Простой путь: подключите аппаратную часть к чипa и запустите сканер I2C.
---
Поскольку Вы задали этот вопрос, теперь я вижу, что не меняете адрес, для R: 1 в конце, напр.(8 bit):

Код: Выделить всё

write:
i2c_write(i2c_addr << 1);
read:
i2c_write(i2c_addr << 1 | 0x01);
Примечание: некоторые компиляторы делают это сами.
Реклама
Эиком - электронные компоненты и радиодетали
Land
Прорезались зубы
Сообщения: 217
Зарегистрирован: Ср янв 11, 2012 11:55:51

Re: DS1621 в Proteus (Atmega88)

Сообщение Land »

veso74, да, спасибо, с адресом разобрался. Для записи получается 0x90, для чтения 0х91. Спасибо, про компилятор не подумал бы даже.
отклик на адрес есть. Осталось разобраться, как получить температуру )
Может кому-то пригодится:

Код: Выделить всё

// Адрес устройства

#define DS1621_ADR_R	0x91
#define DS1621_ADR_W	0x90

// Адреса регистров

#define DS1621_READ_TEMPR		0xAA	// Адрес регистра reads temperature
#define DS1621_READ_COUNTER		0xA8	// Адрес регистра reads the value Count_Remain
#define DS1621_RAED_SLOPE		0xA9	// Адрес регистра reads the value Count_Per_C
#define DS1621_START_CONVERT	0xEE	// Адрес регистра begins a temperature conversion
#define DS1621_STOP_CONVERT		0x22	// Адрес регистра stops temperature conversion
#define DS1621_ACCES_TH			0xA1	// Адрес регистра high temperature limit value into TH register
#define DS1621_ACCES_TL			0xA2	// Адрес регистра low temperature limit value into TH register
#define DS1621_ACCES_CONFIG		0xAC	// Адрес регистра configuration data to configuration register

// Funcion to init DS1621
//****************************************************************** 

void ds1621_init(void)
{
	//BYTE temp = 0;
	i2c_init();	
	i2c_start();
	i2c_send_byte(DS1621_ADR_W);
	i2c_send_byte(DS1621_ACCES_CONFIG);
	i2c_send_byte(0x01); //in LSB One Shot Mode.
	i2c_restart();
	i2c_send_byte(DS1621_ADR_W);
	i2c_send_byte(DS1621_START_CONVERT);	
	i2c_stop();	
}

// get temperature ----------------------------------------------

uint8_t getTemperatura(void)
{
  i2c_start();
  i2c_send_byte(DS1621_ADR_W); 
  i2c_send_byte(DS1621_READ_TEMPR);
  i2c_restart();
  i2c_send_byte(DS1621_ADR_R);
  temperatura = i2c_read_byte(NACK);
  i2c_restart();
  i2c_send_byte(DS1621_ADR_W);
  i2c_send_byte(DS1621_START_CONVERT);
  i2c_stop();
Реклама
Ответить

Вернуться в «AVR»