I2C یا SPI یا UART؟ راهنمای انتخاب پروتکل مناسب برای هر پروژه

I2C، SPI و UART چیست؟ سه زبان اصلی ارتباط بین میکروکنترلر، سنسور، نمایشگر و ماژولها را ساده اما عمیق یاد بگیریم
وقتی ESP32، Arduino یا هر میکروکنترلری را به سنسور، نمایشگر، حافظه یا ماژول GPS وصل میکنیم، قطعات باید با یک «قانون مشترک» با هم حرف بزنند. I2C، SPI و UART سه روش بسیار رایج برای همین کار هستند. در این آموزش نهفقط اسم پایهها، بلکه منطق پشت Clock، Address، ACK، Baud Rate، Chip Select و انتخاب پروتکل مناسب را قدمبهقدم یاد میگیریم.
I2C شبیه یک کلاس است که همه روی یک خط مشترکاند و هر نفر شماره دارد؛ SPI شبیه گفتوگوی خیلی سریع با یک زنگ مشترک است؛ UART هم شبیه دو نفر است که بدون زنگ، فقط از قبل روی سرعت حرفزدن توافق کردهاند.
اول: ارتباط سریال یعنی چه؟
فرض کنید میخواهیم عدد 10110110 را از یک میکروکنترلر به یک سنسور یا نمایشگر بفرستیم. در ارتباط سریال، بیتها یکی پس از دیگری روی یک یا چند خط حرکت میکنند.
نکته اصلی این است که دو طرف باید بدانند هر بیت چه زمانی معتبر است، شروع و پایان پیام کجاست و داده متعلق به کدام دستگاه است. I2C، SPI و UART هرکدام این مسئله را به روش متفاوتی حل میکنند.
Clock مشترک + Address
دو خط اصلی بین همه دستگاهها مشترکاند و دستگاهها با آدرس شناخته میشوند.
Clock مشترک + Select
ارتباط سریع و همزمان ارسال/دریافت؛ هر Client معمولاً یک خط Select دارد.
بدون Clock مشترک
هر دو طرف از قبل روی Baud Rate و ساختار Frame توافق میکنند.
I2C چیست؟
I2C مخفف Inter-Integrated Circuit است. این باس برای ارتباط بین ICها طراحی شده و در حالتهای معمول فقط دو خط اصلی دارد:
طبق مشخصات NXP، I2C یک باس دو سیمه با SDA و SCL است و دستگاهها میتوانند با آدرس نرمافزاری روی همان باس شناخته شوند. نسخه جاری مشخصات NXP در Rev. 7.0 از اصطلاحهای Controller و Target استفاده میکند.
چرا I2C فقط با دو سیم میتواند چند دستگاه را کنترل کند؟
چون هر Target معمولاً یک Address دارد. Controller ابتدا آدرس دستگاه موردنظر را روی باس میفرستد؛ فقط همان دستگاه پاسخ میدهد.
Controller
این آدرسها فقط مثال آموزشی هستند؛ آدرس واقعی هر قطعه را باید از دیتاشیت همان قطعه بررسی کنید.
I2C چقدر سریع است؟
*Ultra Fast-mode حالت یکطرفه خاصی است و با I2C معمول دوطرفه تفاوتهایی دارد. برای بیشتر پروژههای Arduino و ESP32، سرعتهای 100kHz و 400kHz بسیار رایجترند.
یک پیام I2C از چه قسمتهایی ساخته میشود؟
START چیست؟
Controller با یک وضعیت مشخص روی SDA و SCL اعلام میکند: «از اینجا یک انتقال جدید شروع میشود.»
Address و R/W چیست؟
در آدرسدهی رایج 7 بیتی، Controller آدرس Target را میفرستد و مشخص میکند عملیات Read است یا Write. I2C همچنین آدرسدهی 10 بیتی را تعریف میکند، ولی 7 بیتی در پروژههای معمول بسیار رایجتر است.
ACK و NACK چیست؟
بعد از هر Byte، یک بیت نهم برای پاسخ وجود دارد. اگر Receiver داده را پذیرفته باشد، معمولاً با ACK پاسخ میدهد. NACK میتواند معنای «پاسخ ندادم / داده بیشتری نمیخواهم / دستگاه حاضر نیست» داشته باشد؛ معنای دقیق به موقعیت Frame بستگی دارد.
Repeated START چیست؟
Controller میتواند بدون آزاد کردن باس با STOP، یک START دوباره ایجاد کند. این قابلیت در خواندن Registerها بسیار مهم است: ابتدا شماره Register نوشته میشود و سپس جهت ارتباط به Read تغییر میکند.
چرا I2C به مقاومت Pull-up نیاز دارد؟
SDA و SCL در I2C معمولاً بهصورت Open-drain/Open-collector کار میکنند: دستگاهها خط را به LOW میکشند، ولی HIGH شدن خط توسط Pull-up انجام میشود.
مقدار Pull-up یک عدد جادویی ثابت نیست. ولتاژ، ظرفیت باس، سرعت I2C و توان Pull-down دستگاهها روی انتخاب آن اثر دارند. به همین دلیل 4.7kΩ یک مقدار رایج آموزشی است، اما همیشه «مقدار درست» نیست.
Clock Stretching چیست؟
بعضی Targetها میتوانند SCL را برای مدتی LOW نگه دارند و به Controller بگویند: «هنوز آماده نیستم.» این قابلیت Clock Stretching نام دارد و در مشخصات I2C وجود دارد، هرچند همه Controllerها و کتابخانهها آن را به یک شکل پشتیبانی نمیکنند.
SPI چیست؟
SPI یا Serial Peripheral Interface یک ارتباط سریال سنکرون است که برای ارتباط کوتاهبرد و سریع بین تجهیزات Embedded بسیار استفاده میشود.
در نامگذاری جدید Microchip از Host/Client استفاده میشود. MOSI و MISO اصطلاحهای بسیار رایجی هستند، اما در بعضی دیتاشیتهای جدید ممکن است نامهای دیگری مثل SDO/SDI یا COPI/CIPO هم ببینید.
SPI چرا سریع است؟
SPI آدرسدهی I2C و ACK بعد از هر Byte را ذاتاً ندارد و برای ارسال و دریافت خطوط جدا دارد. در ساختار معمول Full-duplex، همزمان که یک بیت روی MOSI خارج میشود، یک بیت از MISO وارد میشود.
چند Client را چطور وصل کنیم؟
MOSI، MISO و SCK معمولاً مشترکاند، اما هر Client یک SS/CS جدا میگیرد.
نتیجه این است که اضافه کردن Clientهای بیشتر در SPI میتواند GPIO بیشتری برای Chip Select مصرف کند.
SPI Mode چیست؟ CPOL و CPHA را خیلی ساده بفهمیم
دو طرف باید روی این موضوع توافق داشته باشند که Clock در حالت Idle چه سطحی دارد و داده روی کدام لبه نمونهبرداری میشود. ترکیب این دو مفهوم چهار Mode معروف SPI را میسازد.
UART چیست؟
UART مخفف Universal Asynchronous Receiver/Transmitter است. کلمه مهم اینجا Asynchronous است: UART خط Clock جداگانه بین دو دستگاه ندارد.
برای اتصال ساده:
اگر Clock نداریم، Receiver از کجا میفهمد بیتها کجا هستند؟
دو طرف از قبل روی سرعت ارتباط یا Baud Rate توافق میکنند. Receiver لبه Start Bit را پیدا میکند و سپس بر اساس Timing داخلی خودش بیتها را نمونهبرداری میکند.
Baud Rate و 8N1 چیست؟
یکی از تنظیمات بسیار رایج UART مثلاً این است:
Frame UART چگونه است؟
UART میتواند Parity اختیاری داشته باشد و تعداد Data/Stop Bit بسته به سختافزار قابل تنظیم است. نکته مهم این است که فرستنده و گیرنده باید تنظیمات سازگار داشته باشند.
UART با RS-232 و RS-485 یکی است؟
خیر. UART روش قالببندی و جابهجایی سریال داده در سطح منطقی است. RS-232 و RS-485 بیشتر درباره لایه الکتریکی/فیزیکی انتقال صحبت میکنند. مثلاً خروجی UART یک MCU را نباید بدون Driver مناسب مستقیماً به پورت واقعی RS-232 قدیمی وصل کرد.
مقایسه کامل I2C، SPI و UART
| ویژگی | I2C | SPI | UART |
|---|---|---|---|
| Clock مشترک | دارد | دارد | ندارد |
| خطوط پایه معمول | SDA + SCL | SCK + MOSI + MISO + CS | TX + RX |
| چند دستگاه روی باس | خیلی مناسب | ممکن، با CSهای بیشتر | معمولاً Point-to-Point |
| روش انتخاب دستگاه | Address | Chip Select | معمولاً لینک مستقیم |
| Full Duplex | خیر، SDA مشترک دوطرفه | معمولاً بله | بله با TX/RX مستقل |
| ACK داخلی پروتکل | دارد | ذاتاً ندارد | ذاتاً ندارد |
| Pull-up ویژه باس | معمولاً لازم است | معمولاً نه | معمولاً نه |
| پیچیدگی سیمکشی چند Device | کم | بیشتر | برای هر لینک جدا |
| کاربرد نمونه | Sensor / OLED / RTC | TFT / Flash / ADC | GPS / Debug / Modem |
کدام پروتکل سریعتر است؟
اگر فقط یک پاسخ بسیار کلی بخواهیم، SPI در بسیاری از پروژههای Embedded برای Throughput بالا انتخاب رایجی است. اما مقایسه «سرعت پروتکل» بدون دیتاشیت دقیق میتواند گمراهکننده باشد.
کدام را برای پروژه خودمان انتخاب کنیم؟
یک راهنمای خیلی سریع
مثال عملی با ESP32 / Arduino
این مثالها برای فهم API هستند؛ پایهها و Address/Mode واقعی را با برد و دیتاشیت خودتان تطبیق دهید.
مثال I2C: اسکن آدرسها
#include <Wire.h>
void setup() {
Serial.begin(115200);
Wire.begin();
Serial.println("I2C Scan:");
for (uint8_t address = 1; address < 127; address++) {
Wire.beginTransmission(address);
uint8_t error = Wire.endTransmission();
if (error == 0) {
Serial.print("Device found at 0x");
if (address < 16) Serial.print("0");
Serial.println(address, HEX);
}
}
}
void loop() {
}Scanner به شما کمک میکند ببینید چه Addressهایی روی باس ACK میدهند. اگر هیچ دستگاهی پیدا نشد، تغذیه، GND، SDA/SCL و Pull-upها را بررسی کنید.
مثال SPI: انتقال یک Byte
#include <SPI.h>
const int CS_PIN = 5;
void setup() {
Serial.begin(115200);
pinMode(CS_PIN, OUTPUT);
digitalWrite(CS_PIN, HIGH);
SPI.begin();
}
void loop() {
SPI.beginTransaction(SPISettings(1000000, MSBFIRST, SPI_MODE0));
digitalWrite(CS_PIN, LOW);
uint8_t received = SPI.transfer(0xA5);
digitalWrite(CS_PIN, HIGH);
SPI.endTransaction();
Serial.println(received, HEX);
delay(1000);
}مثال UART: ارسال پیام
void setup() {
Serial.begin(115200);
}
void loop() {
Serial.println("Hello from MAKATRONIC98");
delay(1000);
}سطح ولتاژ را فراموش نکنید
پروتکل صحیح به معنی ولتاژ صحیح نیست. یک ESP32 معمولاً منطق 3.3V دارد و یک ماژول دیگر ممکن است 5V یا 1.8V باشد.
در I2C این موضوع حساستر هم میشود چون Pull-up تعیین میکند سطح HIGH باس به چه ولتاژی بالا برود. Level Shifterهای مناسب I2C برای اتصال دامنههای ولتاژ متفاوت استفاده میشوند.
خطاهای رایج هر پروتکل
- Pull-up فراموش شده
- Address اشتباه
- SDA و SCL جابهجا
- ظرفیت باس زیاد
- Level Voltage نامناسب
- Clock Stretching ناسازگار
- CS اشتباه
- SPI Mode اشتباه
- Clock بیش از حد
- MOSI/MISO جابهجا
- دو Client همزمان MISO را Drive میکنند
- سیم بلند و Signal Integrity ضعیف
- TX به TX وصل شده
- GND مشترک نیست
- Baud Rate متفاوت
- Parity/Stop Bit متفاوت
- سطح ولتاژ اشتباه
- UART با RS-232 اشتباه گرفته شده
Logic Analyzer چطور به ما کمک میکند؟
Logic Analyzer یکی از بهترین ابزارها برای فهم و عیبیابی این پروتکلهاست. بهجای اینکه فقط ببینیم «کار نمیکند»، میتوانیم Timing و Byteهای واقعی روی سیم را ببینیم.
Decoder نرمافزار Logic Analyzer میتواند در I2C آدرس و ACK، در SPI Byteها، و در UART داده را با Baud Rate مشخص Decode کند.
آیا I2C از SPI بهتر است؟
سؤال «کدام بهتر است؟» معمولاً جواب مطلق ندارد. طراحی خوب یعنی پروتکل را بر اساس نیاز انتخاب کنیم:
اصطلاحات مهمی که باید حفظ باشیم
سه اشتباه مفهومی مهم
«I2C همیشه فقط دو سیم دارد»
از نظر سیگنال باس SDA و SCL دو خط اصلی هستند؛ اما در مدار واقعی تغذیه و GND هم وجود دارند و ممکن است Interrupt یا Reset جداگانه نیز بین ماژول و MCU داشته باشیم.
«SPI همیشه دقیقاً چهار سیم است»
ساختار رایج SCK/MOSI/MISO/CS است، اما بعضی کاربردها MISO ندارند، برخی دستگاهها چند Data Line دارند، و با چند Client تعداد CSها بیشتر میشود.
«UART همان Serial Monitor است»
Serial Monitor یک ابزار نرمافزاری است. UART Peripheral سختافزاری است که داده سریال Asynchronous را ایجاد یا دریافت میکند. روی بعضی بردها USB-to-UART بین کامپیوتر و MCU قرار دارد.
سؤالات متداول
برای سنسور، I2C بهتر است یا SPI؟
اگر سرعت خیلی بالا لازم ندارید و چند سنسور با سیم کم میخواهید، I2C اغلب راحتتر است. اگر سنسور SPI دارد و نرخ نمونهبرداری بالا مهم است، SPI میتواند مناسبتر باشد.
چرا I2C به Pull-up نیاز دارد؟
چون خطوط باس در حالتهای معمول توسط خروجیهای Open-drain به LOW کشیده میشوند و Pull-up مسئول بالا بردن خط به HIGH است.
آیا میتوان دو دستگاه I2C با آدرس یکسان وصل کرد؟
روی یک Bus معمولی، دو Target با آدرس یکسان همزمان قابل تفکیک نیستند؛ مگر Address قابل تغییر باشد یا از Multiplexer/Switch I2C استفاده کنید.
SPI حداکثر چه سرعتی دارد؟
یک سقف واحد برای همه SPIها وجود ندارد. حداکثر SCK را دیتاشیت Host و Client، کیفیت سیگنال و طراحی PCB مشخص میکنند.
چرا UART متن عجیب نشان میدهد؟
اول Baud Rate، Data Bits، Parity و Stop Bit را بررسی کنید. Baud اشتباه یکی از دلایل بسیار رایج نمایش کاراکترهای نامفهوم است.
TX را باید به RX وصل کنیم؟
در UART دو دستگاه معمولاً TX هر دستگاه به RX دستگاه مقابل وصل میشود و GND مشترک نیز لازم است.
کدام پروتکل برای OLED بهتر است؟
بستگی به خود نمایشگر دارد. OLEDهای کوچک زیادی با I2C عرضه میشوند؛ اگر سرعت Refresh بالاتر مهم باشد و مدل نمایشگر SPI داشته باشد، SPI میتواند گزینه مناسبتری باشد.
جمعبندی؛ سه پروتکل را با سه سؤال به یاد بسپارید
دو خط مشترک، چند دستگاه، ACK و Address.
Clock سریع، خطوط ارسال/دریافت جدا و Chip Select.
بدون Clock مشترک، TX/RX و Frame مبتنی بر Baud Rate.
اگر این سه سؤال در ذهنتان بماند، هنگام دیدن یک ماژول جدید خیلی سریع میتوانید ساختار ارتباطش را تشخیص دهید. بعد از آن فقط کافی است دیتاشیت همان قطعه را برای Pinout، سرعت، Address، Mode و Timing دقیق بخوانید.
منابع فنی
نکات I2C با Specification رسمی NXP، مباحث SPI با مستندات Microchip و قالب UART با راهنمای فنی Texas Instruments تطبیق داده شدهاند.