Работа с I2C в библиотеке Wire

mal333
Offline
Зарегистрирован: 23.04.2014

Всех приветствую!

Потратил несколько часов на поиск и чтение по теме, но так и не могу прояснить для себя, как же работать по шине I2C? Может мне кто-нибудь подскажет некоторые моменты?  Буду конкретен:

1. Устройство имеет адрес 0х21. Соответственно для записи адрес 0х42 для записи и 0х43 для чтения. Какие же адреса указывать в Wire.RequestFrom и Wire.Begintransmission?

2. Устройство имеет адрес 0х21, но кроме того имеет внутренний регистр с адресом 0х01, в который я хочу записать байт 0х5а. Как будет выглядеть код?

3. Устройство имеет адрес 0х21, но кроме того имеет внутренний регистр с адресом 0х01, из которого я хочу прочитать байт. Как будет выглядеть код?

4. Таки надо подтягивающие резисторы на шину ставить,или они уже есть в МК?

Спасибо за помощь в виде ссылки или просто куска кода.

Puhlyaviy
Puhlyaviy аватар
Offline
Зарегистрирован: 22.05.2013

В мк не те резисторы что для i2c. И в зависимости от ардуино они либо уже есть на плате либо нет.

mal333
Offline
Зарегистрирован: 23.04.2014

Хорошо, т.е. использовать внутренние резисторы МК, если только он на шине мастер все же возможно? Или полюбому ставить внешние? Если важна конкретика- то платформа Due.

Puhlyaviy
Puhlyaviy аватар
Offline
Зарегистрирован: 22.05.2013

У due 2 шины для i2c. На одной уже стоят резисторы, а на другую их НУЖНО установить.

vdk
Offline
Зарегистрирован: 14.04.2013

Обычно ставят внешние, и часто - на плате с датчиком

А по I2C - возьмите библиотеку для какого-нибудь датчика, да посмотрите, как с ним работают

mal333
Offline
Зарегистрирован: 23.04.2014

vdk пишет:

А по I2C - возьмите библиотеку для какого-нибудь датчика, да посмотрите, как с ним работают

Так вот и не могу найти. Народ подключает датчики температуры и LCD, пишутся библиотеки целые и собственные реализации I2C, но туда лезть- темный лес совсем. Мне просто не понятен(исходя из референса к библиотеке) алгоритм обмена данными с устройством в случае наличия у него своих внутренних регистров.

mal333
Offline
Зарегистрирован: 23.04.2014

Puhlyaviy пишет:
У due 2 шины для i2c. На одной уже стоят резисторы, а на другую их НУЖНО установить.

Насколько я понимаю по даташиту "Both TWD and TWCK are bidirectional lines, connected to a positive supply voltage via a current source or pull-up resistor (see Figure 34-2 on page 715). When the bus is free, both lines are high. The output stages of devices connected to the bus must have an open-drain or open-collector to perform the wired-AND function.TWD and TWCK pins may be multiplexed with PIO lines. To enable the TWI, the programmermust perform the following step:

• Program the PIO controller to dedicate TWD and TWCK as peripheral lines.
The user must not program TWD and TWCK as open-drain. It is already done by the hardware." - резисторы таки есть. Или?
Puhlyaviy
Puhlyaviy аватар
Offline
Зарегистрирован: 22.05.2013

На одной шине они есть снаружи припаяны на ардуиновскрй плате , а на второй их нет и нужно их туда подпаять.

mal333
Offline
Зарегистрирован: 23.04.2014

Puhlyaviy пишет:
На одной шине они есть снаружи припаяны на ардуиновскрй плате , а на второй их нет и нужно их туда подпаять.

Да, увидел на схеме, что линии SDA SCL подтянуты на 3,3В, спасибо. Т.е. на них можно подключать напрямую. Все, п.4 закрыт :)

mal333
Offline
Зарегистрирован: 23.04.2014

Чтобы не напрягать особенно народ, приведу кусок кода обмена по интерфейсу:

#include <Wire.h>
String inputString = "20";         //  a string to hold incoming data
boolean stringComplete = false;  //  whether the string is complete
int pos = 0; 

void setup()
{
  Wire.begin();        // join i2c bus (address optional for master)
  Serial.begin(9600);  // start serial for output
 inputString.reserve(3); 
}

void loop()
{
   if (stringComplete) {
      pos = inputString.toInt();
  Wire.beginTransmission(0x21);
  Wire.write(pos);
  delay(100);
  Wire.requestFrom(0x21, 1);    // request 6 bytes from slave device #

  while(Wire.available())    // slave may send less than requested
  { 
    char c = Wire.read(); // receive a byte as character
    Serial.println(c, HEX);         // print the character
  }
  Wire.endTransmission();
  inputString = ""; 
    stringComplete = false; 
   }
  delay(500);
}

// For DEBUGGING
void serialEvent() {
  while (Serial.available()) {
    // get the new byte:
    char inChar = (char)Serial.read();
    // add it to the inputString:
    inputString += inChar;
    // if the incoming character is a newline, set a flag
    // so the main loop can do something about it:
    if (inChar == '\n') {
      stringComplete = true;
    }
  }
}

Проблема в том, что значение из нужного регистра отображаются только со второго раза( нужно ввести дважды номер регистра, чтобы получить его значение. Вопрос простой: что не так?

vdk
Offline
Зарегистрирован: 14.04.2013

mal333 пишет:

 Мне просто не понятен(исходя из референса к библиотеке) алгоритм обмена данными с устройством в случае наличия у него своих внутренних регистров.

Ну вот, например, запись в регистр ds3231:

void RTC_DS3231::setreg(const uint8_t addr, const uint8_t val) {
    Wire.beginTransmission(DS3231_ADDRESS);
    Wire.write(addr); // адрес регистра
    Wire.write(val); // значение
    Wire.endTransmission();}

 

mal333
Offline
Зарегистрирован: 23.04.2014

Спасибо, с записью стало понятно.

Так же разобрался с чтением: 

 Wire.beginTransmission(0x21); //начинаем работу с шиной
  Wire.write(pos);    // сообщаем ведомому, какой регистр будем читать
  Wire.endTransmission();   //это обязательно!

  Wire.beginTransmission(0x21); // начинаем заново работу с шиной
  Wire.requestFrom(0x21, 1);    //  требуем 1 байт от устройства из регистра с номером pos

     char c = Wire.read(); // receive a byte as character
    Serial.println(c, HEX);         // print the character
 // }
  Wire.endTransmission(); // оканчиваем работу с шиной

Всем спасибо, все работает!