آموزش برنامه نویسی c, برنامه نویسی

بررسی بیت ها در امبدد C – قسمت یازدهم آموزش امبدد C

در قسمت قبل آموزش برنامه نویسی C به نمایش مکمل دو در اعداد صحیح با علامت (Two’s Complement) پرداختیم. در این قسمت به بررسی بیت ها در امبدد C می پردازیم.

دنیای سخت‌افزار شیفته‌ی تعریف همه چیز بر اساس بیت‌ها است. چرا؟ چون سیگنال‌ها هنگام خروج از تراشه، از پین‌هایی با نامی مانند GPIO A-3 (یعنی بیت سوم رجیستر GPIO A) خارج می‌شوند. از آنجایی که هر پین تنها می‌تواند دو حالت بالا (1) یا پایین (0) داشته باشد، به راحتی با یک بیت نمایش داده می‌شود.

اما از دید یک برنامه‌نویس، این سیگنال‌ها معمولاً در قالب رجیسترهای 8، 16 یا 32 بیتی بسته‌بندی شده‌اند. پس، ما نیاز به ابزاری داریم تا به سادگی بین این دو دیدگاه، یعنی دیدگاه سخت‌افزاری (مثل “بیت سوم”) و دیدگاه نرم‌افزاری (مثل “x040”)، ارتباط برقرار کنیم. عملگرهای شیفت، اگر به درستی استفاده شوند، می‌توانند این کار را به نحو احسن انجام دهند.

مثال

تصور کنید یک برد با چندین چراغ LED داریم. مشخصات سخت‌افزاری آن به شرح زیر است:

بیت

نام

شرح

7

MF

خرابی اصلی: هنگامی که هر چراغ‌خطر دیگری روشن شود، روشن می‌شود.

6

DF

خرابی داده: داده‌های ورودی ناسازگار یا خراب هستند.

5

OL

کمبود روغن: سطح روغن در مخزن کم است.

4

OP

فشار روغن: فشار روغن کم است.

3

PW

قطع برق: منبع‌تغذیه اصلی قطع شده است.

2

PF

خطای موقعیت: فریم موقعیت به سوئیچ محدودکننده برخورد کرده است و در جایی که قرار است نیست.

1

AP

فشار هوا: کمپرسور هوا خراب شده است.

0

CF

فیلتر تمیز: فیلتر کمپرسور هوا نیاز به تمیزکاری دارد.

هر بیت از این رجیستر به یک چراغ خاص اختصاص یافته است. مدار هر چراغ مستقیماً به یکی از پین‌های ورودی/خروجی عمومی (GPIO) میکروکنترلر متصل شده است. به عنوان مثال، با تنظیم مقدار بیت صفر (بیت اول) رجیستر GPIO بر روی یک (1)، چراغ “فیلتر تمیز” روشن خواهد شد.

به خاطر سپردن هر بیت و عدد مربوطه، کمی گیج‌کننده است. به عنوان مثال، بیت صفر اولین مقدار، بیت یک مقدار دوم و… را نشان می‌دهد. پس بیت ششم به چه عددی مربوط می‌شود؟

یک راه خوب برای آسان‌تر کردن این کار وجود دارد. بیت 0 مقدار 1 را نگه می‌دارد که معادل عبارت (0>>1) است. بیت 1 مقدار 2 است که معادل (2>>1) می‌شود و بیت 3 هم (3>>1) است. از این رو، به راحتی می‌توان دید که بیت 5 برابر با (5>>1) است. با استفاده از این سیستم، می توانیم ثابت‌هایی را برای نشان دادن هر بیت تعریف کنیم:

بیایید یک‌بار دیگر LED فیلتر تمیز را روشن کنیم، این بار با استفاده از ثابت جدید خود:

در این مثال، از عملگر |= استفاده شده که باعث می‌شود بیت مربوط به فیلتر تمیز در رجیستر روشن شود. این عملگر قبلاً در بخش‌های قبل توضیح داده شده است.

روشن کردن چندین بیت به صورت همزمان

فرض کنید می‌خواهیم همزمان چراغ‌های نشان‌دهنده قطع برق (POWER_FAILURE) و خرابی اصلی (MASTER_FAIL) را روشن کنیم. برای این کار می‌توانیم از کامند زیر استفاده کنیم:

در این کامند، ثابت‌های MASTER_FAIL و POWER_FAILURE به بیت‌های مربوط به خرابی اصلی و قطع برق اشاره می‌کنند. با استفاده از عملگر |، هر دو بیت در رجیستر روشن خواهند شد. توجه کنید که هر مقداری غیرصفر در یک بیت باعث می‌شود آن بیت روشن شود.

خاموش‌کردن یک بیت

برای اینکه یک بیت خاص را خاموش کنیم، از الگوی زیر استفاده می‌کنیم:

برای درک نحوه عملکرد این عملیات، بیایید با استفاده از کامند زیر آن را به طور کامل بررسی کنیم:

ابتدا نتیجه عبارت (MASTER_FAIL | POWER_FAILURE) را محاسبه می‌کنیم:

حالا عملگر نقیض (NOT) یا (~) را روی این نتیجه اعمال می‌کنیم:

در مرحله بعد، مقدار فعلی ledRegister را در نظر می‌گیریم. فرض می‌کنیم در این مثال، بیت‌های نشانگر خرابی اصلی(MASTER_FAIL) و فیلتر تمیز (CLEAN_FILTER) روشن هستند.

حالا نتایج را با عملگر AND  ترکیب می‌کنیم:

همان‌طور که می‌بینید، با خاموش‌کردن بیت‌های نشانگر خرابی اصلی، تنها بیت مربوط به فیلتر تمیز روشن باقی‌مانده است.

بررسی مقادیر بیت‌ها

برنامه زیر نمونه‌ای از کاربرد معمول بیت بنگینگ (Bit-banging) را نشان می‌دهد که به معنی روشن و خاموش‌کردن بیت‌های جداگانه است. این برنامه همچنین شامل منطقی برای بررسی مقادیر بیت‌های مختلف است:

ابتدا به سراغ تابع printLED می‌رویم. این تابع هر بیت را به‌صورت جداگانه بررسی کرده و در صورت روشن بودن آن، پیامی را چاپ می‌کند. (در فصل ۵ با دستور شرطی if که برای این کار استفاده می‌شود آشنا خواهید شد.)

برای درک منطق آن، به دستور زیر توجه کنید:

این پیام در صورتی چاپ میشود که عبارت خط اول برابر با صفر نباشد. از آنجا که این عبارت از عملگر بیتی (&) AND استفاده میکند، هر بیت در ledRegister باید با بیت متناظر در MASTER_FAIL مطابقت داشته باشد تا مقدار ۱ بگیرد. اگر حداقل یک مجموعه از بیتها هر دو مقدار ۱ باشند، دستور printf اجرا میشود. به عبارت دیگر، پشت‌صحنه عملیات به این شکل است:

کل این تابع یک آزمایش یکسان را روی تمام بیت‌های رجیستر انجام می‌دهد و هر بیتی که روشن باشد (یا مقدار ۱ داشته باشد) نمایش می‌دهد. ما پنل چراغ سخت‌افزاری نداریم بنابر‌این از این تابع استفاده می‌کنیم به عبارت دیگر، این تابع به ما امکان می‌دهد ببینیم کدام بیت‌ها در رجیستر فعال هستند.

در بخش‌های بعدی برنامه، ما به طور عمدی تغییراتی در بیت‌ها ایجاد می‌کنیم. به عنوان مثال، با فعال کردن بیت‌های POWER_FAILURE و MASTER_FAIL، شرایطی شبیه به یک قطع برق را شبیه‌سازی می‌کنیم. در نتیجه، زمانی که وضعیت چراغ‌های LED را چاپ می‌کنیم، پیام زیر را دریافت می‌کنیم:

بقیه برنامه، بیت‌های مختلف را برای تولید پیام‌های زیر تنظیم و خالی می‌کند:

جمع بندی

در این چند قسمت اخیر، به بررسی عملیات پایه روی اعداد صحیح پرداختیم. علاوه بر عملیات حسابی معمول مانند جمع، تفریق، ضرب و تقسیم، به روش ذخیره‌سازی اعداد در حافظه‌ی کامپیوتر و چگونگی برخورد با خطاهایی مانند سرریز (overflow) نیز پرداخته شد.

بخش مهم دیگری که مورد بحث قرار گرفت، دستکاری بیت‌ها بود. در این بخش، اعداد صحیح را به عنوان مجموعه‌ای از بیت‌ها (صفر و یک) در نظر گرفتیم و نحوه‌ی کار با آن‌ها را آموختیم. این مفهوم در برنامه‌نویسی سیستم‌های امبدد بسیار کاربردی است، زیرا بسیاری از سخت‌افزارها از رجیسترهایی استفاده می‌کنند که با بیت‌ها سروکار دارند. به عنوان مثال، رجیستر GPIO که برای روشن و خاموش کردن LED استفاده کردیم، بیت‌هایی برای 31 تا GPIO دیگر را در خود جای داده است. 31 پین دیگر کاملاً بی‌ارتباط با LED ما هستند و عملکردهای دیگری دارند.

در قسمت های آینده، به سراغ تصمیم‌گیری‌های شرطی خواهیم رفت و یاد می‌گیریم که چگونه بر اساس نتایج محاسبات، برنامه را در مسیرهای مختلف هدایت کنیم.

انتشار مطالب با ذکر نام و آدرس وب سایت سیسوگ، بلامانع است.

شما نیز میتوانید یکی از نویسندگان سیسوگ باشید.   همکاری با سیسوگ

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *