- Vad är I2C-kommunikationsprotokoll?
- Hur fungerar I2C-kommunikation?
- Var ska jag använda I2C-kommunikation?
- I2C i Arduino
- Komponenter krävs
- Kretsschema
- Arbetsförklaring
- I2C-programmering i Arduino
- Master Arduino Programmering Förklaring
- Slave Arduino Programmering Förklaring
I vår tidigare handledning lärde vi oss om SPI-kommunikation i Arduino. Idag lär vi oss ett annat seriellt kommunikationsprotokoll: I2C (Inter Integrated Circuits). Jämförelse av I2C med SPI, I2C har bara två ledningar medan SPI använder fyra och I2C kan ha Multipel Master och Slave, medan SPI bara kan ha en master och flera slavar. Så det finns mer än en mikrokontroller i ett projekt som behöver vara mästare då I2C används. I2C-kommunikation används vanligtvis för att kommunicera med gyroskop, accelerometer, barometertrycksensorer, LED-skärmar etc.
I denna Arduino I2C-handledning använder vi I2C-kommunikation mellan två arduino-kort och skickar (0 till 127) värden till varandra med hjälp av potentiometer. Värden visas på 16x2 LCD-skärmen som är ansluten till var och en av Arduino-enheterna. Här kommer en Arduino att fungera som mästare och en annan som slav. Så låt oss börja med introduktionen om I2C-kommunikation.
Vad är I2C-kommunikationsprotokoll?
Termen IIC står för " Inter Integrated Circuits ". Det betecknas normalt som I2C eller I kvadrat C eller till och med som 2-tråds gränssnittsprotokoll (TWI) på vissa ställen men allt betyder detsamma. I2C är ett synkron kommunikationsprotokoll som betyder att båda enheterna som delar informationen måste dela en gemensam klocksignal. Den har bara två ledningar för att dela information varav den ena används för kocksignalen och den andra används för att skicka och ta emot data.
Hur fungerar I2C-kommunikation?
I2C-kommunikation introducerades först av Phillips. Som sagt tidigare har den två ledningar, dessa två ledningar kommer att anslutas över två enheter. Här kallas en enhet en master och den andra enheten kallas slav. Kommunikation bör och kommer alltid att ske mellan två en mästare och en slav. Fördelen med I2C-kommunikation är att mer än en slav kan anslutas till en mästare.
Den fullständiga kommunikationen sker via dessa två ledningar, nämligen Serial Clock (SCL) och Serial Data (SDA).
Serial Clock (SCL): Delar klocksignalen som genereras av mastern med slaven
Serial Data (SDA): Skickar data till och från mellan Master och slav.
Vid varje given tidpunkt är det bara befälhavaren som kan initiera kommunikationen. Eftersom det finns mer än en slav i bussen måste mästaren hänvisa till varje slav med en annan adress. När endast slaven med den specifika adressen adresseras kommer att svara tillbaka med informationen medan de andra fortsätter. På så sätt kan vi använda samma buss för att kommunicera med flera enheter.
De spänningsnivåer i I2C är inte fördefinierade. I2C-kommunikation är flexibel, betyder att enheten som drivs av 5v volt, kan använda 5v för I2C och 3.3v-enheterna kan använda 3v för I2C-kommunikation. Men vad händer om två enheter som körs på olika spänningar behöver kommunicera med I2C? En 5V I2C-buss kan inte anslutas till en 3.3V-enhet. I detta fall används spänningsväxlare för att matcha spänningsnivåerna mellan två I2C-bussar.
Det finns vissa uppsättningar villkor som ramar in en transaktion. Initiering av sändning börjar med en fallande kant av SDA, vilket definieras som "START" -villkor i nedanstående diagram där master lämnar SCL högt medan SDA är lågt.
Som visas i ovanstående diagram, Den fallande kanten av SDA är hårdvarutlösaren för START-tillståndet. Efter detta går alla enheter på samma buss i lyssningsläge.
På samma sätt stoppar den stigande kanten av SDA överföringen som visas som 'STOPP-tillstånd i ovanstående diagram, där mastern lämnar SCL högt och också släpper SDA för att gå HÖG. Så stigande kant på SDA stoppar överföringen.
R / W-bit indikerar sändningsriktningen för följande byte, om den är HÖG betyder slaven att sända och om den är låg betyder att mastern kommer att sända.
Varje bit sänds på varje klockcykel, så det tar åtta klockcykler att sända en byte. Efter varje byte, antingen skickad eller mottagen, hålls den nionde klockcykeln för ACK / NACK (kvitterad / ej kvitterad). Denna ACK-bit genereras av antingen slav eller master beroende på situationen. För ACK-bit är SDA inställt på lågt av master eller slav vid 9: e klockcykeln. Så det är lågt det anses som ACK annars NACK.
Var ska jag använda I2C-kommunikation?
I2C-kommunikation används endast för kortdistanskommunikation. Det är verkligen tillförlitligt i viss utsträckning eftersom det har en synkroniserad klockpuls för att göra det smart. Detta protokoll används främst för att kommunicera med sensorer eller andra enheter som måste skicka information till en master. Det är mycket praktiskt när en mikrokontroller måste kommunicera med många andra slavmoduler med ett minimum av endast ledningar. Om du letar efter en långväga kommunikation bör du prova RS232 och om du letar efter mer tillförlitlig kommunikation bör du prova SPI-protokollet.
I2C i Arduino
Bilden nedan visar I2C-stiften som finns i Arduino UNO.
I2C Line | Stift i Arduino |
SDA | A4 |
SCL | A5 |
Innan vi börjar programmera I2C med två Arduino. Vi måste lära oss mer om Wire-biblioteket som används i Arduino IDE.
den biblioteket
1. Wire.begin (adress):
Användning: Detta bibliotek används för kommunikation med I2C-enheter. Detta initierar Wire-biblioteket och går med i I2C-bussen som en mästare eller slav.
Adress: 7-bitars slavadressen är valfri och om adressen inte anges ansluter den sig till bussen som en master så här.
2. Wire.read ():
Användning: Denna funktion används för att läsa en byte som mottogs från master- eller slavenhet, antingen som överfördes från en slavenhet till en masterenhet efter ett samtal för att begära från () eller överfördes från en master till en slav.
3. Wire.write ():
Användning: Denna funktion används för att skriva data till en slav eller masterenhet.
Slave to Master: Slave skriver data till en master när Wire.RequestFrom () används i master.
Master to Slave: För överföring från en master till slave-enhet används Wire.write () mellan samtal till Wire.beginTransmission () och Wire.endTransmission ().
Wire.write () kan skrivas som:
- Wire.write (värde)
värde: ett värde som ska skickas som en enda byte.
- Wire.write (sträng):
sträng: en sträng som ska skickas som en serie byte.
- Wire.write (data, längd):
data: en uppsättning data som ska skickas som byte
längd: antalet byte som ska sändas.
4. Wire.beginTransmission (adress):
Användning: Denna funktion används för att börja sända till I2C-enheten med den angivna slavadressen. Bygg sedan en kö med byte för överföring med skrivfunktionen () och sänd dem sedan genom att anropa endTransmission () -funktionen. Enhetens 7-bitarsadress överförs.
5. Wire.endTransmission ();
Användning: Denna funktion används för att avsluta en sändning till en slavenhet som startades av beginTransmission () och sänder de byte som köades av Wire.write ().
6. Wire.onRequest ();
Användning: Denna funktion anropas när en master begär data med Wire.requestFrom () från slavenheten . Här kan vi inkludera Wire.write () -funktionen för att skicka data till mastern.
7. Wire.onReceive ();Användning: Denna funktion anropas när en slavenhet tar emot data från en master. Här kan vi inkludera Wire.read (); funktion för att läsa data som skickas från master.
8. Wire.requestFrom (adress, kvantitet);
Användning: Denna funktion används i mastern för att begära byte från en slavenhet. Funktionen Wire.read () används för att läsa data som skickas från slavenheten.
adress: 7-bitarsadressen för enheten att begära byte från
kvantitet: antalet byte som ska begäras
Komponenter krävs
- Arduino Uno (2-Nos)
- 16X2 LCD-skärmmodul
- 10K potentiometer (4-Nos)
- Bakbord
- Anslutande ledningar
Kretsschema
Arbetsförklaring
Här för att demonstrera I2C-kommunikation i Arduino använder vi två Arduino UNO med två 16X2 LCD-skärmar kopplade till varandra och använder två potentiometrar vid båda arduino för att bestämma sändningsvärdena (0 till 127) från master till slav och slav till master genom att variera potentiometer.
Vi tar ingångsanalogvärdet vid arduino-stift A0 från (0 till 5V) med hjälp av potentiometer och konverterar dem till Analog till Digital-värde (0 till 1023). Sedan konverteras dessa ADC-värden vidare till (0 till 127) eftersom vi bara kan skicka 7-bitars data via I2C-kommunikation. I2C-kommunikationen sker genom två ledningar vid stift A4 och A5 för båda arduino.
Värdena på Slave Arduinos LCD kommer att ändras genom att variera POT på mastersidan och vice versa.
I2C-programmering i Arduino
Denna handledning har två program, ett för master Arduino och ett för slav Arduino. Kompletta program för båda sidor ges i slutet av detta projekt med en demonstrationsvideo.
Master Arduino Programmering Förklaring
1. Först och främst måste vi inkludera Wire-biblioteket för användning av I2C-kommunikationsfunktioner och LCD-bibliotek för användning av LCD-funktioner. Definiera även LCD-stift för 16x2 LCD. Läs mer om gränssnitt mellan LCD och Arduino här.
#omfatta
2. I ogiltig installation ()
- Vi börjar seriekommunikation med överföringshastighet 9600.
Serial.begin (9600);
- Därefter startar vi I2C-kommunikationen vid stift (A4, A5)
Wire.begin (); // Börjar I2C-kommunikation vid stift (A4, A5)
- Därefter initialiserar vi LCD-displaymodulen i 16X2-läge och visar välkomstmeddelandet och rensar efter fem sekunder.
lcd.begin (16,2); // Initiera LCD-skärm lcd.setCursor (0,0); // Ställer in markören på första raden i Display lcd.print ("Circuit Digest"); // skriver CIRCUIT DIGEST i LCD lcd.setCursor (0,1); // Ställer in markören på andra raden i Display lcd.print ("I2C 2 ARDUINO"); // skriver ut I2C ARDUINO i LCD- fördröjning (5000); // Fördröja i 5 sekunder lcd.clear (); // Rensar LCD-skärm
3. I ogiltig slinga ()
- Först måste vi hämta data från slaven så vi använder requestFrom () med slavadressen 8 och vi begär en byte
Wire.requestFrom (8,1);
Det mottagna värdet läses med Wire.read ()
byte MasterReceive = Wire.read ();
- Därefter måste vi läsa det analoga värdet från master arduino POT kopplad till stift A0
int potvalue = analogRead (A0);
Vi konverterar det värdet i termer av en byte till 0 till 127.
byte MasterSend = karta (potvärde, 0,1023,0,127);
- Därefter måste vi skicka de konverterade värdena så att vi börjar överföra med slav arduino med 8-adress
Wire.beginTransmission (8); Wire.write (MasterSend); Wire.endTransmission ();
- Därefter visar vi de mottagna värdena från slaven arduino med en fördröjning på 500 mikrosekunder och vi tar kontinuerligt emot och visar dessa värden.
lcd.setCursor (0,0); // Ställer in markör på rad en i LCD lcd.print (">> Master <<"); // Utskrifter >> Master << vid LCD lcd.setCursor (0,1); // Ställer in markören på rad två i LCD lcd.print ("SlaveVal:"); // Skriver ut SlaveVal: i LCD lcd.print (MasterReceive); // Skriver ut MasterReceive i LCD mottagen från Slave Serial.println ("Master Mottagen från Slave"); // Skriver ut i Serial Monitor Serial.println (MasterReceive); fördröjning (500); lcd.clear ();
Slave Arduino Programmering Förklaring
1. Samma som master, först och främst behöver vi inkludera Wire-biblioteket för att använda I2C-kommunikationsfunktioner och LCD-bibliotek för att använda LCD-funktioner. Definiera även LCD-stift för 16x2 LCD.
#omfatta
2. I ogiltig installation ()
- Vi börjar seriekommunikation med överföringshastighet 9600.
Serial.begin (9600);
- Därefter startar vi I2C-kommunikationen vid stift (A4, A5) med slavadress som 8. Här är det viktigt att ange slavadressen.
Wire.begin (8);
Därefter måste vi anropa funktionen när Slave får värde från master och när Master begär värde från Slave
Wire.onReceive (receiveEvent); Wire.onRequest (requestEvent);
- Därefter initialiserar vi LCD-displaymodulen i 16X2-läge och visar välkomstmeddelandet och rensar efter fem sekunder.
lcd.begin (16,2); // Initiera LCD-skärm lcd.setCursor (0,0); // Ställer in markören på första raden i Display lcd.print ("Circuit Digest"); // skriver CIRCUIT DIGEST i LCD lcd.setCursor (0,1); // Ställer in markören på andra raden i Display lcd.print ("I2C 2 ARDUINO"); // skriver ut I2C ARDUINO i LCD- fördröjning (5000); // Fördröja i 5 sekunder lcd.clear (); // Rensar LCD-skärm
3. Därefter har vi två funktioner en för begivenhetshändelse och en för mottagningshändelse
För begäran Event
När värdet för masterbegäran från slaven kommer denna funktion att köras. Denna funktion tar inmatningsvärde från Slave POT och konverterar det i termer av 7-bitars och skickar det värdet till master.
ogiltig requestEvent () { int potvalue = analogRead (A0); byte SlaveSend = karta (potvärde, 0,1023,0,127); Wire.write (SlaveSend); }
För mottagningshändelse
När Master skickar data till slav med slavadress (8) kommer denna funktion att utföras. Denna funktion läser det mottagna värdet från master och lagring i en variabel av typbyte .
ogiltigt mottagandeEvent (int howMany { SlaveReceived = Wire.read (); }
4. I Void loop ():
Vi visar det mottagna värdet från master kontinuerligt i LCD-displaymodulen.
void loop (void) { lcd.setCursor (0,0); // Ställer in markör på rad en i LCD lcd.print (">> Slave <<"); // Skriv ut >> Slav << vid LCD lcd.setCursor (0,1); // Ställer in markören vid rad två i LCD lcd.print ("MasterVal:"); // Skriver ut MasterVal: i LCD lcd.print (SlaveReceived); // Skriver ut SlaveReceived värde i LCD mottagen från Master Serial.println ("Slave mottagen från Master:"); // Skriver ut i Serial Monitor Serial.println (SlaveReceived); fördröjning (500); lcd.clear (); }
Genom att vrida potentiometern på ena sidan kan du se de olika värdena på LCD-skärmen på en annan sida:
Så detta är hur I2C-kommunikation sker i Arduino, här har vi använt två Arduinos för att visa inte bara skicka data utan också ta emot data med I2C-kommunikation. Så nu kan du ansluta vilken som helst I2C-sensor till Arduino.
Den fullständiga kodningen för Master och Slave Arduino ges nedan med en demonstrationsvideo