پروتکل SPI
اصول گذرگاه چهار سیمی SPI؛ پینهای MOSI و MISO و SCK و SS روی Uno، کتابخانه SPI و تابع transfer، مفهوم mode و سرعت کلاک و جدول مقایسهٔ کامل با I2C.
آنچه در این درس میآموزید
- چهار خط SPI و نقش هر کدام را توضیح دهید و سیمکشی را روی Uno انجام دهید
- با کتابخانه SPI و تابع transfer بایت بفرستید و بگیرید
- نقش خط CS/SS و الزام خروجیبودن آن را درک کنید
- بر اساس جدول مقایسه، بین I2C و SPI انتخاب درست بکنید
فهرست مطالب
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 یعنی «بنویس» و بایت بعدی مقدار ۰ تا ۱۲۸ است):
#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);
}توضیح خطبهخط:
digitalWrite(CS_PIN, LOW)دستگاه را بیدار میکند؛ همهٔ بایتهای بعدی فقط برای او معنا دارند.- دو بار
SPI.transferپشتهم دو بایت فرمان را میفرستد؛ SPI نه پارامتر آدرس میخواهد نه بستهبندی — بایتها بهترتیب میروند. HIGHکردن CS پایان گفتوگو است؛ MCP4131 در همین لبه مقدار جدید را روی مقاومتش اعمال میکند.- الگوی «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:
#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 — و میبینید این گذرگاهها روی چه زیربنایی سوارند.