- Що таке протокол зв'язку I2C?
- Як працює I2C Communication?
- Де використовувати зв'язок I2C?
- I2C в Arduino
- Потрібні компоненти
- Кругова діаграма
- Робоче пояснення
- Програмування I2C в Arduino
- Майстер Arduino програмування Пояснення
- Пояснення програмування підлеглого Arduino
У нашому попередньому підручнику ми дізналися про комунікацію SPI в Arduino. Сьогодні ми дізнаємось про ще один протокол послідовного зв'язку: I2C (інтегральні мікросхеми). Порівнюючи I2C з SPI, I2C має лише два дроти, тоді як SPI використовує чотири, а I2C може мати декілька ведучих і ведених, тоді як SPI може мати лише одного ведучого та декілька ведених. Отже, у проекті є більше одного мікроконтролера, який повинен бути майстрами, тоді використовується I2C. Зв'язок I2C зазвичай використовується для зв'язку з гіроскопом, акселерометром, барометричними датчиками тиску, світлодіодними дисплеями тощо.
У цьому посібнику з Arduino I2C ми використовуватимемо зв'язок I2C між двома платами arduino та передаватиме значення (від 0 до 127) один одному за допомогою потенціометра. Значення відображатимуться на РК-дисплеї розміром 16x2, підключеному до кожного з Arduino. Тут один Ардуїно діятиме як Господар, а інший - як Раб. Отже, почнемо із вступу про спілкування I2C.
Що таке протокол зв'язку I2C?
Термін IIC розшифровується як “ Інтегральні мікросхеми ”. Зазвичай це позначається як I2C, або я в квадраті C, або навіть як 2-провідний інтерфейсний протокол (TWI) в деяких місцях, але все це означає одне і те ж. I2C - це протокол синхронного зв'язку, що означає, що обидва пристрої, які обмінюються інформацією, повинні мати спільний тактовий сигнал. Він має лише два дроти для обміну інформацією, з яких один використовується для сигналу крана, а інший - для передачі та прийому даних.
Як працює I2C Communication?
Вперше зв'язок I2C був представлений Філіпсом. Як вже було сказано раніше, він має два дроти, ці два дроти будуть з'єднані між собою двома пристроями. Тут один пристрій називається ведучим, а інший пристрій - веденим. Спілкування повинно і завжди відбуватиметься між двома Володарем і Рабом. Перевага зв'язку I2C полягає в тому, що до ведучого може бути підключено більше одного веденого пристрою.
Повна комунікація відбувається за допомогою цих двох проводів, а саме: послідовного годинника (SCL) та послідовних даних (SDA).
Серійний годинник (SCL): Поділяє тактовий сигнал, сформований ведучим, із веденим пристроєм
Серійні дані (SDA): Надсилає дані до головного та веденого пристроїв та назад.
У будь-який момент часу тільки майстер зможе ініціювати спілкування. Оскільки в шині більше одного веденого, ведучий повинен посилатися на кожного веденого, використовуючи іншу адресу. При зверненні лише ведений з цією конкретною адресою відповість з інформацією, поки інші продовжують виходити. Таким чином ми можемо використовувати одну і ту ж шину для зв'язку з кількома пристроями.
На рівнях напруги I2C не призначені. Зв'язок I2C є гнучким, означає пристрій, який живиться від напруги 5 В, може використовувати 5 В для I2C, а пристрої 3,3 В можуть використовувати 3 В для зв'язку I2C. Але що, якщо два пристрої, що працюють на різній напрузі, потребують зв’язку за допомогою I2C? Шина I2C 5V не може бути пов'язана з 3.3V пристрої. У цьому випадку регулятори напруги використовуються для узгодження рівнів напруги між двома шинами I2C.
Існує певний набір умов, які визначають транзакцію. Ініціалізація передачі починається з падаючого краю SDA, який визначається як умова «СТАРТ» на діаграмі нижче, де ведучий залишає SCL високим при встановленні SDA низьким.
Як показано на наведеній вище схемі нижче, Край SDA є апаратним пусковим механізмом для старту START. Після цього всі пристрої на одній шині переходять у режим прослуховування.
Таким же чином, висхідний край SDA зупиняє передачу, що відображається як умова 'STOP' на наведеній вище схемі, де ведучий залишає SCL високим, а також випускає SDA, щоб піднятися HIGH. Тож висхідний край SDA зупиняє передачу.
Біт R / W вказує напрямок передачі наступних байтів, якщо він HIGH, це означає, що ведений передаватиме, а якщо він низький, означає, що головний передаватиме.
Кожен біт передається на кожному тактовому циклі, тому для передачі байта потрібно 8 тактових циклів. Після кожного відправленого або отриманого байту для ACK / NACK (підтверджено / не підтверджено) проводиться дев'ятий тактовий цикл. Цей біт ACK генерується підпорядкованим або ведучим залежно від ситуації. Для біту ACK SDA встановлюється на низький рівень ведучим або веденим пристроєм на 9- му тактовому циклі. Отже, низький рівень вважається ACK, інакше NACK.
Де використовувати зв'язок I2C?
Зв'язок I2C використовується лише для зв'язку на короткі відстані. Це, безумовно, надійно до певної міри, оскільки він має синхронізований тактовий імпульс, щоб зробити його розумним. Цей протокол в основному використовується для зв'язку з датчиком або іншими пристроями, які повинні надсилати інформацію майстру. Дуже зручно, коли мікроконтролер повинен взаємодіяти з багатьма іншими підлеглими модулями, використовуючи мінімум лише дроти. Якщо ви шукаєте зв'язку на великі відстані, вам слід спробувати RS232, а якщо ви шукаєте більш надійний зв'язок, спробуйте протокол SPI.
I2C в Arduino
На зображенні нижче показані штифти I2C, присутні в Arduino UNO.
Лінія I2C | Булавка в Arduino |
SDA | A4 |
SCL | A5 |
Перш ніж ми почнемо програмувати I2C за допомогою двох Arduino. Нам потрібно дізнатись про бібліотеку Wire, що використовується в IDE Arduino.
бібліотека
1. Wire.begin (адреса):
Використання: Ця бібліотека використовується для встановлення зв'язку з пристроями I2C. Це ініціює роботу з бібліотекою дротів та приєднання до шини I2C як ведучого або підлеглого.
Адреса: 7-розрядна підлегла адреса не є обов’язковою, і якщо адреса не вказана, вона приєднується до шини як головний, як цей.
2. Wire.read ():
Використання: Ця функція використовується для зчитування байта, який був отриманий від ведучого або веденого пристрою, або який був переданий від веденого пристрою на головний пристрій після виклику requestFrom (), або переданий від ведучого до веденого.
3. Wire.write ():
Використання: Ця функція використовується для запису даних на підлеглий або головний пристрій.
Підпорядкований ведучому : підлеглий записує дані до ведучого, коли в master використовується Wire.RequestFrom () .
Ведучий до підлеглого : Для передачі від ведучого до підлеглого пристрою використовується Wire.write () між викликами Wire.beginTransmission () та Wire.endTransmission ().
Wire.write () можна записати як:
- Wire.write (значення)
value: значення, яке надсилається у вигляді одного байта.
- Wire.write (рядок):
string: рядок, який слід надіслати у вигляді серії байтів.
- Wire.write (дані, довжина):
data: масив даних, що надсилається у вигляді байтів
length: кількість байт для передачі.
4. Wire.beginTransmission (адреса):
Використання: Ця функція використовується для початку передачі на пристрій I2C із заданою адресою веденого пристрою. Згодом побудуйте чергу байтів для передачі за допомогою функції write (), а потім передайте їх, викликавши функцію endTransmission () . Передається 7-бітна адреса пристрою.
5. Wire.endTransmission ();
Використання: Ця функція використовується для завершення передачі на підлеглий пристрій, розпочатої методом beginTransmission (), і передає байти, які були в черзі за допомогою Wire.write ().
6. Wire.onRequest ();
Використання: Ця функція викликається, коли ведучий запитує дані за допомогою Wire.requestFrom () із підлеглого пристрою. Сюди ми можемо включити функцію Wire.write () для передачі даних майстру.
7. Wire.onReceive ();Використання: Ця функція викликається, коли підлеглий пристрій отримує дані від ведучого. Сюди ми можемо включити Wire.read (); функція зчитування даних, надісланих від майстра.
8. Wire.requestFrom (адреса, кількість);
Використання: Ця функція використовується у ведучому для запиту байтів від підлеглого пристрою. Функція Wire.read () використовується для зчитування даних, надісланих з веденого пристрою.
address: 7-розрядна адреса пристрою, з якого потрібно запитувати байти
кількість: кількість байтів на запит
Потрібні компоненти
- Arduino Uno (2-Nos)
- Модуль РК-дисплея 16X2
- Потенціометр 10K (4-Ні)
- Макет
- Підключення проводів
Кругова діаграма
Робоче пояснення
Тут для демонстрації зв'язку I2C в Arduino ми використовуємо два Arduino UNO з двома РК-дисплеями 16X2, прикріпленими один до одного, і використовуємо два потенціометри на обох arduino для визначення значень передачі (від 0 до 127) від ведучого до веденого та веденого до ведучого, змінюючи значення потенціометр.
Ми приймаємо вхідне аналогове значення на ардуїновому виводі A0 від (0 до 5 В) за допомогою потенціометра і перетворюємо їх в аналогове в цифрове значення (від 0 до 1023). Потім ці значення ADC перетворюються далі (від 0 до 127), оскільки ми можемо надсилати лише 7-бітові дані через I2C-зв'язок. Зв'язок I2C відбувається через два дроти на штифтах A4 і A5 обох arduino.
Значення на рідкокристалічному дисплеї Slave Arduino будуть змінені, змінюючи значення POT на стороні ведучого і навпаки.
Програмування I2C в Arduino
Цей підручник має дві програми - одну для майстра Arduino та іншу для раба Arduino. Повні програми для обох сторін наведені в кінці цього проекту з демонстраційним відео.
Майстер Arduino програмування Пояснення
1. Перш за все нам потрібно включити бібліотеку Wire для використання функцій зв'язку I2C та бібліотеку LCD для використання функцій LCD. Також визначте РК-шпильки для РК-дисплеїв 16x2. Дізнайтеся більше про взаємодію РК із Arduino тут.
#включати
2. Налаштування void ()
- Ми починаємо послідовний зв'язок зі швидкістю передачі даних 9600.
Serial.begin (9600);
- Далі ми починаємо зв'язок I2C на штифті (A4, A5)
Wire.begin (); // Починає зв'язок I2C на штифті (A4, A5)
- Далі ми ініціалізуємо модуль РК-дисплея в режимі 16X2 і відображаємо привітальне повідомлення та очищаємо через п’ять секунд.
lcd.begin (16,2); // Ініціалізація РК-дисплея lcd.setCursor (0,0); // Встановлює курсор у першому рядку дисплея lcd.print ("Circuit Digest"); // Друкує CIRCUIT DIGEST у РК-дисплеї lcd.setCursor (0,1); // Встановлює курсор у другому рядку дисплея lcd.print ("I2C 2 ARDUINO"); // Друкує I2C ARDUINO із затримкою РК (5000); // Затримка на 5 секунд lcd.clear (); // Очищає РК-дисплей
3. У циклі void ()
- Спочатку нам потрібно отримати дані від веденого пристрою, тому ми використовуємо requestFrom () із веденою адресою 8 і запитуємо один байт
Wire.requestFrom (8,1);
Отримане значення зчитується за допомогою Wire.read ()
байт MasterReceive = Wire.read ();
- Далі нам потрібно прочитати аналогове значення з основного ардуіно POT, приєднаного до виводу A0
int potvalue = analogRead (A0);
Ми перетворюємо це значення в перерахунку на один байт як 0 до 127.
байт MasterSend = map (potvalue, 0,1023,0,127);
- Далі нам потрібно надіслати ці перетворені значення, тому ми розпочнемо передачу з веденого arduino з 8 адресами
Wire.beginTransmission (8); Wire.write (MasterSend); Wire.endTransmission ();
- Далі ми відображаємо ці отримані значення від веденого arduino з затримкою в 500 мікросекунд, і ми постійно отримуємо та відображаємо ці значення.
lcd.setCursor (0,0); // Встановлює курсор у першому рядку рідкокристалічного друку LCD (">> Master <<"); // Друк >> Майстер << на LCD lcd.setCursor (0,1); // Встановлює курсор у другому рядку рідкокристалічного друку РК ("SlaveVal:"); // Друкує SlaveVal: у рідкокристалічному РК- принтері (MasterReceive); // Друкує MasterReceive на РК-дисплеї, отриманому від Slave Serial.println ("Master Received From Slave"); // Друк у послідовному моніторі Serial.println (MasterReceive); затримка (500); lcd.clear ();
Пояснення програмування підлеглого Arduino
1. Те саме, що і master, перш за все, нам потрібно включити Wire бібліотеку для використання функцій зв'язку I2C та LCD бібліотеку для використання функцій LCD. Також визначте РК-шпильки для РК-дисплеїв 16x2.
#включати
2. Налаштування void ()
- Ми починаємо послідовний зв'язок зі швидкістю передачі даних 9600.
Serial.begin (9600);
- Далі ми починаємо зв’язок I2C на виводі (A4, A5) з веденою адресою як 8. Тут важливо вказати адресу веденої.
Wire.begin (8);
Далі нам потрібно викликати функцію, коли ведений отримує значення від ведучого і коли головний запит значення від веденого
Wire.onReceive (receiveEvent); Wire.onRequest (requestEvent);
- Далі ми ініціалізуємо модуль РК-дисплея в режимі 16X2 і відображаємо привітальне повідомлення та очищаємо через п’ять секунд.
lcd.begin (16,2); // Ініціалізація РК-дисплея lcd.setCursor (0,0); // Встановлює курсор у першому рядку дисплея lcd.print ("Circuit Digest"); // Друкує CIRCUIT DIGEST у РК-дисплеї lcd.setCursor (0,1); // Встановлює курсор у другому рядку дисплея lcd.print ("I2C 2 ARDUINO"); // Друкує I2C ARDUINO із затримкою РК (5000); // Затримка на 5 секунд lcd.clear (); // Очищає РК-дисплей
3. Далі ми маємо дві функції: одну для події запиту та одну для події отримання
За запитом Подія
Коли значення головного запиту від веденого, ця функція буде виконана. Ця функція приймає вхідне значення з веденого POT і перетворює його в 7-бітове значення і надсилає це значення майстру.
void requestEvent () { int potvalue = analogRead (A0); байт SlaveSend = map (potvalue, 0,1023,0,127); Wire.write (SlaveSend); }
Для отримання події
Коли ведучий надсилає дані веденому з веденою адресою (8), ця функція буде виконана. Ця функція зчитує отримане значення з ведучого та зберігає у змінній типу байт .
void receiveEvent (int howMany { SlaveReceived = Wire.read (); }
4. У циклі Void ():
Отримане значення від ведучого ми постійно відображаємо в модулі РК-дисплея.
цикл void (void) { lcd.setCursor (0,0); // Встановлює курсор у першому рядку РК- друку (">> Ведений <<"); // Друк >> Slave << на LCD lcd.setCursor (0,1); // Встановлює курсор у другому рядку РК- друку ("MasterVal:"); // Друкує MasterVal: у РК-дисплеї lcd.print (SlaveReceived); // Друкує значення SlaveReceived на РК-дисплеї, отримане від Master Serial.println ("Ведомий елемент, отриманий від ведучого:"); // Друк у послідовному моніторі Serial.println (SlaveReceived); затримка (500); lcd.clear (); }
При обертанні потенціометра з одного боку, ви можете побачити різні значення на РК - дисплеї на іншій стороні:
Отже, таким чином відбувається спілкування I2C в Arduino, тут ми використовуємо два Arduino, щоб продемонструвати не тільки надсилання даних, але й отримання даних за допомогою зв’язку I2C. Тож тепер ви можете підключити будь-який датчик I2C до Arduino.
Повне кодування для Arduino Master і Slave подано нижче з демонстраційним відео