Соединение ATTiny85 I2C с Arduino Nano

Я пытаюсь отправлять и получать данные с помощью I2C между Arduino Nano и ATTiny85. ATTiny установлен на этой плате: Ссылка

Я пытался связаться с подчиненным устройством с помощью простого сканера I2C, но ничего не нашел.

Это коды:

Мастер (сканер I2C):

// --------------------------------------
// i2c_scanner
//
// Версия 1
// Эта программа (или код, похожий на нее)
// можно найти во многих местах.
// Например, на форуме Arduino.cc.
// Оригинальный автор неизвестен.
// Версия 2, июнь 2012 г., с использованием Arduino 1.0.1
// Максимально упрощено пользователем Arduino.cc Krodal
// Версия 3, 26 февраля 2013 г.
// V3 от Луарнольда
// Версия 4, 3 марта 2013 г., с использованием Arduino 1.0.3
// пользователем Arduino.cc Кродалом.
// Изменения Луарнольда удалены.
// Адреса сканирования изменены с 0...127 на 1...119,
// по данным сканера i2c Ника Гаммона
// http://www.gammon.com.au/forum/?id=10896
// Версия 5, 28 марта 2013 г.
// Как и версия 4, но адрес теперь сканируется до 127.
// Кажется, датчик использует адрес 120.
// Версия 6, 27 ноября 2015 г.
// Добавлено ожидание последовательной связи Леонардо.
//
//
// Этот скетч тестирует стандартные 7-битные адреса
// Устройства с более высоким битовым адресом могут отображаться неправильно.
//

#include <Wire.h>


void setup()
{
  Wire.begin();

  Serial.begin(9600);
  while (!Serial);             // Леонардо: дождаться последовательного монитора
  Serial.println("\nI2C Scanner");
}


void loop()
{
  byte error, address;
  int nDevices;

  Serial.println("Scanning...");

  nDevices = 0;
  for(address = 1; address < 127; address++ )
  {
    // i2c_scanner использует возвращаемое значение
    // Write.endTransmission, чтобы проверить,
    // устройство подтвердило адрес.
    Wire.beginTransmission(address);
    error = Wire.endTransmission();

    if (error == 0)
    {
      Serial.print("I2C device found at address 0x");
      if (address<16)
        Serial.print("0");
      Serial.print(address,HEX);
      Serial.println("  !");

      nDevices++;
    }
    else if (error==4)
    {
      Serial.print("Unknown error at address 0x");
      if (address<16)
        Serial.print("0");
      Serial.println(address,HEX);
    }    
  }
  if (nDevices == 0)
    Serial.println("No I2C devices found\n");
  else
    Serial.println("done\n");

  delay(500);           // ждем 5 секунд для следующего сканирования
}

А это код ATTiny85 (подчиненного устройства):

#include <TinyWire.h>

#define led_pin 1

byte own_address = 10;


void setup() {
  // настраиваемled_pin как выход для управления светодиодом
  pinMode(led_pin, OUTPUT);

  // настраиваем библиотеку TinyWire для функциональности подчиненного устройства I2C
  TinyWire.begin( own_address );
  // устанавливаем обратный вызов для события приема ведомого устройства
  TinyWire.onReceive( onI2CReceive );
}

void loop() {

}

/*
I2C Slave Receive Callback:
Note that this function is called from an interrupt routine and shouldn't take long to execute
*/
void onI2CReceive(int howMany){
  // цикл, пока все полученные байты не будут прочитаны
  while(TinyWire.available()>0){
    // переключает светодиод каждый раз, когда получено 'a'
    if(TinyWire.read()=='a') digitalWrite(led_pin, !digitalRead(led_pin));
  }
}

После того как я запрограммировал обе платы, я соединил контакты SCL и SCK на платах вместе.

Если я открою последовательный монитор ведущего устройства, вот что я получу:

Сканирование сканером I2C... Неизвестная ошибка по адресу 0x20 Неизвестная ошибка по адресу адрес 0x21 Устройства I2C не найдены

Сканирование... Неизвестная ошибка по адресу 0x78 Устройства I2C не найдены

Сканирование... Устройства I2C не найдены

Сканирование... Неизвестная ошибка по адресу 0x08 Неизвестная ошибка по адресу 0x09 Неизвестная ошибка по адресу 0x60 Устройства I2C не найдены

Сканирование... Неизвестная ошибка по адресу 0x70 Устройства I2C не найдены

И так далее. Может кто-нибудь объяснить мне, где я делаю ошибки?

, 👍0

Обсуждение

вы заземлили вместе?, @Juraj

@Юрай, ты прав, я забыл подключить их к одному и тому же заземлению. Но сейчас я только читаю «Устройства I2C не найдены», @Banfotech _


1 ответ


Лучший ответ:

1

Проблема решена!

Я изменил код, это окончательный вариант:

#include <TinyWire.h>

#define led_pin 1
#define I2C_SLAVE_ADDR  0x11  


void setup() {
    // настраиваемled_pin как выход для управления светодиодом
    pinMode(led_pin, OUTPUT);

    // настраиваем библиотеку TinyWire для функциональности подчиненного устройства I2C
    TinyWire.begin( I2C_SLAVE_ADDR );
    // устанавливаем обратный вызов для события приема ведомого устройства
    TinyWire.onReceive( onI2CReceive );
}

void loop() {

}

/*
Обратный вызов приема подчиненного устройства I2C:
Обратите внимание, что эта функция вызывается из процедуры обработки прерывания, и ее выполнение не должно занимать много времени.
*/
void onI2CReceive(int howMany){
    // цикл, пока все полученные байты не будут прочитаны
    while(TinyWire.available()>0){
        // переключает светодиод каждый раз, когда получено 'a'
        if(TinyWire.read()=='a') digitalWrite(led_pin, !digitalRead(led_pin));
    }
}

Таким образом сканер I2C видит плату по адресу 0x11.

Подключения следующие:

  • Вывод SCL Arduino на вывод SCL ATTiny85 (P2)
  • Вывод Arduino SDA на вывод ATTiny85SDA (P0)
  • Позаботьтесь о том, чтобы провода были заземлены на обеих платах одинаково.
,

Адрес I2C имеет длину 7 бит, за которым следует бит направления. Таким образом, 10 или 11 — это один и тот же адрес, но бит направления разный. 0x10 — зарезервированный адрес. https://www.i2c-bus.org/addressing/, @Juraj

@Juraj Вы правы в том, что адрес имеет длину 7 бит. Но адрес библиотеки TinyWire (а также библиотеки Wire) не включает бит направления. Он добавляется к байту адреса библиотекой в зависимости от используемых функций. Итак, 10 и 11 здесь не один и тот же адрес., @chrisl

@chrisl, да. десятичное число 10 сильно отличается от 0x11, @Juraj

Кроме того, 0x11 и 0x10 не являются одним и тем же адресом, поскольку сюда не входит бит направления., @chrisl

@chrisl, как бы вы установили бит направления для 0x10 и 0x11, чтобы они были разными адресами?, @Juraj

Вы не устанавливаете здесь бит направления. ОП использует библиотеки Wire. Адрес, который вы используете с любой из их функций, не включает бит направления. Библиотеки используют младшие 7 бит предоставленного адреса и создают байт адреса I2C, сдвигая предоставленный адрес на один бит влево и устанавливая младшему биту (который теперь равен нулю) правильное значение в зависимости от запрошенной операции. Значение адреса, используемое в скетче, не идентично байту адреса I2C. Адреса будут преобразованы в байт адреса I2C, например 0x20/0x21 и 0x22/0x23., @chrisl