آردوینومتوسط۸ دقیقه مطالعهArduino IDE 2.x / Uno R3

پروتکل SPI

اصول گذرگاه چهار سیمی SPI؛ پین‌های MOSI و MISO و SCK و SS روی Uno، کتابخانه SPI و تابع transfer، مفهوم mode و سرعت کلاک و جدول مقایسهٔ کامل با I2C.

آنچه در این درس می‌آموزید

  • چهار خط SPI و نقش هر کدام را توضیح دهید و سیم‌کشی را روی Uno انجام دهید
  • با کتابخانه SPI و تابع transfer بایت بفرستید و بگیرید
  • نقش خط CS/SS و الزام خروجی‌بودن آن را درک کنید
  • بر اساس جدول مقایسه، بین I2C و SPI انتخاب درست بکنید
نویسنده: تیم داکنامه · بازبینی: ۲۰۲۶-۱۰-۳۱
فهرست مطالب
پیش‌نیاز: پروتکل I2C

I2C دو سیم می‌خواست و از آدرس برای تفکیک دستگاه‌ها استفاده می‌کرد؛ اما هر بیت آدرس و هر قفل‌وتشریفات پروتکل، سرعت را کم می‌کند. وقتی داده سنگین است — تصویر روی نمایشگر، خواندن کارت حافظه، فریم‌های ماژول RFID — سرعت مهم‌تر از صرفه‌جویی در سیم است. اینجا «گذرگاه SPI» (Serial Peripheral Interface) وارد می‌شود: چهار سیم، بدون آدرس روی خط و با سرعتی چند برابر I2C. کارت‌های SD، نمایشگرهای رنگی و ماژول‌های RFID مثل RC522 همه روی همین گذرگاه کار می‌کنند.

SPI چطور کار می‌کند؟

SPI چهار خط دارد:

خط نام کامل نقش
MOSI Master Out, Slave In مستر می‌فرستد، اسلیو می‌گیرد
MISO Master In, Slave Out اسلیو می‌فرستد، مستر می‌گیرد
SCK Serial Clock ساعت؛ مستر ضرب می‌کند
SS/CS Slave Select / Chip Select انتخاب دستگاه؛ فعال‌شدن با سطح LOW

چون خط آدرس وجود ندارد، تفکیک دستگاه‌ها با خط CS انجام می‌شود: هر اسلیو خط CS خودش را دارد. مستر CS یک دستگاه را LOW می‌کند، با آن حرف می‌زند و بعد HIGH؛ بقیه اسلیوها در همین مدت ساکت می‌مانند. پس «یک دستگاه = یک خط CS اضافه» و همین است که سیم‌کشی دستگاه‌های زیاد را پرهزینه‌تر از I2C می‌کند. در عوض دو خط داده مستقل دارید: ارسال و دریافت هم‌زمان — به این خاصیت «دوطرفهٔ کامل» (Full Duplex) می‌گویند.

پین‌های SPI روی Uno

خط SPI پین Uno
MOSI D11
MISO D12
SCK D13
SS D10

کتابخانه SPI

کتابخانهٔ SPI همراه هسته است. توابع اصلی:

  • SPI.begin() — فعال‌سازی سخت‌افزار SPI و پین‌های ثابت.
  • SPI.transfer(byte) — یک بایت می‌فرستد و هم‌زمان بایت ورودی از اسلیو را برمی‌گرداند؛ در SPI ارسال و دریافت در یک عمل انجام می‌شود.
  • SPI.beginTransaction(SPISettings(speed, order, mode)) و SPI.endTransaction() — تنظیم سرعت و حالت برای یک گفت‌وگوی تمیز و ایمن نسبت به وقفه‌ها.

دو پارامتر SPISettings را مختصر بشناسید: «سرعت کلاک» (تا ۸ مگاهرتز روی Uno) و «حالت» (Mode) که تعیین می‌کند لبهٔ کلاک و سیگنال داده با هم چه رابطه‌ای دارند. هر دیتاشیت اسلیو، حالت درست خودش را نوشته — مثلاً RC522 با حالت ۰ کار می‌کند — و کتابخانهٔ اختصاصی ماژول معمولاً این تنظیمات را خودش انجام می‌دهد؛ این درس به مفهوم بسنده می‌کند و رجیسترنویسی را به منابع رسمی می‌سپارد.

یک انتقال حداقلی

مثال زیر با یک دیجیتال پتانسیومتر MCP4131 کار می‌کند — قطعهٔ ارزان و رایج که مقاومتش را با دستور دیجیتال عوض می‌کنید (دیتاشیت Microchip: دستور 0x02 یعنی «بنویس» و بایت بعدی مقدار ۰ تا ۱۲۸ است):

mcp4131-minimal.ino
#include <SPI.h>

const int CS_PIN = 10;

void setResistance(byte value) {
  digitalWrite(CS_PIN, LOW);   // Select the chip
  SPI.transfer(0x02);          // Command: write to wiper
  SPI.transfer(value);         // Wiper position 0..128
  digitalWrite(CS_PIN, HIGH);  // Release the chip
}

void setup() {
  pinMode(CS_PIN, OUTPUT);
  digitalWrite(CS_PIN, HIGH);  // Keep the chip unselected at boot
  SPI.begin();
  Serial.begin(9600);
  Serial.println("Ready");
}

void loop() {
  setResistance(0);    // Minimum resistance
  delay(1000);
  setResistance(128);  // Maximum resistance
  delay(1000);
}

توضیح خط‌به‌خط:

  1. digitalWrite(CS_PIN, LOW) دستگاه را بیدار می‌کند؛ همهٔ بایت‌های بعدی فقط برای او معنا دارند.
  2. دو بار SPI.transfer پشت‌هم دو بایت فرمان را می‌فرستد؛ SPI نه پارامتر آدرس می‌خواهد نه بسته‌بندی — بایت‌ها به‌ترتیب می‌روند.
  3. HIGHکردن CS پایان گفت‌وگو است؛ MCP4131 در همین لبه مقدار جدید را روی مقاومتش اعمال می‌کند.
  4. الگوی «LOW، انتقال‌ها، HIGH» الگوی همیشگی هر تراکنش SPI است؛ در هر کتابخانهٔ SPI (کارت SD، RC522، نمایشگر TFT) دقیقاً همین را در زیر کلاه خواهید دید.

خروجی سریال مانیتور فقط پیام آماده‌باش است؛ خود عملکرد روی مقاومت مدار (مثلاً روشنایی یک LED متصل به وایپر) دیده می‌شود:

خروجی کد

Ready

I2C یا SPI؟

ویژگی I2C SPI
تعداد خطوط ۲ (SDA، SCL) ۴ + یک خط CS برای هر دستگاه
تفکیک دستگاه‌ها آدرس روی خط خط CS جداگانه
جهت داده نیم‌دوطرفه در هر لحظه دوطرفهٔ کامل
سرعت روی Uno تا حدود ۱۰۰ کیلوهرتز در حالت استاندارد تا ۸ مگاهرتز
تعداد دستگاه زیاد ارزان: همه روی دو سیم پرهزینه: هر دستگاه یک CS
کاربردهای معمول LCD، ساعت RTC، سنسورهای محیطی کارت SD، نمایشگر TFT، RFID، حافظه‌های سریع

قاعدهٔ عملی: دستگاه‌های کم‌داده و متعدد با I2C، دستگاه‌های پرحجم‌داده با SPI. خیلی از ماژول‌ها هر دو را دارند (DS3231 هم I2C دارد)؛ انتخاب با نقشهٔ پین‌های آزاد پروژه شماست.

اشتباهات رایج و عیب‌یابی

نشانه علت رایج راه‌حل
دستگاه اصلاً جواب نمی‌دهد جابه‌جایی MOSI و MISO خطوط را چک کنید: MOSI به ورودی دادهٔ اسلیو و MISO به خروجی آن
ارتباط گاه‌به‌گاه می‌افتد CS نوسانی یا سیم‌های بلند CS را OUTPUT و در حالت عادی HIGH نگه دارید؛ سیم‌ها را کوتاه کنید
مستر خودش اسلیو می‌شود و ساکت است پین SS (D10) به‌صورت ورودی رها شده pinMode(10, OUTPUT); در setup
داده درست می‌رسد اما معنا ندارد حالت (Mode) اشتباه بین مستر و اسلیو حالت درست را از دیتاشیت اسلیو بگیرید؛ کتابخانهٔ اختصاصی معمولاً تنظیمش می‌کند
ماژول کار می‌کند اما ناپایدار تغذیهٔ ناکافی ماژول‌های پرجریان مثل RC522 تغذیهٔ مستقیم و پرنویز پایدار از 3.3V یا 5V طبق دیتاشیت بدهید

تمرین‌ها

تمرین

تمرین ۱ — مَحو شدن با دیجیتال پتانسیومتر

تابع setResistance در اسکچ mcp4131-minimal را حفظ کنید و loop را طوری تغییر دهید که مقاومت مثل درس PWM به‌نرمی از ۰ تا ۱۲۸ و برگشت برود؛ هر پله ۲۰ میلی‌ثانیه.

نمایش راه‌حل

دو حلقهٔ رفت‌وبرگشت روی مقدار وایپر، مثل حلقه‌های fade:

mcp4131-fade.ino
#include <SPI.h>

const int CS_PIN = 10;

void setResistance(byte value) {
  digitalWrite(CS_PIN, LOW);
  SPI.transfer(0x02);
  SPI.transfer(value);
  digitalWrite(CS_PIN, HIGH);
}

void setup() {
  pinMode(CS_PIN, OUTPUT);
  digitalWrite(CS_PIN, HIGH);
  SPI.begin();
}

void loop() {
  for (int value = 0; value <= 128; value += 4) {
    setResistance(value);
    delay(20);
  }
  for (int value = 128; value >= 0; value -= 4) {
    setResistance(value);
    delay(20);
  }
}

هر setResistance یک تراکنش کامل SPI است: انتخاب، دو بایت، آزادسازی. اگر به خروجی وایپر یک LED با مقاومت سری ببندید، همان رفت‌وبرگشت نور درس PWM را می‌بینید — این بار با قطعه‌ای که روی گذرگاه فرمان می‌گیرد.

:::

خلاصه

  • SPI چهار خط دارد: MOSI و MISO برای داده، SCK برای ساعت و CS برای انتخاب دستگاه؛ مستر آردوینوست.
  • پین‌های SPI روی Uno ثابت‌اند: D11 و D12 و D13 و D10 برای SS؛ SS حتی بی‌استفاده باید OUTPUT بماند.
  • SPI.transfer ارسال و دریافت را هم‌زمان انجام می‌دهد و الگوی تراکنش همیشه «CS پایین، بایت‌ها، CS بالا» است.
  • سرعت و mode در SPISettings تنظیم می‌شود و مقدار درستشان از دیتاشیت اسلیو می‌آید.
  • I2C برای دستگاه‌های زیاد و کم‌داده، SPI برای داده‌های سنگین و سرعت بالا؛ جدول مقایسه راهنمای انتخاب است.

حالا هر دو گذرگاه اصلی را می‌شناسید؛ در درس بعدی از میکروکنترلرِ وسط برد سر در می‌آورید: حافظه‌ها، کلاک و معماری ATmega328P — و می‌بینید این گذرگاه‌ها روی چه زیربنایی سوارند.

منابع و ارجاع‌ها