پروتکل RS232 یکی از پروتکلهای قدیمی اما در عین حال، پرکاربرد در صنایع مختلف است. از این پروتکل میتوان برای انتقال اطلاعات با سرعت کم و در فواصل متوسط استفاده کرد. با توجه به سادگی این پروتکل و عملکرد مناسب آن از لحاظ انتقال سالم اطلاعات، هنوز هم در بسیاری از کاربردهای صنعتی از پروتکل RS232 استفاده میشود.
More...
در این مقاله، نحوه پیادهسازی پروتکل RS232 به کمک FPGA را شرح میدهم و در مورد ملزومات پیادهسازی بخشهای مختلف آن توضیح میدهم. این یک پروژه بسیار کوچک است که میتواند اطلاعات بسیار مفیدی را در زمینه کدنویسی برای FPGA به شما منتقل کند.
برای استفاده هر چه بیشتر از این مطلب، پیشنهاد میکنم پس از مطالعه مقاله و بدون نگاه کردن به کد ارائه شده در آن، خودتان اقدام به نوشتن کد یک ماجول RS232 کنید. سپس کد ارائه شده در این مقاله و توضیحات آن را مطالعه کند و با کد خودتان مقایسه کند. این فرآیند، روش بسیار مناسبی برای افزایش مهارت کدنویسی و دستیابی به تسلط عملی برای کار با تراشههای FPGA است.
برای دانلود فایل PDF این مقاله، روی دکمه زیر کلیک کنید:
پروتکل RS232 چیست؟
وقتی با FPGA کار میکنید، حتما نیاز خواهید داشت با دنیای بیرون آن ارتباط برقرار کنید. مثلا دستورات یا پارامترهایی را از یک کامپیوتر یا یک برد دیگر به FPGA ارسال کنید، یا بعضی از نتایج محاسبه شده در FPGA را به کامپیوتر برای نمایش یا انجام محاسبات مورد نیاز ارسال کنید. برای این کار، نیاز به یک پروتکل ارتباطی دارید.
یکی از پروتکلهای ارتباطی که از گذشته مورد استفاده بوده و هنوز هم در خیلی از موارد میتواند انتخاب بهینه باشد، پروتکل RS232 است. به کمک این پروتکل میتوان با سرعتهایی در حد چند ده کیلوبیت بر ثانیه و به صورت پکتهایی شامل هشت بیت، دیتا را منتقل نمود.
ارتباط سریال RS232 برای انتقال دادهها در مسیرهای با طول متوسط و سرعت کم از گذشته مورد استفاده قرار میگرفته است. در حال حاضر هم بسیاری از وسایل جانبی در سیستمهای کنترلی و یا پردازشی از این پروتکل ساده اما کارآمد برای انتقال دادهها استفاده میکنند.
در یک ارتباط دوطرفه سریال، دو وسیله مطابق شکل زیر به تبادل دادهها میپردازند. در هر سمت، یک فرستنده و یک گیرنده RS232 وجود دارد. بین دو وسیله مورد نظر، حداقل سه سیم برای ارتباط وجود دارد. یکی برای انتقال داده از وسیله شماره ۱ به شماره ۲ و دیگری ارتباط در جهت عکس را فراهم میکند. یک سیم هم به عنوان زمین یا مرجع وجود دارد.

اصولا یکی از این دو وسیله Data Terminal Equipment یا DTE و دیگری Data Circuit-terminating Equipment یا DCE نامیده میشود. مثالی از DTE میتواند یک پورت کامپیوتر باشد و به عنوان مثالی برای DCE میتوان از مودم، چاپگر، حافظههای بیرونی و دیگر وسایل جانبی نام برد.
پورتهای سریال RS232 در دو اندازه ۹ پین (D-Type 9 pin connector) و ۲۵ پین وجود دارند. پورت در اندازه ۹ پین که بیشتر مورد استفاده قرار میگیرد در شکل زیر نشان داده شده است.


در این پورت ۹ پین که از دید DTE نشان داده شده است، پایه شماره ۲ برای دریافت دیتا (Rx) و پایه شماره ۳ برای ارسال دیتا (Tx) استفاده میشود. پایه شماره ۵ هم به عنوان پایه زمین (GND) استفاده میشود. اگر پورت ۹ پین را در سمت DCE در نظر بگیریم، جای پین Tx و پین Rx عوض میشوند و به ترتیب پین شماره ۲ و ۳ خواهند بود. پس کافیست پین شماره ۲ از یک وسیله DTE را به پین شماره ۲ از یک وسیله DCE و پین شماره ۳ از یک وسیله DTE را به پین شماره ۳ از وسیله DCE وصل کرد.
فرمت پکت ارسال در پروتکل RS232
موضوعی که آگاهی از آن برای طراحی و پیادهسازی این بلوک مورد نیاز است، فرمت پکت ارسال در پروتکل RS232 است. شکل زیر، یک پکت سریال RS232 را نشان میدهد. هر پکت یا بسته داده در ارتباط RS232 یک بایت را منتقل میکند.

همانطور که در شکل بالا دیده میشود، در زمانی که دادهای ارسال نمیشود، باید سطح منطقی یک روی خط ارسال قرار بگیرد. پس از شروع ارسال یک پکت، پکتی با مشخصات فوق باید در خروجی قرار بگیرد. این پکت از ۱۱ بیت تشکیل شده است. توجه کنید که هر پکت RS232، یک بایت دیتا را منتقل میکند.
بیت اول که مقدار آن صفر است Start Bit نامیده میشود و مشخص کننده شروع پکت است. هشت بیت مربوط به دیتا در ادامه قرار میگیرند. بیتهای دیتا به ترتیب از سبک به سنگین ارسال میشوند. در ادامه، بیت پریتی (Parity Bit) قرار میگیرد و در آخر، بیت Stop Bit که همواره یک است قرار گرفته و پایان یک پکت را مشخص میکند.
بیت پریتی
مقدار بیت پریتی برابر XOR همه بیتهای داده ورودی هستند. از این بیت به هنگام دریافت پکت در گیرنده و برای بررسی صحت داده دریافتی استفاده میشود. برای این کار، با توجه به اینکه مقدار این بیت برابر XOR تمام هشت بیت داده ورودی است، در گیرنده و پس از دریافت بایت مورد نظر، یک بار دیگر بیت پریتی بایت دریافتی را حساب نموده و آن را با بیت پریتی دریافتی مقایسه میکنند. در صورت مغایر بودن این دو مقدار، بایت دریافتی دارای اعتبار نخواهد بود و باید نادیده گرفته شود.
سرعت ارسال
آخرین موردی که در ساخت سیگنال پکت RS232 باید به آن توجه کنید، موضوع عرض هر بیت یا سرعت ارسال است. در پروتکل RS232 هرکدام از بیتهای دیتا، Stop، Start و پریتی دارای عرض زمانی مشخصی هستند. به عبارت دیگر، فرکانس ارسال بیتها در پروتکل RS232 مقادیر مشخصی هستند که باید از جانب طراح ماجول ارسال و دریافت RS232 مورد توجه قرار گیرد.
این فرکانس که در اصطلاح به آن baud rate گفته میشود، دارای چند مقدار مشخص است. بعضی از این مقادیر عبارتند از: ۹۶۰۰، ۳۸۴۰۰، ۵۷۶۰۰ و ۱۱۵۲۰۰ بیت بر ثانیه (bit per Second یا bps). مثلا استفاده از baud rate برابر با ۹۶۰۰bps به معنای عرض بیت برابر با ۱۰۴٫۱۶μs است.
پس پیادهساز ماجول فرستنده RS232 باید این موضوع را در نظر داشته باشد و عرض تمام بیتها را بر مبنای baud rate مورد نظر طراحی کند. مثلا اگر کلاک سیستم برابر با ۵۰MHz (پریود ۲۰ns) باشد، برای تولید عرض بیت ۱۰۴٫۱۶μs که منتاظر با baud rate برابر با ۹۶۰۰bps است باید هر بیت را با ۵۲۰۸ کلاک نشان دهیم چون: ۱۰۴٫۱۶μs/20ns=5208
پیادهسازی فرسنتده/گیرنده RS232
همانطور که در بخش قبلی هم اشاره کردم، یک ماجول کامل RS232 دارای دو بخش فرسنتده و گیرنده است. این دو بخش میتوانند به طور همزمان کار کنند و بنابراین، ارتباط RS232 یک ارتباط Full Duplex است. در این بخش، برای طراحی هر کدام از این دو ماجول، ایدههایی را مطرح میکنم.
فرستنده RS232
مثل همیشه، کار طراحی را با مشخص نمودن پورتهای مورد نیاز ماجول شروع کنید. وقتی پورتهای ماجول را طراحی میکنید، سعی کنید خودتان را جای کسی که میخواهد از ماجول شما استفاده کند قرار دهید و ببنید که او برای اینکه بتواند به راحتی از قابلیتهای ماجول شما استفاده کند، نیاز به چه پورتهایی دارد.
از آنجاییکه هر بسته ارسالی در پروتکل سریال RS232 یک بایت را منتقل میکند، باید بلوک فرستنده را به گونهای طراحی کنیم که در ورودی، یک بایت را دریافت کرده و در خروجی آن را به صورت سریال ارسال کند. بنابراین، حتما به یک پورت ورودی هشت بیتی برای دریافت دیتا و یک پورت تک بیتی برای ارسال دیتای سریال نیاز است. اسم پورت هشت بیتی برای ورودی دیتا را Data_In و اسم پورت سریال خروجی را Serial_Out میگذارم.
اما فردی که از ماجول فرستنده استفاده میکند باید بتواند به این ماجول اطلاع دهد که در چه لحظهای میخواهد ارسال را انجام دهد. بنابراین نیاز به یک ورودی داریم که بعد از قرار دادن دیتای هشت بیتی در ورودی مربوط به آن، فرمان ارسال را به ماجول اعمال کند. اسم این پورت را Send میگذارم. پیشنهاد میکنم پورتهای فرمان ورودی مثل Send را حساس به لبه بالارونده طراحی کنید.
از طرف دیگر، وقتی یک فرآیند ارسال آغاز شد، نباید فرمان ارسال دیگری صادر شود تا زمانیکه ارسال فعلی کامل شود. بنابراین، باید به استفاده کننده از ماجول اطلاع داد که ماجول در حال ارسال دیتا است و نمیتواند درخواست ارسال جدیدی داشته باشد. برای این منظور، یک پورت تک بیتی خروجی هم به ماجول اضافه میکنیم و قرارداد میکنیم که در لحظاتی که ماجول در حال ارسال دیتا است، این خروجی یک باشد و در لحظات دیگر برابر با صفر باشد. اسم این پورت را هم Busy میگذارم.
ماجول فرستنده باید به گونهای طراحی شود که اگر در زمانیکه ماجول Busy است، فرمان Send ارسال شود، مشکلی در عملکرد ماجول ایجاد نشود. شکل زیر، ماجول مورد نظر برای طراحی فرستنده RS232 در FPGA را نشان میدهد.

گیرنده RS232
برای طراحی پورتهای گیرنده هم باید به نیازمندیهای فردی که میخواهد از ماجول شما استفاده کند فکر کنید. اولین پورتی که برای این گیرنده لازم به نظر میرسد، یک ورودی سریال تک بیتی برای دریافت پکت سریال است. اسم این سیگنال را Serial_In میگذارم.
بعد از اینکه دیتای هشت بیتی موجود در پکت سریال دریافتی به طور موفقیتآمیز استخراج شد، باید آن را به خروجی ماجول گیرنده ارسال کرد. بنابراین، نیاز به یک خروجی هشت بیتی داریم که دیتای دریافتی را به آن ارسال کنیم. اسم Data_Out میتواند نام مناسبی برای این پورت باشد.
اما وقتی یک دیتای هشت بیتی از پکت دریافتی استخراج شد و در پورت Data_Out قرار داده شد، باید به استفاده کننده از ماجول هم خبر دهیم. بنابراین، نیاز به یک پورت خروجی تک بیتی داریم که همزمان با قرار دادن دیتای هشت بیتی در خروجی، به مدت یک کلاک برابر با یک شود. اسم این پورت را Valid میگذارم.
با این توضیحات، ماجول گیرنده RS232 هم به شکل زیر خواهد بود.

معرفی کد فرستنده/گیرنده RS232
کد VHDL مربوط به بخش فرستنده/گیرنده پروتکل RS232 از طریق لینک زیر، قابل دانلود است. مجددا یادآوری میکنم که برای استفاده آموزشی بیشتر از این کد، بهتر است ابتدا خودتان سعی کنید با توضیحاتی که در مورد پروتکل RS232 و نحوه پیادهسازی آن داده شد اقدام به نوشتن کد کنید و سپس آن را با کد ارائه شده در این مقاله مقایسه کنید.
برای دانلود کد VHDL، روی دکمه زیر کلیک کنید:
در نوشتن این کد فرض شده است که کلاک ورودی برابر با ۵۰MHz است. در نتیجه پریود کلاک برابر با ۲۰ns است. برای فرستنده و گیرنده، مقدار baud rate برابر با ۹۶۰۰bps در نظر گرفته شده است که معادل عرض بیت ۱/۹۶۰۰=۱۰۴٫۱۶μs است. پس هر بیت را باید با ۵۲۰۸ کلاک نشان داد چون: ۱۰۴٫۱۶μs/20ns=5208. این مقدار در سیگنال Baud_Rate_9600 قرار داده شده است. شمارنده Bit_Width_Count برای ایجاد عرض بیت متناسب با این baud rate استفاده شده است.
در لبه بالارونده سیگنال ورودی Send به شرطی که ماجول مشغول (Busy) نباشد؛ یعنی در حال ارسال پکتی نباشد، مقدار بیت پریتی محاسبه شده و سیگنال Busy فعال میشود. در کلاک بعد، پکت کامل، شامل بیتهای Start و Stop، بیت پریتی و بایت مورد نظر برای ارسال ساخته میشود. در کلاک بعد، فاز ارسال شروع میشود و هر کدام از بیتهای پکت کامل به مدت ۵۲۰۸ کلاک در خروجی سریال ماجول قرار داده میشوند. پس از ارسال هر یازده بیت پکت کامل، سیگنال Busy غیر فعال شده و مقدار منطقی یک روی پورت سریال خروجی قرار داده میشود تا زمانی که مجددا سیگنال Send دریافت شود. با توجه به اینکه لبه بالارونده سیگنال Send و مشغول نبودن ماجول در یک عبارت شرطی با هم کنترل میشوند، در صورتی که ماجول در حال ارسال پکتی باشد و سیگنال Send اعمال شود، چون ماجول مشغول است، این سیگنال را نادیده میگیرد.
نکات کدنویسی ماجول فرسنتده/گیرنده
در این بخش به بعضی از نکات کدنویسی که در این ماجول استفاده شده است اشاره میکنم. توجه به این نکته لازم است که بکارگیری بعضی از نکاتی که مطرح میشوند ممکن است برای ماجول کوچکی مثل فرستنده/گیرنده RS232 و ماجولهای مشابه ضرورتی نداشته باشند. این موارد بیشتر برای کدهای خیلی بزرگ یا ماجولهایی که فرکانس کلاک آنها زیاد است ضروری است. با این حال بهتر است در هر کدی هر چند کوچک آنها را به کار بندیم.
همواره سعی کنید تمام کد را به صورت سنکرون با یک کلاک بنویسید. به عبارت دیگر، عبارت Process در کد شما باید فقط حساس به کلاک سیستم باشد و نه سیگنال دیگری. همچنین تمام کد باید داخل عبارت شرط لبه بالارونده کلاک نوشته شود. اگر مجبور به استفاده از کلاک با فرکانس دیگری هستید، بهتر است در صورت امکان این کلاک ضریب صحیحی از کلاک اصلی سیستم باشد.
تمام سیگنالهای ورودی به جز کلاک را یک بار در عبارت Process در رجیستری داخلی بافر کنید و پس از آن در تمام کد، به جای استفاده از سیگنال ورودی از سیگنال بافر شده استفاده کنید. همچنین برای تمام سیگنالهای خروجی، یک سیگنال داخلی تعریف کنید و تمام ارجاعات به آن سیگنال خروجی را به سیگنال داخلی اعمال کنید. سپس در خارج از عبارت Process سیگنال داخلی را به سیگنال پورت خروجی اعمال کنید.
تا جای ممکن از ساختارهای شرطی تو در تو اجتناب کنید و سعی کنید بیش از سه لایه عبارت شرطی تو در تو در ماجول نداشته باشید. همچنین تا جای ممکن از شرطهای ساده استفاده کنید.
چطور از صحت پیادهسازی خودمان مطمئن شویم؟
مثل همیشه، سریعترین روش برای اطمینان از صحت عملکرد ماجولهای کوچک، انجام شبیهسازی رفتاری است. برای انجام این کار، در نرمافزار ISE یک تستبنچ برای ماجول فرستنده و یک تستبنچ برای ماجول گیرنده ایجاد کنید و هر کدام را جداگانه تست کنید.
در تستبنچ ماجول فرستنده، در بخشی که باید ورودیها را اعمال کنید، یک بایت دلخواه به عنوان ورودی به پورت Data_In ارجاع دهید و همزمان پورت Send را به مدت یک کلاک برابر با یک قرار دهید و شبیهساز را اجرا کنید. سپس خروجی Serial_Out را با آنچه از خروجی سریال انتظار داشتید مقایسه کنید و در صورت وجود تفاوت، کدتان را برای یافتن خطا بررسی کنید.
در تستبنچ ماجول گیرنده، باید یک رشته یازدهبیتی ایجاد کنید و به ورودی Serial_In اعمال کنید. بعد از انجام شبیهسازی، انتظار داریم که بایت موجود در پکتی که به ورودی Serial_In اعمال کردیم در خروجی Data_Out ماجول قرار بگیرد و همزمان پورت Valid به مدت یک کلاک برابر با یک شود.
تستبنچهای نمونهای برای هر دو ماجول در کنار کدهای اصلی قرار داده شدهاند که میتوانید از لینک بالا دانلود کنید.
آیا مقاله پیادهسازی پروتکل RS232 برای شما مفید بود؟
لطفا نظرتان را در مورد این برنامه در پایین همین پست با دیگران به اشتراک بگذارید. همچنین با کلیک روی هر کدام از دکمههای اشتراک گذاری ابتدای این مطلب و به اشتراکگذاری آن در شبکههای اجتماعی میتوانید افراد بیشتری را در یادگیری این مطالب سهیم کنید.