مقدمه
Inter-Integrated Circuit یا به اختصار I2C یک پروتکل ارتباطی سریال میباشد.
این پروتکل two wire interface) TWI) نیز نامیده میشود زیرا از دو سیم برای برقراری ارتباط استفاده میکند. این دوسیم SDA (داده سریال) و SCL (کلاک سریال) میباشند.
I2C یک پروتکل ارتباطی مبتنی بر تایید (acknowledgment-based) میباشد، بدین معنی که فرستنده پس از انتقال داده یک تایید از طرف گیرنده را درخواست کرده تا مطلع گردد که گیرنده داده را با موفقیت تحویل گرفته است.
I2C در دو حالت با نامهای زیر کار میکند،
- مد ارباب (Master mode)
- مد برده (Slave mode)
SDA برای تبادل داده بین دستگاههای ارباب و برده به کار میرود.
SCL به عنوان کلاک همزمان کننده ارباب و برده به کار میرود.
دستگاه ارباب ارتباط را با دستگاه برده آغاز میکند. ارباب برای شروع گفتگو به آدرس برده نیاز دارد. وقتی که ارباب برده را با آدرسش خطاب قرار میدهد، برده به آن پاسخ میدهد.
دستگاههای I2C دارای آدرسهای منحصربه فرد ۷ بیته یا ۱۰ بیته میباشند. بنابراین برای دسترسی به این قطعات، ارباب باید از طریق این آدرسهای یکتای ۷ یا ۱۰ بیته آنها را خطاب قرار دهد.
I2C کاربردهای فراوانی مانند خواندن RTC (ساعت بلادرنگ) و دسترسی به حافظه EEPROM خارجی دارد. همچنین از آن در ماژولهای سنسور مانند ژیروسکوپ و مغناطیسسنج و … نیز استفاده میشود.
پروتکل I2C از دو خط برای ارتباط استفاده میکند.
- SCL: یک سیگنال کلاک میباشد. داده روی لبه کلاک به دیگر دستگاهها ارسال میشود.
- SDA: یک خط داده سریال بوده که برای تبادل داده بین ارباب و برده استفاده میشود.
گذرگاه I2C پیکربندی درین باز (open drain) دارد، بدین معنی که میتواند خط سیگنال را به پایین بکشد اما نمیتواند آن را بالاکش کند. بنابراین خط به حالت نامشخص خواهد رفت. برای اجتناب از این وضعیت، باید از مقاومتهای بالاکش (مقاومت های پول آپ Pull-up ، کاربرد و محاسبه) برای اتصال به پینهای SCL و SDA استفاده کرد.
پینهای I2C در آردوینو
پینهای I2C بورد آدوینو Uno در شکل زیر مشخص شدهاند.
بورد آردوینو Uno تنها یک ماژول I2C دارد، اما دو خط SDA و SCL را در دو مکان مختلف فراهم آورده است.
نکته: هنگام برقراری ارتباط با پروتکل I2C، باید از مقاومتهای بالاکش استفاده کرد. مقدار این مقاومتها بسته به دستگاه به کار رفته متفاوت است.
توابع I2C برای آردوینو
(Wire.write (data: برای نوشتن (انتقال) داده به ارباب یا برده استفاده میشود.
پارامترها
Data: میتواند یک تک بایت، رشته یا آرایهای از دادهها باشد.
مقدار بازگشتی
تعداد بایتهای نوشته شده را برمیگرداند.
مثال
Wire.write(7); //send data byte Wire.write(“i2c”); //send string to slave device Wire.write(a, 6); //here a is an array
()Wire.available: این تابع از طرف ارباب یا برده به کار گرفته میشود تا بررسی کند که داده درخواست شده موجود هست یا خیر و تعداد بایتهای موجود را برمیگرداند.
()Wire.read: از این تابع برای خواندن داده مورد درخواست از برده به ارباب یا برای خواندن داده فرستاده شده از ارباب به برده استفاده میشود.
توابع مورد استفاده برای I2C ارباب در آردوینو
نکته: هر I2C برده دارای یک آدرس منحصر به فرد میباشد. هنگام برقراری ارتباط با پروتکل I2C، ارباب از این آدرس استفاده میکند.
آردوینو دارای کتابخانهای به نام Wire Library میباشد که امکان برقراری ارتباط با دستگاههای I2C را فراهم میکند.
()Wire.begin: کتابخانهی Wire را مقداردهی اولیه (initialization) کرده و گذرگاه را به عنوان ارباب متصل میکند.
(Wire.beginTransmission (slave address: این تابع فرآیند انتقال به یک I2C برده با آدرس مشخص را شروع میکند. Slave address آدرس ۷ بیته دستگاهی است که میخواهیم با آن ارتباط برقرار کنیم.
مثال:
Wire.beginTransmission (50) //begin transmission with slave having address 50
Wire. requestFrom(address, no of byte)
یا
Wire. requestFrom(address, no of byte, stop)
این تابع را ارباب به کار بسته تا از برده داده درخواست کرده و یا داده را دریافت کند. داده مورد درخواست را میتوان با تابع ()Wire.read خواند.
پارامترها
Address: آدرس دستگاهی که میخواهیم با آن ارتباط برقرار کنیم.
No . of byte: تعداد بایتهای مورد درخواست.
Stop: یک مقدار بولی است که:
- True: یک پیام توقف بعد از درخواست ارسال کرده و گذرگاه را آزاد میکند.
- False: به صورت بیوقفه پس از درخواست یک restart ارسال میکند، و ارتباط را فعال نگه میدارد.
مقدار بازگشتی
تعداد بایتهای برگردانده شده از برده را برمیگرداند.
مثال
Wire.requestFrom(50, 4) //request 4 no. of bytes from slave having address 50 Wire.requestFrom(50, 4, true) //will stop receiving data after 4 bytes, releasing bus
()Wire.endTransmission: این تابع، فرآیند انتقالی که با تابع ()beginTransmisson آغاز شده بود را پایان داده و دادههای صفبندی شده با تابع ()write را ارسال میکند.
مقدار بازگشتی
بایتهایی که نشانگر وضعیت انتقال هستند را برمیگرداند.
توابع مورد استفاده برای I2C برده در آردوینو
(Wire.begin (address: کتابخانه Wire را مقداردهی اولیه کرده و گذرگاه I2C را به عنوان برده با آدرس مشخص متصل میکند.
پارامترها
Address: آدرس ۷ بیتی برده، اگر مشخص نشود، گذرگاه به عنوان ارباب متصل میگردد.
(Wire.onReceive(handler: تابع کنترل کننده بوده و زمانی فراخوانی میشود که برده یک داده انتقالی از ارباب را دریافت کند.
مثال:
void setup() { Wire.begin(8); // join i2c bus with address #8 Wire.onReceive(receiveEvent); // register event Serial.begin(9600); // start serial for output } void receiveEvent (int howmany){ while (1 < Wire.available()) { // loop through all but the last char c = Wire.read(); // receive byte as a character Serial.print(c); // print the character } }
(Wire.onRequest (handler: یک تابع کنترل کننده است که زمانی که ارباب از برده درخواستی میکند فراخوانی میشود، هیچ پارامتری دریافت نکرده و هیچ چیزی برنمیگرداند.
مثال:
void setup() { Wire.begin(8); // join i2c bus with address #8 Wire.onRequest(requestEvent); // register event } void loop() { delay(100); } // function that executes whenever data is requested by master // this function is registered as an event, see setup () void requestEvent() { Wire.write("hello "); // respond with message of 6 bytes // as expected by master }
دیاگرام اتصالات
ارتباط I2C بین دو آردوینو
داده را از ارباب به برده انتقال میدهیم. در اینجا، از دو آردوینو به عنوان ارباب و برده استفاده میکنیم.
از مثال نمونهی کتابخانه Wire که آردوینو تدارک دیده و IDE استفاده کرده و ارتباط I2C را برقرار میکنیم.
از کتابخانه Wire، از master_writer به عنوان آردوینو ارباب و slave_receiver به عنوان آردوینو برده استفاده میکنیم. این مثال اعداد را از ارباب به برده منتقل کرده و برده آن را روی مانیتور سریال نمایش میدهد.
میتوان به کتابخانه از طریق زیر دسترسی پیدا کرد.
- File -> Examples -> Wire -> master_writer
File -> Examples -> Wire -> master_receiver
اسکچ برای آردوینو به عنوان master writer
// Wire Master Writer // by Nicholas Zambetti <http://www.zambetti.com> // Demonstrates use of the Wire library // Writes data to an I2C/TWI slave device // Refer to the "Wire Slave Receiver" example for use with this // Created 29 March 2006 // This example code is in the public domain. #include <Wire.h> void setup() { Wire.begin(); // join i2c bus (address optional for master) } byte x = 0; void loop() { Wire.beginTransmission(8); // transmit to device #8 Wire.write("x is "); // sends five bytes Wire.write(x); // sends one byte Wire.endTransmission(); // stop transmitting x++; delay(500); }
اسکچ برای آردوینو به عنوان Slave receiver
// Wire Slave Receiver // by Nicholas Zambetti <http://www.zambetti.com> // Demonstrates use of the Wire library // Receives data as an I2C/TWI slave device // Refer to the "Wire Master Writer" example for use with this // Created 29 March 2006 // This example code is in the public domain. #include <Wire.h> void setup() { Wire.begin(8); // join i2c bus with address #8 Wire.onReceive(receiveEvent); // register event Serial.begin(9600); // start serial for output } void loop() { delay(100); } // function that executes whenever data is received from master // this function is registered as an event, see setup() void receiveEvent(int howMany) { while (1 < Wire.available()) { // loop through all but the last char c = Wire.read(); // receive byte as a character Serial.print(c); // print the character } int x = Wire.read(); // receive byte as an integer Serial.println(x); // print the integer }
خروجی مانیتور سریال آردوینو برده
ارتباط دو سیمه بین دو آردوینو با استفاده از I2C
میخواهیم برنامهای بنویسیم که یک پیام Hello را به برده ارسال کرده و برده نیز پیام را با Hi پاسخ میدهد. از دو آردوینو Uno به عنوان ارباب و برده استفاده میشود.
اسکچ برای ارباب
#include <Wire.h> void setup() { Serial.begin(9600); /* begin serial comm. */ Wire.begin(); /* join i2c bus as master */ Serial.println("I am I2C Master"); } void loop() { Wire.beginTransmission(8); /* begin with device address 8 */ Wire.write("Hello Slave"); /* sends hello string */ Wire.endTransmission(); /* stop transmitting */ Wire.requestFrom(8, 9); /* request & read data of size 9 from slave */ while(Wire.available()){ char c = Wire.read();/* read data received from slave */ Serial.print(c); } Serial.println(); delay(1000); }
اسکچ برای برده
#include <Wire.h> void setup() { Wire.begin(8); /* join i2c bus with address 8 */ Wire.onReceive(receiveEvent); /* register receive event */ Wire.onRequest(requestEvent); /* register request event */ Serial.begin(9600); /* start serial comm. */ Serial.println("I am I2C Slave"); } void loop() { delay(100); } // function that executes whenever data is received from master void receiveEvent(int howMany) { while (0 <Wire.available()) { char c = Wire.read(); /* receive byte as a character */ Serial.print(c); /* print the character */ } Serial.println(); /* to newline */ } // function that executes whenever data is requested from master void requestEvent() { Wire.write("Hi Master"); /*send string on request */ }
خروجی مانیتور سریال ارباب
خروجی مانیتور سریال برده
- منبع: ترجمه از سایت electronicwings.com
امیدوارم آموزش I2C در آردوینو براتون مفید واقع شده باشه. کامنت یادتون نره:)
اگر این نوشته برایتان مفید بود لطفا کامنت بنویسید.