Обсуждаем контроллеры компании Atmel.
Ответить

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

Вс сен 18, 2022 10:42:14

Доброго всем котам.
Суть проблемы. 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 раз.

Re: DS1621 в Proteus (Atmega88)

Вс сен 18, 2022 11:59:22

0xAA возвращает два байта: t_msb и t_lsb.
i2c_restart(); не использовал, из любопытства: можете показать.
Бы предпочел стандартный повторный i2c_start(); // repeat start condition

Re: DS1621 в Proteus (Atmega88)

Вс сен 18, 2022 12:31:53

да, я знаю, что возвращает два байта. Но ведь мне никто не может запретить принять только старший байт.
Вы про это:
Код:
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 откликается (правда температуру считать не получается)
В чем подвох?

Re: DS1621 в Proteus (Atmega88)

Вс сен 18, 2022 12:39:43

В зависимости от компилятора: 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);

Примечание: некоторые компиляторы делают это сами.

Re: DS1621 в Proteus (Atmega88)

Вс сен 18, 2022 13:13:02

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();
Ответить