wprowadzenie
komunikacja I2C stała się de facto metodą komunikacji między mikrokontrolerami, mikrokomputerami i różnymi układami scalonymi i czujnikami. Istnieje od 1982 roku i został pierwotnie opracowany do stosowania w odbiornikach telewizyjnych.
chociaż w poprzednich artykułach wykorzystaliśmy wiele czujników i wyświetlaczy I2C, nie przyjrzeliśmy się właściwie temu, jak działa I2C i jak można go używać do komunikacji między mikrokontrolerami.
dzisiaj poprawimy to i dowiemy się więcej o I2C. zobaczymy również, jak może być używany do wymiany informacji między dwoma Arduino i jak może być użyty do umożliwienia jednemu Arduino kontrolowania drugiego.
To będzie pierwszy z czterech artykułów na temat I2C. w przyszłych artykułach zobaczymy, jak możemy zbudować własne urządzenia I2C, jak połączyć Raspberry Pi i Arduino za pomocą I2C i jak zrobić kilka zaawansowanych konfiguracji I2C, w tym przy użyciu wielu masterów na jednej magistrali I2C.
zaczynajmy!
Komunikacja I2C
I2C jest protokołem szeregowym używanym w interfejsie 2-przewodowym o niskiej prędkości. Został pierwotnie opracowany przez Phillips w 1982 roku, aby umożliwić układom scalonym w odbiornikach telewizyjnych komunikację ze sobą.
czasy się zmieniły, Phillips jest teraz NXP i I2C stał się standardem komunikacji, który jest obsługiwany przez praktycznie każdego głównego producenta półprzewodników.
I2C to skrót od „Inter-Integrated Circuit”. Jest również nazywany ” IIC ” lub „I kwadrat C”.
zastosowania i ograniczenia
I2C jest używany z mikrokontrolerami takimi jak Arduino i z mikrokomputerami takimi jak Raspberry Pi. Wiele wyświetlaczy i czujników łączy się z kontrolerem hosta za pomocą I2C.
I2C ma jednak kilka ograniczeń. Nie jest szczególnie szybki, chociaż dla większości jego zamierzonych zastosowań jest wystarczająco szybki.
I2C może być używany tylko na krótkich dystansach, w końcu pierwotnie miał komunikować się między układami scalonymi na tej samej płytce drukowanej. Maksymalna odległość niezawodnej transmisji zmniejsza się wraz ze wzrostem prędkości, przy najwolniejszej prędkości (100 Kbaud lub częstotliwość zegara 100 KHz) maksymalna odległość wynosi około metra.
prędkości I2C
oryginalna magistrala I2C miała prędkość maksymalną 100 KHz. Większość popularnych aplikacji nadal korzysta z tej prędkości, ponieważ jest ona wystarczająca do przesyłania danych z czujników i do prostych wyświetlaczy.
I2C i ma kilka trybów wyższej prędkości. Nie wszystkie urządzenia I2C obsługują te tryby:
- Tryb Szybki – ma maksymalną prędkość zegara 400 KHz.
- tryb Hi-Speed – maksymalna częstotliwość taktowania fo 3,4 MHz
- tryb Ultra Fast – Maksymalna częstotliwość taktowania 5 MHz
na magistrali I2C to master określa prędkość taktowania.
Jak działa I2C
magistrala I2C ma dwa sygnały, wraz z podłączeniem zasilania i uziemienia.
dwie linie sygnałowe są następujące:
- SDA – jest to dwukierunkowa linia danych.
- SCL – jest to sygnał zegara.
do każdej linii sygnałowej dołączone są dwa rezystory podciągające, podciągają one magistralę do napięcia zasilającego, gdy jest nieaktywna.
zauważ, że napięcie zasilania nie jest standardowe, może to być 3,3 lub 5 woltów. Może to być również niższe napięcie dla niektórych szybkich implementacji I2C.
ta różnica napięć zasilania może powodować problemy podczas łączenia urządzeń I2C, które używają różnych poziomów logiki. Omówimy to bardziej w przyszłym artykule, kiedy pokażę Ci, jak interfejs Raspberry Pi (3.3-volt logic) z Arduino Uno (5-volt logic).
istnieją dwa typy urządzeń, które mogą być podłączone do magistrali I2C – Master i Slave.
urządzenie główne steruje magistralą i dostarcza sygnał zegara. Żąda danych od niewolników indywidualnie. W magistrali może być więcej niż jedno urządzenie główne, ale tylko jedno może być aktywne w danym momencie.
urządzenia master nie mają przypisanego do nich adresu.
urządzenia Slave mają adres, A Ten adres musi być unikalny w magistrali. Używają 7-bitowego schematu adresowania, więc na jednej szynie I2C może znajdować się do 128 niewolników. W rzeczywistości ta duża kolekcja urządzeń nigdy nie jest używana, rzadko zdarza się zobaczyć kilkanaście urządzeń I2C na jednej magistrali.
zaimplementowano nowszy, 10-bitowy schemat adresowania, jest on wstecznie kompatybilny z istniejącą metodą adresowania 7-bitowego.
komercyjne urządzenia I2C są przydzielane adresowi I2C przez NXP, który utrzymuje specyfikację magistrali. Chociaż I2C jest open source od 2006 roku, pobierana jest opłata za uzyskanie adresu slave od NXP. Nie jest wymagana opłata za Urządzenia główne ani za urządzenia, które nie są przeznaczone do produkcji komercyjnej.
niektóre urządzenia I2C mają przypisane wiele adresów, Zwykle różnice w dolnych bitach adresu. Urządzenia te można ręcznie skonfigurować dla różnych adresów, umożliwiając korzystanie z wielu urządzeń tego samego typu na jednej magistrali I2C.
inne pochodne I2C
istnieją inne autobusy, które zostały wyprowadzone z magistrali I2C i które są pod wieloma względami kompatybilne z I2C.
- TWI – interfejs Twin Wire jest praktycznie identyczny z magistralą I2C. W rzeczywistości jest to autobus, którego używa Arduino, TWI został opracowany, gdy szyna I2C nie była open source i Atmel nie chciał ryzykować naruszenia nazwy handlowej. Jedyną istotną różnicą między TWI i I2C jest to, że TWI nie obsługuje zaawansowanej techniki zwanej „rozciąganiem zegara”.
- SMBus jest kolejną równoważną magistralą I2C, opracowaną przez Intela. Podobnie jak TWI obsługuje większość funkcji I2C.
w przyszłym artykule wyjaśnię, jak są skonstruowane dane na magistrali I2C. Ale teraz mamy kilka podstawowych informacji o I2C, na tyle, by zacząć eksperymentować.
Arduino Wire Library
Arduino ma wbudowaną bibliotekę do pracy z I2C o nazwie Wire Library. To sprawia, że bardzo łatwo komunikować się na magistrali I2C, i może skonfigurować Arduino stać się albo master lub slave.
Biblioteka Wire ma kilka przydatnych funkcji do pracy z I2C.
- begin() – inicjuje bibliotekę i ustawia Arduino jako master lub slave.
- requestFrom() – funkcja ta jest używana przez master do żądania danych z pliku slave.
- beginTransmission() – ta funkcja jest używana przez master do wysyłania danych do określonego pliku slave.
- endTransmission() – ta funkcja jest używana przez master do zakończenia transmisji rozpoczętej funkcją beginTransmission.
- write() – używana zarówno przez master, jak i slave do wysyłania danych na magistralę I2C.
- available() – używana zarówno przez master, jak i slave do określenia liczby bajtów w danych, które otrzymują.
- read() – odczytuje bajt danych z magistrali I2C.
- SetClock() – używana przez master do ustawiania określonej częstotliwości zegara.
- onReceive() – używana przez plik slave do określenia funkcji, która zostanie wywołana podczas odbierania danych od master.
- onrequest() – używana przez plik slave do określenia funkcji, która jest wywoływana, gdy master zażąda danych.
niektóre z tych funkcji wykorzystamy w naszych szkicach.
połączenia Arduino I2C
połączenia SDA i SCL dla I2C różnią się między modelami Arduino. Eksperymenty, które mam zamiar pokazać, zostały wykonane przy użyciu dwóch Arduino Unos, ale możesz użyć innych modeli Arduino, pod warunkiem, że odpowiednio zmienisz Szpilki.
ułożyłem wykres, aby pomóc ci go rozgryźć. Zawiera kilka wspólnych płyt Arduino, a także kilka dyskretnych układów scalonych. Pinouty do układów I listy (ATTiny i ATmega328P) są z pakietem DIP, a nie montowane powierzchniowo.
Arduino Board or Chip | SDA | SCL |
Uno | A4 | A5 |
Mega2560 | 20 | 21 |
Nano | A4 | A5 |
Pro Mini | A4 | A5 |
Leonardo | 2 | 3 |
Due (has two I2C) | 20 + SDA1 | 20 + SCL1 |
ATTiny85 & ATTiny45 | 5 | 7 |
ATmega328P | 27 | 28 |
niektóre klony Arduino Uno mają oddzielne piny SDA i SCL i możesz ich użyć zamiast dwóch pinów analogowych, jeśli chcesz. Są wewnętrznie połączone z tym samym miejscem.
zauważ, że Arduino Due faktycznie ma dwa porty I2C.
należy również pamiętać, że w Internecie są nieprawidłowe Schematy podłączenia dla Pro Mini. Użyj dwóch pinów analogowych, A4 i A5, jak pokazano w powyższej tabeli.
I2C między 2 Arduino
dla naszego pierwszego eksperymentu będziemy hoo dwa Arduino razem i wymiany danych między nimi. Jeden Arduino będzie mistrzem, drugi niewolnikiem.
używam dwóch Arduino Unos, ale możesz zastąpić inne Arduino, jeśli nie masz dwóch Unos. Użyj poprzedniego wykresu dla połączeń.
podpinanie 2 Arduino ’ s
oto jak połączyłem moje dwa Arduino Unos razem:
jest to dość proste podłączenie, zasadniczo wystarczy związać ziemię i dwa piny I2C razem.
należy pamiętać, że mój diagram nie pokazuje użycia oporników pull-up, odkryłem, że wszystko wydawało się działać poprawnie bez nich. Możesz jednak je uwzględnić, zwłaszcza jeśli wystąpią błędy lub przerywana operacja.
aby podłączyć niektóre Rezystory podciągania, podłącz kilka rezystorów 10K do linii SDA i SCL. Podłącz drugi koniec do wyjścia 5-woltowego na jednym z Arduino.
Master Demo Sketch
oto szkic, który zostanie użyty na Arduino, które oznaczyłeś jako master.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
|
/*
demonstracja wersji wzorcowej I2C
I2C-demonstracja wzorcowa.ino
Demonstrate use of I2C bus
Master sends character and gets reply from Slave
DroneBot Workshop 2019
https://dronebotworkshop.com
*/
// Include Arduino Wire library for I2C
#include <Wire.h>
// Define Slave I2C Address
#define SLAVE_ADDR 9
// Define Slave answer size
#define ANSWERSIZE 5
void setup() {
// Initialize I2C communications as Master
Wire.begin();
/ /Setup serial monitor
Serial.begin (9600);
Serial.println („I2C Master Demonstration”);
}
void loop () {
opóźnienie(50);
Serial.println („Write data to slave”);
// Write a charatre to the Slave
.beginTransmission (SLAVE_ADDR);
.write (0);
.endTransmission ();
Serial.println („Receive data”);
// odczytaj odpowiedź z pliku Slave
// odczytaj 5 znaków
drutu.requestFrom(SLAVE_ADDR, ANSWERSIZE);
/ /Dodaj znaki do łańcucha
String response=””;
while (Wire.available ()) {
char b = Wire.read();
response += B;
}
// Drukuj do monitora szeregowego
Serial.println (response);
}
|
jak w przypadku wszystkich szkiców I2C, zaczynamy od włączenia biblioteki Wire.
następnie definiujemy kilka stałych, które reprezentują adres I2C pliku slave oraz liczbę bajtów danych, które spodziewamy się z niego pobrać.
w konfiguracji inicjujemy komunikację I2C jako master. Wiemy, że jest to master, ponieważ nie ma parametru adresu w funkcji begin. Ustawiamy również Monitor szeregowy i drukujemy na nim wiersz tekstu.
teraz do pętli.
zaczynamy z małym opóźnieniem czasowym, głównie po to, aby spowolnić wszystko na tyle, abyśmy mogli odczytać wyświetlacz na monitorze szeregowym.
następnie używamy funkcji beginTransmission do wysyłania danych do pliku slave. W tym przypadku dane, które wysyłamy, są tylko liczbą zero. Kończymy wysyłanie z wywołaniem do funkcji endTransmission.
następnie żądamy pewnych danych z powrotem z pliku slave za pomocą funkcji requestFrom.
następnie formułujemy łańcuch odpowiedzi, odczytując dane, bajt na raz, z pliku slave.
szczegóły tego, co robimy i dane, które otrzymujemy, drukujemy na monitorze szeregowym. A potem kończymy pętlę i robimy to od nowa.
szkic Demo Slave
teraz na szkic używany przez slave.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
|
/*
I2C Slave Demo
i2c-slave-demo.ino
Demonstrate use of I2C bus
Slave receives character from Master and responds
DroneBot Workshop 2019
https://dronebotworkshop.com
*/
// Include Arduino Wire library for I2C
#include <Wire.h>
// Define Slave I2C Address
#define SLAVE_ADDR 9
// Define Slave answer size
#define ANSWERSIZE 5
// Define string with response to Master
String answer = „Hello”;
Void Setup() {
// inicjalizuj komunikację I2C jako slave
.begin (SLAVE_ADDR);
// funkcja uruchamiana, gdy dane są wymagane z przewodnika master
.onRequest (requestEvent);
/ /funkcja uruchamiana, gdy Dane odebrane z przewodu głównego
.onReceive (receiveEvent);
/ /Setup Serial Monitor
Serial.begin (9600);
Serial.println („I2C Slave Demonstration”);
}
void receiveEvent () {
// Read while data received
while (0 < drut.available ()) {
bajt x = Drut.read ();
}
/ / Drukuj do monitora szeregowego
Serial.println („Receive event”);
}
void requestEvent () {
/ / Ustaw zmienną bajtową w odpowiednim rozmiarze
odpowiedź bajtowa;
/ /sformatuj odpowiedź jako tablicę
dla (bajt i=0;i
odpowiedź = (bajt) odpowiedź.charAt (i);
}
// Wyślij Odpowiedź z powrotem do Kreatora
Wire.write (odpowiedź,rozmiar (odpowiedź));
//Drukuj na monitorze szeregowym
Serial.println(„Zdarzenie żądania”);
}
pętla unieważnienia() {
// opóźnienie w pętli
opóźnienie(50);
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
|
/*
demonstracja głównego sterowania I2C
I2C jest głównym sterowaniem demonstracyjnym.ino
Demonstrate use of I2C bus
Master sends potentimeter position data
DroneBot Workshop 2019
https://dronebotworkshop.com
*/
// Include Arduino Wire library for I2C
#include <Wire.h>
// Define Slave I2C Address
#define SLAVE_ADDR 9
// Analog pin for potentiometer
int analogPin = 0;
// Integer to hold potentiometer value
int val = 0;
void setup () {
/ /Inicjalizuj komunikację I2C jako Master
Przewód.
}
void loop () {
opóźnienie (50);
/ / odczyt wartości puli
/ / mapowanie do zakresu 1-255 dla szybkości błysku
val = map(analogRead (analogPin), 0, 1023, 255, 1);
/ / napisz znak do pliku Slave
.beginTransmission (SLAVE_ADDR);
.write (val);
.endtransmisja();
}
|
jak zawsze musimy dołączyć bibliotekę drutu na początku szkicu. Zdefiniujemy również stałą do przechowywania adresu slave.
ponieważ używamy potencjometru, będziemy musieli zdefiniować zarówno pin, do którego jest podłączony, jak i zmienną, aby utrzymać jego wartość.
wszystko, co robimy w konfiguracji, to inicjalizacja połączenia I2C jako master.
W pętli odczytujemy wartość potencjometru i mapujemy ją do zakresu 01-255. Musimy to zrobić, ponieważ wysyłamy jeden bajt informacji i możemy przechowywać tylko tyle wartości w jednym bajcie.
zauważ, że odwracamy sekwencję numeracji w funkcji mapy Arduino, odbywa się to tak, aby system zachowywał się tak, jak tego oczekujemy – przekręcenie potencjometru w prawo zwiększa szybkość błysku. Ponieważ „szybkość błysku” jest określona przez opóźnienie czasowe, większa liczba wysyłanych będzie równa się dłuższej szybkości błysku.
zauważ również, że nie wysyłamy wartości 0, która po prostu utrzyma diodę LED w jednym stanie. Zamiast tego ustawiamy nasz zasięg na 1.
teraz to tylko kwestia wysłania bajtu do slave i powtórzenia pętli ponownie.
Remote Demo Receive Sketch
strona slave musi odbierać dane od master i używać ich do flashowania diody LED.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
|
/ *
Demonstracja slave sterowania I2C
i2c slave-prezentacja zarządzanie.ino
Demonstrate use of I2C bus
Receives potentimeter position data
Controls LED blink rate
DroneBot Workshop 2019
https://dronebotworkshop.com
*/
// Include Arduino Wire library for I2C
#include <Wire.h>
// Define Slave I2C Address
#define SLAVE_ADDR 9
// Define LED Pin
int LED = 13;
// Variable for received data
int rd;
// Variable for blink rate
int br;
void setup () {
pinMode(LED, wyjście);
/ /Inicjalizuj komunikację I2C jako Slave
Przewód.begin (SLAVE_ADDR);
// funkcja uruchamiana po odebraniu danych z przewodu master
.onReceive (receiveEvent);
// Setup Serial Monitor
Serial.begin (9600);
Serial.println („I2C Slave Demonstration”);
}
void receiveEvent () {
// odczytuje jeden znak z I2C
rd = Wire.read ();
/ / wypisuje wartość przychodzących danych
Serial.println (rd);
}
void loop () {
delay (50);
// Oblicz wartość mrugnięcia
br = map (rd, 1, 255, 100, 2000); związku z tym, że w tym przypadku nie jest to możliwe, należy zwrócić uwagę na fakt, że w tym przypadku nie jest to możliwe.> zaczynamy od zwykłego włączenia biblioteki wire, a także zdefiniowania adresu Slave. Definiujemy również pin dla diody LED.
zdefiniowano kilka dodatkowych zmiennych, jedna przechowuje odebrane dane, a druga niesie wartość opóźnienia czasowego dla szybkości mrugania. w konfiguracji ustawiamy pin we/wy dla diody LED jako wyjście i inicjalizujemy magistralę I2C. Gdy używamy adresu slave w funkcji begin, Biblioteka Wire wie, że działamy jako slave. musimy tylko zdefiniować funkcję onReceive, w przeciwieństwie do ostatniego demo nie oczekujemy żadnych żądań od mistrza. Ustawiamy również i drukujemy na monitorze szeregowym, będziemy używać monitora do przeglądania przychodzących danych. funkcja receiveEvent odczytuje przychodzące dane i przypisuje je do zmiennej I. Wyświetla również wartość na monitorze szeregowym. wreszcie, w pętli używamy przychodzących danych do mrugnięcia DIODĄ LED. Po raz kolejny używamy funkcji Map, aby to osiągnąć, zmieniając przychodzące wartości 1-255 na szerszy zakres. Możesz eksperymentować ze zmianą tego zakresu, aby dioda LED migała szybciej lub wolniej, jeśli chcesz. kilka ostatnich wypowiedzi to w zasadzie szkic Arduino Blink in disguise! Włączamy i wyłączamy diodę LED na czas określony w ostatnim kroku. a następnie powtarzamy pętlę. uruchamianie zdalnego Demozaładuj kod i zasilaj oba Arduino. możesz użyć monitora szeregowego na slave Arduino, aby wyświetlić przychodzące dane. obracanie potencjometru powinno teraz zmieniać szybkość migania diody LED na slave. podsumowanieTo kończy nasze pierwsze szczegółowe spojrzenie na I2C. w następnej odsłonie dowiemy się więcej o strukturze danych, które są wymieniane. Weźmiemy również zwykły czujnik i zamienimy go w czujnik I2C. miłego komunikowania się! zasobyszkice – wszystkie szkice I2C użyte w tym artykule. I2C information – informacje dotyczące protokołu I2C Komunikacja I2C Część 1 – Arduino do Arduino
podsumowanie
Nazwa artykułu
I2C communications Part 1 – Arduino do Arduino
opis
w pierwszej części serii artykułów o I2C dowiesz się, czym jest I2C. Zobaczysz także, jak Biblioteka drutu Arduino sprawia, że komunikacja przez I2C jest bardzo prosta.
Author
DroneBot Workshop
Publisher Name
DroneBot Workshop
Publisher Logo
Tagged on: Arduino Tutorial
|