منظور از پروتکل های ارتباطی ، پروتکل هایی مانند SPI ، I2C و … هستند . این پروتکل ها امکان ارتباط بین IC های مختلف و ماژول های مختلف را فراهم می کنند . اگر شما از آن دسته از افرادی هستید که از یادگیری دقیق پروتکل های ارتباطی طفره رفته و همیشه به سراغ کتابخانه های آماده رفته اید ، این آموزش مناسب شماست . اما چرا باید این ارتباط ها را یادبگیریم ؟ نکته مهم این است که شما هر چقدر بر موضوعات مختلف تسلط داشته باشید توانایی خلق و به اصتلاح هک کردن خود را بالا می برید . یادگیری پروتکل های ارتباطی نقش عصای موسی را در مهندسی الکترونیک و امبدد سیستم دارد ، شما با یادگیری این ارتباط ها توانایی راه اندازی هر سنسور و ماژولی را خواهید داشت . پس با یادگیری این پروتکل ها ، دردسر گشتن به دنبال کتابخانه های مختلف را یک بار برای همیشه حل کنید .
انواع پروتکل های ارتباطی
قبل از اینکه به هر چیز دیگری بپردازیم لازم است دسته بندی ها و کلیات این پروتکل های ارتباطیرا یادبگیریم .
در ابتدا دو دسته بندی اصلی برای پروتکل ها وجود دارد :
1- پروتکل های بیت گرا ( Bit-Oriented ) یا سریال :
در این نوع ارتباط دیتا به صورت بیت به بیت یا سریال بین دو ماژول منتقل می شود . اغلب پروتکل های مورد استفاده در امبدد سیستم ها از این نوع هستند مانند UART ، SPI ، I2C و غیره .
2- پروتکل های کاراکتر گرا ( Character Oriented ) یا موازی :
در این نوع از ارتباط داده ها به صورت بایت به بایت یا به صورت موازی منتقل می شوند . از این ارتباط در راه اندازی نمایشگر ها ، حافظه ها و سایر ماژول هایی که نیاز به سرعت بالا در ارتباط دارند استفاده می شود .
از نظر همزمانی ارتباط بین طرفین نیز کلیه ارتباط ها به سه دسته زیر تقسیم می شوند :
1- یک طرفه
2 – نیمه دو طرفه ( هر بار فقط یک طرف ارتباط حق ارسال دیتا دارد )
3- تمام دو طرفه
معرفی تمام دسته بندی ها خارج از حوصله این آموزش است و ما تنها به دنبال روش آسان و سریع برا یادگیری این پروتکل ها هستیم .
اما چگونه می توان خیلی ساده هر پروتکلی را یادگرفت ؟
جواب این سوال بسیار ساده است . کافیست یک بار پروتکلی را که می خواهیم یادبگیریم به صورت نرم افزاری اجرا کنیم 🙂 .
به طور مثال در اینجا ما می خواهیم پروتکل UART را بیاموزیم .
قدم اول مطالعه جزئیات پروتکل مورد نظر است ، در این مرحله تنها کاری که می کنیم جستجوی عنوان پروتکل در گوگل و مطالعه مستندات آن است !
با مطالعه در مورد UART متوجه شدیم که این یک ارتباط سریال غیر همزمان نیمه دو طرفه است که دیتا از طریق دو سیم منتقل می شود که یک TX مربوط به ارسال و دیگری RX مربوط به دریافت دیتا است . پین های RX و TX دو ماژولی که قصد ارتباط UART را دارند به صورت زیر به همدیگر متصل می شود .
اما قسمت مهم در یادیگری زمان بندی سیگنال ها است . با جستجوی UART signal timing به نتیجه زیر رسیدیم :
شکل واضح تر به صورت زیر است :
تصویر فوق بیانگر زمان بندی ارسال دیتا در ارتباط UART است که به صورت زیر است :
در حالت عادی یعنی زمانی که هیچ دیتایی برای ارسال نداریم ، پین TX برابر با یک است .
در ابتدای ارتباط باید یک سیگنال Start ارسال کنیم ، برای این کار پین TX را به اندازه یک دوره زمانی صفر میکنیم .
سپس بیت به بیت (از بیت D0) دیتا را بر روی TX قرار می دهیم .
در پایان باید بیت Stop را بفرستیم که برای این کار پین TX را به مدت یک دوره زمانی یک میکنیم .
در پایان برای آزاد گذاشتن خط باید آن را یک کنیم .
در این ارتباط دوره زمانی هر بیت باید مقدار مشخصی باشد ، این مقدار ها باید در دو طرف ارتباط از قبل تنظیم شده باشند ، به طور مثال هر دو طرف ارتباط می توانند روی یک نرخ ارسال 9600 بیت بر ثانیه تنظیم شوند ، اگر در طرف گیرنده این نرخ به اشتباه تنظیم شود دیتا به درستی دریافت نمی شود .
اجرای عملی UART نرم افزاری بر روی آردوینو :
حالا نوبت به اجرای مراحل قبلی هستیم . در واقع می خواهیم به صورت نرم افزاری و بیت به بیت ارتباط UART را بر روی آردوینو اجرا کنیم . فرض کنید می خواهیم کاراکتر ‘A’ را با نرخ 9600 بیت بر ثانیه ارسال کنیم . برای اینکه بتوایم دیتا را در ترمینال آردوینو IDE مشاهده کنیم ، همان پین TX سخت افزاری را به عنوان TX ارتباط خود قرار می دهیم . با توجه به نقشه برد آردوینو UNO پین D1 را به عنوان TX در نظر می گیرم :
پس قبل از هر کاری این پین را به عنوان خروجی تعریف می کنیم ، چون TX خروجی است :
void setup() {
pinMode(1,OUTPUT);
}
void loop() {
}
حال به سراغ ادامه کار می رویم ، گفتیم که نرخ ارتباط را 9600 بیت بر ثانیه در نظر گرفتیم ، این یعنی دوره زمانی هر بیت 1/9600 ثانیه است یعنی 104 میلی ثانیه . پس با قرار دادن هر بیت بر روی پین TX باید 104 میلی ثانیه صبر کنیم و سپس بیت بعدی را ارسال کنیم . دیتایی که ما می خواهیم ارسال کنیم کاراکتر ‘A’ است ، با سرچ ASCII Table در گوگل و مشاهده جدول کاراکتر های اسکی مقدار باینری حرف ‘A’ را پیدا می کنیم که برابر با 0b01000001 است . پس کاری که ما باید انجام بدهمی به صورت زیر است :
خط TX را به عنوان خروجی و در حالت یک قرار می دهیم .
به عنوان بیت استارت پین TX را صفر و به اندازه 104 میلی ثانیه صبر میکنیم
بیت D0 کاراتر ‘A’ را ارسال می کنیم ، یعنی TX را به مدت 104 میلی ثانیه یک میکنیم .
بیت D1 کاراتر ‘A’ را ارسال می کنیم ، یعنی TX را به مدت 104 میلی ثانیه صفر میکنیم .
بیت D2 کاراتر ‘A’ را ارسال می کنیم ، یعنی TX را به مدت 104 میلی ثانیه صفر میکنیم .
.
.
.
بیت D7 کاراتر ‘A’ را ارسال می کنیم ، یعنی TX را به مدت 104 میلی ثانیه صفر میکنیم .
در نهایت پین TX را به مدت 104 ثانیه یک میکنیم ، به عنوان بیت Stop .
,در نهایت خط TX را در همان حالت یک میگذاریم .
با انجام مراحل بالا کاراکتر ‘A’ از طریق پروتکل UART با بادریت 9600 ارسال خواهد ، خیلی ساده .
کد نهایی به صورت زیر خواهد شد :
void setup() {
pinMode(1,OUTPUT);
digitalWrite(1,HIGH);
}
void loop() {
digitalWrite(1,LOW);//------------->Start BIT
delayMicroseconds(104);
digitalWrite(1,HIGH);//------------>D0 BIT 1
delayMicroseconds(104);
digitalWrite(1,LOW);//------------->D1 BIT 0
delayMicroseconds(104);
digitalWrite(1,LOW);//------------->D2 BIT 0
delayMicroseconds(104);
digitalWrite(1,LOW);//------------->D3 BIT 0
delayMicroseconds(104);
digitalWrite(1,LOW);//------------->D4 BIT 0
delayMicroseconds(104);
digitalWrite(1,LOW);//------------->D5 BIT 0
delayMicroseconds(104);
digitalWrite(1,HIGH);//------------>D6 BIT 1
delayMicroseconds(104);
digitalWrite(1,LOW);//------------->D7 BIT 0
delayMicroseconds(104);
digitalWrite(1,HIGH);//------------>Stop BIT
delayMicroseconds(104);
delay(1000);
}
پس از آپلود کد بالا بر روی برد آردوینو ، از مسیر Tools وارد Serial Monitor شوید و در پایین پنجره همانند توصیر زیر Baud Rate را روی 9600 قرار دهید :
پس از این کار مشاهده خواهید کرد که هر یک ثانیه یک بار کاراکتر ‘A’ چاپ خواهد شد .
این تنها روشی ساده برای درک بهتر UART است ، برای دریافت دیتا همان کار بالا را انجام می دهید با ابن تفاوت که هر 104 میکرو ثانیه وضعیت پین RX را خوانده و بیت های D0 تا D7 یک متغییر را بر اساس ان تغییر می دهید . هدف از این آموزش ساده تر کردن یادگیری پروتکل های ارتباطی است . در آموزش های بعدی ارتباط I2C به طور کامل و ساده شرح داده خواهد شد . من از اینکه این آموزش مفید واقع شده باشد بسیار خوشحال خواهم شد . در صورت داشتن هر سوال و یا مشکلی در ارتباط با این اموزش می توانید کامنت بگذارید .