پروتکل رابطه وسایل جانبی در آردوینو (SPI)، یک رابط سریال است که از 4 سیم برای ارتباط بین میکروکنترلرها و تراشهها یا تجهیزات جانبی استفاده میکند. معمولا به جای 4 سیم از 3 سیم استفاده میشود. یک سیم برای دریافت داده، یک سیم برای ارسال داده، یک سیم برای همزمان سازی و یک سیم هم برای انتخاب تراشه برای شروع ارسال مورد استفاده قرار میگیرد. ارتباط SPI یک ارتباط تمام دو طرفه (full duplex) است به این معنا که به صورت همزمان هم میتوانیم داده ارسال کنیم و هم داده دریافت کنیم. حداکثر نرخ ارسال بیت یا باود ریت در این پروتکل از I2C بالاتر است.
پایههای SPI
در ارتباط SPI از 4 سیم به شرح زیر استفاده می شود :
- SCK : سیگنال کلاک که توسط مستر ایجاد میشود.
- MOSI : سیگنال خروجی از مستر و ورودی به اسلیو که توسط مستر ارسال میشود.
- MISO : سیگنال خروجی از اسلیو و ورودی به مستر که توسط مستر ارسال میشود.
- SS : سیگنال انتخاب اسلیو میباشد.
از توابع زیر برای ارتباط SPI استفاده میشود، قبل از آن نیز باید کتابخانه SPI.h به برنامه اضافه شود:
- ()begin : انجام تنظیمات اولیه SPI، تنظیم پایههای SCK ، MOSI و SS به حالت خروجی، صفر کردن پایههای SCK و MOSI ، یک کردن پایه SS
- (setClockDivider(divider : از این تابع برای تنظیم کلاک ارتباط SPI نسبت به کلاک اصلی میکروکنترلر استفاده میشود. در بردهای مبتنی بر AVR عدد divider میتواند مقادیر 2, 4, 8, 16, 32, 64 و 128 باشد. به صورت پیشفرض این عدد روی ثابت SPI_CLOCK_DIV4 تنظیم شده است که باعث میشود یک چهارم کلاک میکروکنترلر به ارتباط SPI اختصاص داده شود. (مثلا در بردهای با فرکانس میکروکنترلر 20MHz فرکانس SPI برابر 5MHz میشود.)
- Divider : برای این متغیر میتوان از یکی از ثباتهای زیر استفاده نمود:
SPI_CLOCK_DIV2, SPI_CLOCK_DIV4, SPI_CLOCK_DIV8, SPI_CLOCK_DIV16, SPI_CLOCK_DIV32, SPI_CLOCK_DIV64, SPI_CLOCK_DIV128
- (transfer(val: از این تابع برای ارسال و دریافت همزمان داده استفاده میشود. مقدار دریافت شده در متغیر receivedVal ذخیره سازی میشود.
- ((beginTransaction(SPISettings(speedMaximum, dataOrder, dataMode : متغیر speedMaximum برابر کلاک است، dataOrder (دارای دو حالت MSBFIRST یا LSBFIRST و dataMode (دارای چهار حالت SPI_MODE0, SPI_MODE1, SPI_MODE2, or SPI_MODE3)
برای ارتباط SPI 4 حالت داریم که عبارتاند از:
- Mode 0 : (حالت 0) (به صورت پیشفرض)
در این حالت کلاک به صورت عادی صفر است CPOL = 0 و از دادهها در لبه بالارونده سیگنال نمونه برداری میشود (لبه صعودی) (CPHA = 0) .
- Mode 1 : (حالت 1)
در این حالت کلاک به صورت عادی صفر است CPOL = 0 و از دادهها در لبه پایین رونده سیگنال نمونه برداری میشود (لبه نزولی) (CPHA = 1).
- Mode 2: (حالت 2)
در این حالت کلاک به صورت عادی یک است CPOL = 1 و از دادهها در لبه بالارونده سیگنال نمونه برداری میشود (لبه صعودی) (CPHA = 0).
- Mode 3: (حالت 3)
در این حالت کلاک به صورت عادی یک است CPOL = 1 و از دادهها در لبه پایین رونده سیگنال نمونه برداری میشود (لبه نزولی) (CPHA = 1).
- (attachInterrupt(handler : از این تابع در اسلیو برای دریافت دادههای ارسال شده از سمت مستر استفاده میشود.
حال میخواهیم دو برد آردوینو UNO را از طریق ارتباط SPI به یکدیگر وصل کنیم، یکی را به عنوان مستر و دیگری را به عنوان اسلیو تعریف میکنیم.
- (ss) : پایه 10
- (MOSI) : پایه 11
- (MISO) : پایه 12
- (SCK) : پایه 13
پایه زمین بین دو برد مشترک است. شکل زیر نحوه اتصال بین دو برد را نشان میدهد:
مثال زیر کدهای نمونه برای مستر و اسلیو را نشان میدهد:
SPI به عنوان مستر
مثال:
#include <SPI.h> void setup (void) { Serial.begin(115200); //set baud rate to 115200 for usart digitalWrite(SS, HIGH); // disable Slave Select SPI.begin (); SPI.setClockDivider(SPI_CLOCK_DIV8);//divide the clock by 8 } void loop (void) { char c; digitalWrite(SS, LOW); // enable Slave Select // send test string for (const char * p = "Hello, world!\r" ; c = *p; p++) { SPI.transfer (c); Serial.print(c); } digitalWrite(SS, HIGH); // disable Slave Select delay(2000); }
SPI به عنوان اسلیو
مثال:
#include <SPI.h> char buff [50]; volatile byte indx; volatile boolean process; void setup (void) { Serial.begin (115200); pinMode(MISO, OUTPUT); // have to send on master in so it set as output SPCR |= _BV(SPE); // turn on SPI in slave mode indx = 0; // buffer empty process = false; SPI.attachInterrupt(); // turn on interrupt } ISR (SPI_STC_vect) // SPI interrupt routine { byte c = SPDR; // read byte from SPI Data Register if (indx < sizeof buff) { buff [indx++] = c; // save data in the next index in the array buff if (c == '\r') //check for the end of the word process = true; } } void loop (void) { if (process) { process = false; //reset the process Serial.println (buff); //print the array on serial monitor indx= 0; //reset button to zero } }
خیلی ممنون از اینکه آموزش پروتکل رابطه وسایل جانبی در آردوینو (SPI) را با ما دنبال کردید.
منبع: میکرودیزاینرالکترونیک