- Какво е I2C протокол за комуникация?
- Как работи I2C Комуникацията?
- Къде да използвам I2C комуникация?
- I2C в Arduino
- Необходими компоненти
- Електрическа схема
- Работно обяснение
- Програмиране на I2C в Arduino
- Master Arduino Програмиране Обяснение
- Обяснение на програмирането на Slave Arduino
В предишния ни урок научихме за SPI комуникацията в Arduino. Днес ще научим за друг протокол за серийна комуникация: I2C (Inter Integrated Circuits). Сравнявайки I2C със SPI, I2C има само два проводника, докато SPI използва четири, а I2C може да има множество главни и подчинени, докато SPI може да има само един главен и няколко подчинени. Така че в проекта има повече от един микроконтролер, който трябва да бъде майстор, след това се използва I2C. I2C комуникацията обикновено се използва за комуникация с жироскоп, акселерометър, барометрични сензори за налягане, LED дисплеи и т.н.
В този урок за Arduino I2C ще използваме I2C комуникация между две платки на arduino и ще изпращаме стойности (от 0 до 127) помежду си, като използваме потенциометър. Стойностите ще се показват на 16x2 LCD, свързан към всеки от Arduino. Тук един Arduino ще действа като Господар, а друг ще действа като Slave. Затова нека започнем с въведението за I2C комуникацията.
Какво е I2C протокол за комуникация?
Терминът IIC означава „ Интер интегрални схеми “. Обикновено се обозначава като I2C или I на квадрат C или дори като двупроводен интерфейсен протокол (TWI) на някои места, но всичко означава едно и също. I2C е синхронен комуникационен протокол, което означава, че и двете устройства, които споделят информацията, трябва да споделят общ тактов сигнал. Той има само два проводника за споделяне на информация, от които единият се използва за сигнала на крана, а другият се използва за изпращане и получаване на данни.
Как работи I2C Комуникацията?
I2C комуникацията е представена за първи път от Филипс. Както беше казано по-рано, той има два проводника, тези два проводника ще бъдат свързани през две устройства. Тук едното устройство се нарича master, а другото устройство се нарича slave. Комуникацията трябва и винаги ще се осъществява между двама Господар и Роб. Предимството на I2C комуникацията е, че повече от един slave може да бъде свързан към Master.
Пълната комуникация се осъществява чрез тези два проводника, а именно, сериен часовник (SCL) и сериен данни (SDA).
Сериен часовник (SCL): Споделя сигнала на часовника, генериран от главното устройство, с подчинения
Серийни данни (SDA): Изпраща данните към и между главния и подчинения.
Във всеки един момент само майсторът ще може да инициира комуникацията. Тъй като в шината има повече от един slave, капитанът трябва да се обърне към всеки slave, използвайки различен адрес. Когато се обърне само робът с този конкретен адрес ще отговори с информацията, докато останалите продължават да излизат. По този начин можем да използваме една и съща шина за комуникация с множество устройства.
Нивата на напрежение на I2C не са предварително дефинирани. I2C комуникацията е гъвкава, означава устройството, което се захранва от 5v волта, може да използва 5v за I2C и 3.3v устройствата могат да използват 3v за I2C комуникация. Но какво, ако две устройства, работещи на различни напрежения, трябва да комуникират чрез I2C? А 5V I2C автобус не може да бъде свързан с 3.3V устройство. В този случай превключвателите на напрежение се използват за съвпадение на нивата на напрежение между две I2C шини.
Има някои условия, които определят транзакцията. Инициализирането на предаването започва с падащ ръб на SDA, което се дефинира като условие „START“ в диаграмата по-долу, където master оставя 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 устройства. Това стартира Wire библиотеката и се присъединява към I2C шината като главен или подчинен.
Адрес: 7-битовият роб адрес не е задължителен и ако адресът не е посочен, той се присъединява към шината като главен като този.
2. Wire.read ():
Употреба: Тази функция се използва за четене на байт, получен от главно или подчинено устройство, или който е предаден от подчинено устройство към главно устройство след повикване към requestFrom () или е предаден от главен на подчинен.
3. Wire.write ():
Използване: Тази функция се използва за записване на данни в подчинено или главно устройство.
Slave to Master: Slave записва данни на master, когато Wire.RequestFrom () се използва в master.
Master to Slave: За предаване от master към slave устройство Wire.write () се използва между повикванията на Wire.beginTransmission () и Wire.endTransmission ().
Wire.write () може да се запише като:
- Wire.write (стойност)
value: стойност, която се изпраща като единичен байт.
- Wire.write (низ):
низ: низ, който се изпраща като поредица от байтове.
- Wire.write (данни, дължина):
data: масив от данни, който се изпраща като байтове
дължина: броят на байтовете за предаване.
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 (); функция за четене на данните, изпратени от master.
8. Wire.requestFrom (адрес, количество);
Използване: Тази функция се използва в главното устройство за заявяване на байтове от подчинено устройство. Функцията Wire.read () се използва за четене на данните, изпратени от подчиненото устройство.
address: 7-битовият адрес на устройството, от което се искат байтове
количество: броят на байтовете за заявка
Необходими компоненти
- Arduino Uno (2-Nos)
- 16X2 LCD дисплеен модул
- 10K потенциометър (4-Nos)
- Макет
- Свързване на проводници
Електрическа схема
Работно обяснение
Тук за демонстриране на I2C комуникация в Arduino използваме Two Arduino UNO с два 16X2 LCD дисплея, прикрепени един към друг, и използваме два потенциометра на двата arduino, за да определим стойностите за изпращане (от 0 до 127) от главен на подчинен и подчинен на главен, като променяме потенциометър.
Взимаме входна аналогова стойност на arduino pin A0 от (0 до 5V) с помощта на потенциометър и ги преобразуваме в аналогова в цифрова стойност (0 до 1023). След това тези ADC стойности се преобразуват допълнително в (0 до 127), тъй като можем да изпращаме само 7-битови данни чрез I2C комуникация. Комуникацията I2C се осъществява чрез два проводника на пин A4 и A5 на двата arduino.
Стойностите на LCD на Slave Arduino ще се променят чрез промяна на POT от главната страна и обратно.
Програмиране на I2C в Arduino
Този урок има две програми - една за главен Arduino и друга за slave Arduino. Пълни програми за двете страни са дадени в края на този проект с демонстрационно видео.
Master Arduino Програмиране Обяснение
1. На първо място трябва да включим Wire библиотека за използване на комуникационни функции I2C и LCD библиотека за използване на LCD функции. Определете също LCD щифтове за LCD 16x2. Научете повече за свързването на LCD с Arduino тук.
#include
2. При настройка за невалидност ()
- Започваме серийна комуникация със скорост на предаване 9600.
Serial.begin (9600);
- След това стартираме комуникацията I2C на пин (A4, A5)
Wire.begin (); // Започва I2C комуникация на пин (A4, A5)
- След това инициализираме LCD дисплейния модул в режим 16X2 и показваме приветственото съобщение и изчистваме след пет секунди.
lcd.begin (16,2); // Инициализиране на LCD дисплей lcd.setCursor (0,0); // Задава курсора на първия ред на дисплея lcd.print ("Circuit Digest"); // отпечатва CIRCUIT DIGEST в LCD lcd.setCursor (0,1); // Задава курсора на втория ред на дисплея lcd.print ("I2C 2 ARDUINO"); // отпечатва I2C ARDUINO при LCD забавяне (5000); // Забавяне за 5 секунди lcd.clear (); // Изчиства LCD дисплея
3. In void loop ()
- Първо трябва да получим данни от подчиненото устройство, затова използваме requestFrom () с подчинен адрес 8 и искаме един байт
Wire.requestFrom (8,1);
Получената стойност се чете с помощта на Wire.read ()
байт MasterReceive = Wire.read ();
- След това трябва да прочетем аналоговата стойност от главния arduino POT, прикрепен към щифт A0
int potvalue = analogRead (A0);
Преобразуваме тази стойност в един байт като 0 до 127.
байт MasterSend = карта (potvalue, 0,1023,0,127);
- След това трябва да изпратим тези преобразувани стойности, така че започваме предаването с подчинен arduino с 8 адрес
Wire.beginTransmission (8); Wire.write (MasterSend); Wire.endTransmission ();
- След това показваме получените стойности от подчиненото arduino със закъснение от 500 микросекунди и непрекъснато получаваме и показваме тези стойности.
lcd.setCursor (0,0); // Задава курсора на ред първи от LCD lcd.print (">> Master <<"); // Разпечатки >> Главен << на LCD lcd.setCursor (0,1); // Задава курсора на втори ред от LCD lcd.print ("SlaveVal:"); // Отпечатва SlaveVal: в LCD lcd.print (MasterReceive); // Отпечатва MasterReceive в LCD, получен от Slave Serial.println ("Master Received From Slave"); // Отпечатва в Serial Monitor Serial.println (MasterReceive); забавяне (500); lcd.clear ();
Обяснение на програмирането на Slave Arduino
1. Същото като master, на първо място трябва да включим Wire библиотека за използване на комуникационни функции I2C и LCD библиотека за използване на LCD функции. Определете също LCD щифтове за LCD 16x2.
#include
2. При настройка за невалидност ()
- Започваме серийна комуникация със скорост на предаване 9600.
Serial.begin (9600);
- След това стартираме I2C комуникацията на пин (A4, A5) с подчинен адрес като 8. Тук е важно да посочим подчинения адрес.
Wire.begin (8);
След това трябва да извикаме функцията, когато Slave получава стойност от master и когато Master изисква стойност от Slave
Wire.onReceive (receiveEvent); Wire.onRequest (requestEvent);
- След това инициализираме LCD дисплейния модул в режим 16X2 и показваме приветственото съобщение и изчистваме след пет секунди.
lcd.begin (16,2); // Инициализиране на LCD дисплей lcd.setCursor (0,0); // Задава курсора на първия ред на дисплея lcd.print ("Circuit Digest"); // отпечатва CIRCUIT DIGEST в LCD lcd.setCursor (0,1); // Задава курсора на втория ред на дисплея lcd.print ("I2C 2 ARDUINO"); // отпечатва I2C ARDUINO при LCD забавяне (5000); // Забавяне за 5 секунди lcd.clear (); // Изчиства LCD дисплея
3. След това имаме две функции една за събитие за заявка и една за събитие за получаване
За заявка Събитие
Когато стойността на главната заявка от подчинена тази функция ще бъде изпълнена. Тази функция взема входна стойност от Slave POT и я преобразува в 7-битова и изпраща тази стойност на master.
void requestEvent () { int potvalue = analogRead (A0); байт SlaveSend = карта (potvalue, 0,1023,0,127); Wire.write (SlaveSend); }
За събитие за получаване
Когато Master изпраща данни на slave с slave адрес (8), тази функция ще бъде изпълнена. Тази функция чете получената стойност от master и съхранява в променлива от тип байт .
void receiveEvent (int howMany { SlaveReceived = Wire.read (); }
4. В цикъл Void ():
Показваме получената стойност от master непрекъснато в LCD дисплейния модул.
цикъл на невалидни (void) { lcd.setCursor (0,0); // Задава курсора на ред първи от LCD lcd.print (">> Slave <<"); // Разпечатки >> Slave << на LCD lcd.setCursor (0,1); // Задава курсора на втори ред от LCD lcd.print ("MasterVal:"); // Отпечатва MasterVal: в LCD lcd.print (SlaveReceived); // Отпечатва SlaveReceived стойност в LCD, получена от Master Serial.println ("Slave Received From Master:"); // Отпечатва в Serial Monitor Serial.println (SlaveReceived); забавяне (500); lcd.clear (); }
Чрез завъртане на потенциометъра от едната страна можете да видите различните стойности на LCD от другата страна:
Така че, как се осъществява I2C комуникацията в Arduino, тук използваме два Arduinos, за да демонстрираме не само изпращане на данни, но и получаване на данни чрез I2C комуникация. Така че сега можете да свържете всеки I2C сензор с Arduino.
Пълното кодиране за Master и Slave Arduino е дадено по-долу с демонстрационно видео