در این مطلب قصد داریم پروتکل SPI و نحوه راه اندازی آن در آردوینو را بررسی کنیم.
کاربرد پروتکل SPI:
پروتکل SPI (Serial Peripheral Interface) یا رابط سریال تجهیزات جانبی، همان طور که از نام آن پیداست یک رابط از نوع سریال است که برای ارتباط برقرار کردن بین میکروکنترلر و تجهیزات و قطعات خارجی مانند انواع سنسورها مورد استفاده قرار میگیرد.
در ارتباط SPI از 4 سیم برای ارتباط استفاده میشود که اغلب در کاربردهای ساده از سیم چهارم استفاده نمیشود و ارتباط به صورت 3 سیمه است.
پایههای مورد استفاده در ارتباط SPI:
SCK : پایه مربوط به کلاک که توسط میکروکنترلر مستر ایجاد میشود.
MOSI : پایه مربوط به خروج داده از مستر و ورود داده به اسلیو
MISO : پایه مربوط به خروج داده از اسلیو و ورود داده به مستر
SS : از این پایه برای انتخاب اسلیو توسط مستر استفاده میشود (معمولا توسط ایجاد ولتاژ صفر). همان طور که پیش تر اشاره شد، این پایه در کاربردهای ساده که تنها یک مستر و یک اسلیو وجود دارد اغلب استفاده نمیشود (مگر این که در کاربردهای پیشرفته نیاز به همزمان سازی ارتباط بین مستر و اسلیو وجود داشته باشد).
و در طرف مستر توسط یک مقاومت بالاکش به تغذیه و در سمت اسلیو مستقیما به زمین وصل میشود.
نکته : سرعت ارتباط SPI در مقایسه با پروتکل I2C بیشتر است. در مورد این پروتکل در مطالب آینده توضیح میدهیم.
مفهوم مستر و اسلیو:
در ارتباط SPI از دو واژه مستر (master) و اسلیو (slave) به کرات نام برده میشود. اگر با درس مدارات منطقی و فلیپ فلاپها آشنایی داشته باشید، شاید این دو واژه برایتان آشنا باشد. در اینجا این دو واژه شباهت زیادی به فلیپ فلاپهای مستر و اسلیو دارد.
در هر ارتباط SPI در هر طرف ارتباط، باید حداقل یک میکروکنترلر مستر وجود داشته باشد. یکی از مهم ترین وظایف میکروکنترلر مستر، تولید پالس ساعت برای ایجاد امکان تبادل داده بر روی پایه SCK است.
مدهای عملکرد SPI:
در ارتباط SPI چهار نوع مد عملکرد وجود دارد که به ترتیب به نامهای Mode 0 (به صورت پیشفرض) تا Mode 4 نام گذاری میشوند. جزئیات عملکرد این مدها مربوط به نوع سطح سیگنال در وضعیت بی کاری (Idle) و وضعیت ارسال و دریافت داده و همچنین لبهی مورد استفاده (لبه بالا رونده و لبه پایین رونده) برای شروع ارتباط میباشد.
توابع SPI در آردوینو :
نکته: قبل از استفاده از این توابع، باید فایل هدر SPI.h را به برنامه اضافه کنید. در مورد نحوه استفاده از این توابع در ادامه توضیح میدهیم.
- begin() : از این تابع باید در شروع برنامه برای ایجاد ارتباط استفاده کنیم.
- setClockDivider(x) : توسط این تابع میتوانیم فرکانس کلاک ارتباط را نسبت به کلاک میکروکنترلر تعیین کنیم. عدد x مقداری است که فرکانس میکروکنترلر بر آن تقسیم میشود. به عنوان مثال اگر فرکانس برد 20MHz باشد، با نوشتن عبارت :
SPI.setClockDivider(4)
فرکانس 20MHz بر عدد 4 تقسیم شده و بر روی 5MHz تنظیم میشود.
اعداد مجاز برای استفاده عبارت اند از:
2,4,8,16,32,64,128
- transfer(val): توسط این تابع، میتوانیم به طور همزمان یک بایت (val) را ارسال کرده و یک بایت را از طرف مقابل دریافت کنیم.
- beginTransaction(x,y,z) : پارامتر x در این تابع تعیین کننده حداکثر فرکانس کلاک، پارامتر y تعیین کننده ترتیب ارسال بیتها (اول بیت پرارزشتر (MSB) یا اول بیت کم ارزشتر (LSB)) و پارامتر z تعیین کننده مد عملکرد SPI است که در مورد آن توضیح داده شد.
پیاده سازی عملی:
سخت افزار:
برای پیاده سازی عملی ارتباط SPI ، از دو برد Arduino UNO استفاده کرده و مطابق شکل به یکدیگر متصل میکنیم.
- (SS) : pin 10
- (MOSI) : pin 11
- (MISO) : pin 12
- (SCK) : pin 13
نکته : زمین دو برد مشترک است و باید به یکدیگر متصل شوند.
نرم افزار:
همان طور که توضیح داده شد، در هر ارتباط باید حداقل یک مستر وجود داشته باشد. در این پروژه قصد داریم یک برد را به عنوان مستر و یک برد را به عنوان اسلیو تعریف کنیم. (انتخاب مستر و یا اسلیو بودن تفاوتی ندارد)
کدهای زیر را بر روی برد مستر پروگرام کنید:
#include <SPI.h> void setup (void) { Serial.begin(115200); digitalWrite(SS, HIGH); SPI.begin (); SPI.setClockDivider(SPI_CLOCK_DIV8); } void loop (void) { char c; digitalWrite(SS, LOW); for (const char * p = "Melec.ir\r" ; c = *p; p++) { SPI.transfer (c); Serial.print(c); } digitalWrite(SS, HIGH); delay(2000); }
کدهای زیر را بر روی برد اسلیو پروگرام کنید:
#include <SPI.h> char buff [50]; volatile byte indx; volatile boolean process; void setup (void) { Serial.begin (115200); pinMode(MISO, OUTPUT); SPCR |= _BV(SPE); indx = ; // buffer empty process = false; SPI.attachInterrupt(); } ISR (SPI_STC_vect) { byte c = SPDR; if (indx < sizeof buff) { buff [indx++] = c; if (c == '\r') process = true; } } void loop (void) { if (process) { process = false; Serial.println (buff); indx= ; } }
در این برنامه از امکانات مختلفی مانند ارتباط USART و وقفه ارتباط SPI استفاده شده است.
امیدوارم این آموزش برایتان مفید بوده باشد.
منابع :
tutorialspoint.com