در دو جلسه قبلی، در مورد پروتکل USART و SPI توضیح دادیم و کدهایی ساده برای راه اندازی این پروتکل ها را در آردینو بررسی کردیم.
در این بخش در مورد سومین پروتکل پرکاربرد در دنیای میکروکنترلرها، یعنی پروتکل I2C توضیح دهیم.
در نگاه اول شاید I2C از دو پروتکل دیگر کمی پیچیده تر باشد اما قصد داریم به طور ساده روش کارکرد این پروتکل و راه اندازی آن در آردوینو را بررسی کنیم.
کاربرد پروتکل I2C :
پروتکل I2C Inter-integrated circuit یکی از انواع ارتباط سریال است که برای ارتباط برقرار کردن بین میکروکنترلرهای مختلف یا برای دریافت داده از سنسورهای پیشرفته دیجیتالی مورد استفاده قرار می گیرد.
از این پروتکل در مسافت های کوتاه (در حد فواصل روی PCB) استفاده می شود.
به عنوان مثال تعدادی از سنسورهای معروف که از این پروتکل استفاده می کنند عبارت است از : DS3231 ، LM75 ، ADXL345 ، انواع ماژول ها و…
مشخصات I2C :
- تعداد پایه های کم
- انعظاف پذیری بالا
- امکان اتصال 112 میکروکنترلر یا سنسور
- 10Kbit/s (سرعت کم) 100Kbit/s (سرعت استاندارد)
- مناسب برای مسافت های کوتاه، حداکثر فاصله ارتباط در حد چند متر
پایه های مورد استفاده در ارتباط :
در این ارتباط تنها از دو پایه برای دریافت و ارسال داده استفاده می شود که این مسئله در مقابل پروتکل هایی مانند SPI که حداقل از سه پایه برای ارتباط استفاده می کند، یک مزیت محسوب می شود.
SDA : پایه مربوط به ارسال و دریافت داده.
SCL : پایه مربوط به پالس ساعت برای همزمان کردن ارتباط بین فرستنده ها و گیرنده ها
نکته : ممکن است در سنسورها و ماژول های مختلف از اسامی متفاوتی برای پایه ها استفاده شود که در این مورد باید به دیتاشیت آن قطعه مراجعه شود.
در بردهای آردوینو : Uno, Pro Mini : A4 (SDA), A5 (SCL) Mega, Due : 20 (SDA), 21 (SCL) Leonardo, Yun : 2 (SDA), 3 (SCL)
مستر و اسلیو :
مشابه ارتباط SPI ، در این ارتباط نیز باید حداقل یک مستر و حداقل یک اسلیو وجود داشته باشد. از جمله مهم ترین وظایف مستر، تولید پالس ساعت بر روی پایه SCL و آدرس دهی اسلیوهای شبکه است.
شکل زیر ارتباط فیزیکی واحدهای اسلیو و مستر را نشان می دهد.
نکته مهم در این شکل، وجود مقاومت های پول آپ (بالاکش) برای خطوط SDA و SCL است که با توجه به مکانیزم طبقه خروجی واحد های I2C ، وجود این مقاومت ها لازم است. مقدار متداول برای این مقاومت ها 4.7K اهم است.
انواع روش های ارتباط I2C در آردوینو :
با توجه به این که در این پروتکل تنها از یک پایه برای ارسال و دریافت داده استفاده می شود، برای ایجاد ارتباط I2C دو حالت وجود دارد :
- مستر فرستنده، اسلیو گیرنده
- مستر گیرنده، اسلیو فرستنده
حالت اول، مستر فرستنده، اسلیو گیرنده :
در این حالت از توابع زیر برای ارتباط استفاده می شود : (قبل از استفاده از این توابع، باید فایل هدر Wire.h را به برنامه اضافه کنید)
- (begin(Address : در ارتباط I2C ، اسلیو ها باید دارای یک آدرس 7 بیتی باشند تا توسط مستر شناخته شوند. اگر این تابع را برای سمت مستر استفاده می کنیم نیازی به استفاده تعیین آدرس وجود ندارد ولی در سمت اسلیو باید در داخل پرانتز و به جای Address مقدار آدرس دلخواه را قرار دهیم.
- (beginTransmission(Address : از این تابع برای شروع ارتباط با اسلیوی که دارای آدرس Address می باشد استفاده میشود.
- (write(X : از این تابع برای ارسال داده مورد نظر (x) به سمت اسلیو استفاده می شود.
- endTransmission : از این تابع برای اتمام ارتباط استفاده می شود.
توابع مورد استفاده در اسلیو :
- (begin(Address : شروع ارتباط، تنظیم آدرس اسلیو بر روی Address
- (onReceive(M : توسط این تابع داده های دریافت شده را ذخیره سازی می کنیم.
- available : دریافت تعداد بایت های دریافت شده، از این تابع در تابع Wire.onReceive استفاده می شود.
مثال :
توسط ارتباط I2C ، یک عبارت رشته ای را توسط مستر ارسال کرده و در سمت اسلیو دریافت و در خروجی سریال چاپ کنید.
کد سمت مستر :
#include <Wire.h> void setup() { Wire.begin(); { short age = 0; void loop() { Wire.beginTransmission(2); Wire.write("age is = "); Wire.write(age); Wire.endTransmission(); delay(1000); }
کد سمت اسلیو :
#include <Wire.h> void setup() { Wire.begin(2); Wire.onReceive(receiveEvent); Serial.begin(9600); } void loop() { delay(250); } void receiveEvent(int howMany) { while (Wire.available()>1) { char c = Wire.read(); Serial.print(c); } }
حالت دوم، مستر گیرنده، اسلیو فرستنده :
در این حالت، مستر درخواست مورد نیاز خود را به اسلیو (توسط آدرس) ارسال می کند و در بایت های بعدی اسلیو داده های مورد نیاز مستر را ارسال می کند.
از توابع زیر برای این نوع ارتباط استفاده می شود :
- :(Wire.requestFrom(address,number of bytes از این تابع برای درخواست داده از اسلیو استفاده می شود. آرگومان اول این تابع آدرس اسلیو و آرگومان دوم آن تعداد بایت های مورد نیاز است. پس از ارسال این تابع، داده های ارسال شده توسط اسلیو توسط دو تابع () available و () wire.read بررسی و خوانده می شوند.
تابع مورد استفاده در سمت اسلیو :
- (onRequest(handler : از این تابع برای پاسخگویی به درخواست های اسلیو استفاده می شود.
مثال :
در طرف مستر، یک بایت را از اسلیو با آدرس 2 درخواست کنید و پس از دریافت، آن را در خروجی سریال چاپ کنید.
در طرف اسلیو، با هر بار درخواست مستر، تعداد درخواست رخ داده را به سمت مستر ارسال کند.
کد سمت مستر :
#include <Wire.h> { Wire.begin(); Serial.begin(9600); // start serial for output } void loop() { Wire.requestFrom(2, 1); while (Wire.available()) { char c = Wire.read(); Serial.print(c); } delay(500); }
کد سمت اسلیو :
#include <Wire.h> void setup() { Wire.begin(2); Wire.onRequest(requestEvent); } Byte x = 12; void loop() { delay(100); } void requestEvent() { Wire.write(x); x++; }
امیدوارم این بخش آموزشی برایتان مفید بوده باشد.
منبع :toturialspoint.com
اگر این نوشته برایتان مفید بود لطفا کامنت بنویسید.
بخش آموزشی نظیر ندارد.
سلام. از یک آردوینو مگا به عنوان مستر و چند آردوینو uno به عنوان slave استفاده کردم تا مقدار آنالوگ خوانده شده رو انتقال بدم به مستر. یعنی مستر اینجا گیرنده و اسلیو فرستنده است. موقعی که پاور یکی از اسلیوها رو قطع می کنم، متسر هنگ میکنه و دیگه اطلاعات رو نمی خونه. یعنی توی سریال مانیتور دیگه اطلاعاتی نمایش داده نمیشه و قفل میکنه. مشکل از کجاست و راه حلی براش دارین؟ چون پروتکل I2C یه شبکه هست و اگه قرار باشه با از کار افتادن یکی از نودها کل شبکه مختل بشه نمیشه ازش استفاده کرد…
در ضمن در آردوینو مگا مقاومت پول آپ داخلی برای I2C قرار داده شده، اما من برای اطمینان خارجی 4.7 کیلو هم برای هر دو خط sda , scl هم گذاشتم . در هر دو صورت فرقی نکرد و این هنگ بودن اتفاق می افتاد.
سلام من دوتا ماژول دارم هردو تا را میتونم به یک اردوینو(ارتباط i2c) وصل کنم؟
سلام، بله
سلام. خواهش ميكنم شما ديگه جواب بديد لطفا
در دوسايت اين سوال رو مطرح كردم فقط گفتن ممنون بابت اشتراك گذاري نظرتون و تمام. ديگه كمكم نكردن
من يه ماژول دارم كه از پروتكل i2c استفاده ميكنه. تا الان تونستم 55سمپل در ثانيه ازش بگيرم كه بايد اين نرخ دوبرابر بشه. ميشم يكم كمكم كني؟