AVR, آردوینو, توصیه شده, کتابخانه برنامه نویسی, مقاله های سیسوگ, میکروکنترلر

تبدیل کتابخانه های CPP آردوینو به C برای AVR

تبدیل کتابخانه های آردوینو به AVR

تبدیل کد های آردوینو به AVR

شاید تا به حال برای شما هم پیش آمده باشد که یک کتابخانه خیلی خوب و قدرتمند پیدا کرده باشید، اما آن را برای آردوینو و با زبان آن ++C نوشته شده باشند. در حالی که شما برنامه نویس میکروکنترلر AVR با زبان C هستید. در این مقاله کاربردی، سعی می‌کنیم تا به‌صورت عملی کدهای کتابخانه‌ای را از آردوینو به AVR تبدیل کنیم.

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

 

قبل از اینکه دست به کار بشید و کتابخانه آردوینو رو تبدیل کنید، اول چند چیز مهم رو باید بررسی کنید.

  • آیا جستجو کرده اید که کسی قبل از شما این کتابخانه را برای AVR نوشته است یا نه؟!
  • آیا به جز این، کتابخانه تمیز تر، بهتر و با امکانات بیشتری نیز برای این کار نوشته شده است؟
  • آیا کتابخانه مورد نظر آن قدر ارزش دارد که بر روی آن وقت بگذارید و آن را تبدیل کنید؟ آیا خودتان نمیتوانید آن را از اول بنویسید؟
  • آیا قبل از تبدیل، آن را بر روی آردوینو تست کرده ام تا از صحت عملکرد آن مطمئن شوم؟!
  • و…

 

چند نکته مهم!

هرچند نوشتن مجدد کتابخانه‌ای که قبلاً توسط دیگران نوشته شده، ممکن است کار بسیار وقت گیری باشد، اما خیلی اوقات اگر کدی را خودتان از اول بنویسید، بعداً در عیب یابی و پشتیبانی آن بسیار راحت‌تر خواهید بود. همین طور هیچ وقت نمی‌توان برای تبدیل کدها از یک زبان یا حالتی به حالت دیگر یک الگوی ثابت ارائه داد. چون باید دقیقاً هدف و منظور برنامه نویس را از کدهایی که نوشته است بدانید. شاید برنامه نویس با توجه به محدودیت‌ها و یا امکاناتی دستگاه مورد نظرش داشته است، برنامه‌ای را توسعه داده باشد، و یا با چندین بار اجرا و تست گرفتن، به کد مورد نظر رسیده باشد، در حالی که همان کدها بر روی دستگاه شما باید به نحو دیگری پیاده سازی شوند.

پس اگر کدی را که برای زبان و دستگاه مورد نظر شما نوشته شده را پیدا نکردید، اما همان کتابخانه را برای دستگاه دیگری پیدا کردید، تا حد امکان سعی کنید به جای تبدیل، از آن‌ها الگو گرفته و خودتان آن را بازنویسی کنید.

 

این نکته را نیز در ذهن داشته باشید که شما می‌توانید به کمک چارچوب برنامه نویسی (Framework) آردوینو برای بسیاری از میکروکنترلر های AVR و ARM نیز برنامه نویسی کنید و حتماً هم نیازی به تبدیل کدها نخواهید داشت. توصیه می‌کنم مقاله “آماده سازی محیط VSCODE برای برنامه نویسی AVR” را از دست ندهید.

 

شما به عنوان کسی که می‌خواهد کتابخانه ++C آردوینو را به C تبدیل کند، باید با ساختار (Structure) و قواعد نوشتاری (Syntax) هر دو زبان به اندازه کافی آشنا باشید.

 

تفاوت های زبان C با ++C

خوب مسلماً بررسی کامل ساختار هر دو زبان بحث طولانی دارد و در یک مطلب نمی‌گنجد. اما شما باید به تفاوت‌های این دو زبان نیز توجه داشته باشید. برای مثال، زبان CPP آبجکتیو است. به همین خاطر متغیرها و کلاس‌هایی با طول متغیر مثل String و… را می‌توان تعریف کرد. در حالی که در زبان C، مدیریت حافظه معمولاً به‌صورت استاتیک است و شما باید طول آرایه‌ها، رشته‌های متنی و دیگر خواص داینامیک CPP را تعیین کنید.

 

برخی از مهم‌ترین امکاناتی که در زبان برنامه نویسی ++C اضافه شده‌اند:

  • کلاس – class
  • قالب یا تمپلیت  – template
  • توابع مجازی – virtual function
  • operator overloading
  • مدیریت خطاها – Exception Handling
  • ارث بری و ارث بری چندگانه – multiple inheritances
  • افزایش قابلیت های Type Checking
  • اختصاص حافظه داینامیک – Dynamic memory

همان طور که میدانید، زبان ++C بر پایه‌ی C است که گرامر آن توسعه یافته است و شی‌ء گرایی و امکانات دیگر به آن اضافه شده است. یعنی کدهای C در محیط ++C نیز اجرا خواهند شد.

تبدیل کتابخانه آردوینو به AVR یک مبحث بسیار طولانی است و می‌تواند حالت‌های بسیار زیادی هم داشته باشد. اما خوب! نگران نباشید. با یه مثال خیلی ساده شروع می‌کنیم. بزن بریم!

 

بررسی کتابخانه هدف – مورس

به عنوان نمونه، می‌خواهیم یک کتابخانه ساده مثل Morse آردوینو را برای AVR تبدیل کنیم. این کتابخانه شامل یک کلاس با نام Morse است و دو عضو با نام‌های dot و dash دارد. با صدا زدن این توابع، بر روی پین مورد نظر کدهای مورس را ایجاد می‌کند. ما ابتدا این کلاس را از حالت شی‌ء گرا خارج کرده و در خود آردوینو توابع جدید را تست می‌کنیم، سپس آن را برای AVR باز نویسی می‌کنیم.

 

بررسی فایل ها

کتابخانه مورس و تمام فایل‌های مورد نیاز در این آموزش، در انتها قابل دانلود هستند. همان‌طور که میدانید هر کتابخانه چه در زبان C و چه در زبان ++C یک فایل سرآیند (Header: هدر) و یک فایل منبع (Source) می‌باشد. پسوند فایل منبع در زبان سی پلاس پلاس، cpp. و در زبان سی، c. می‌باشد. پسوند فایل سرآیند در هر دو زبان معمولا h. است. اما گاهی اوقات در زبان CPP، فایل هدر ممکن است بدون پسوند و یا با پسوند hpp. نیز ظاهر شود.

 

فایل Morse.h

 

فایل Morse.cpp

 

نحوه استفاده از کتابخانه در آردوینو

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

با توجه به وجود متد سازنده (structure) در کلاس، هنگام ساختن شی جدید حتماً باید پارامترهای خواسته شده را نیز به ورودی متد بدهید. در اینجا برای ساخت کتابخانه، از ما شماره پینی که می‌خواهیم کد مورس روی آن اجرا شود را می‌خواهد. به همین خاطر عدد 13 را در ورودی تابع بالا وارد می‌کنیم.

 

حال، در هر جای برنامه برای صدا زدن متد مورد نظر از شی‌ء ساخته شده، به شکل زیر عمل می‌کنیم:

 

به همین ترتیب برنامه اصلی (main) ما به شکل زیر نوشته می‌شود.

 

مرحله اول -خارج کردن متد ها ازکلاس

تغییرات فایل منبع

ابتدا از کل پروژه یک کپی بگیرید و تغییرات را روی پروژه اصلی انجام ندهید! از فایل سورس برای تبدیل به زبان C شروع می‌کنیم. فایل را برای ویرایش باز کنید. از آن جایی که توابع، دیگر وابسته به کلاس نیستند، می‌بایست نام کلاس (در اینجا::Mors) از ابتدای متدها حذف شوند. اما بهتر است به جای حذف، تنها عبارت  ::  را در نام تمام توابع با  _  جایگزین کنید و نام متد جدید را نیز به حروف کوچک تغییر دهید. زیرا با حذف نام کلاس از ابتدای برخی توابع، ممکن است تشابه اسمی میان نام جدید و نام توابع دیگر کلاس ها بوجود آید.

برای مثال:

 

به شکل زیر اصلاح می‌شود:

 

این کار به شما کمک می‌کند تا بعداً بدانید تابع استفاده شده در برنامه، مربوط به کدام کتابخانه است. برای مثال، اگر به توابع کتابخانه lcd در کدویژن نیز دقت کنید، همین فرمت را دارند:

 

متد سازنده کلاس

متد سازنده یا همان Constructor وظیفه مقدار دهی اولیه اشیاء را هنگام ساخته شدن دارد. این متد هم نام کلاس خودش می‌باشد و از لحاظ سینتکس، مانند یک متد محسوب می‌شود. اما هیچ‌گونه مقدار برگشتی مشخصی ندارد. یعنی هنگام ساختن آن هیچ مقدار برگشتی (حتی void) را برای آن تعریف نمی‌کنیم. همه‌ی کلاس‌ها نیز لزوماً متد سازنده ندارند.

از آنجایی که متد سازنده، هم نام خود کلاس است، در مرحله قبل نام آن به  morse_morse  تبدیل می‌شود. چون در زبان C کلاسی وجود ندارد، متد سازنده‌ای هم وجود ندارد. اما کتابخانه برای شروع کار خود، نیاز به مقدار دهی و تنظیمات اولیه دارد. بنابراین نام متد سازنده (که به شکل morse_morse در آمده است) را اصلاح می‌کنیم و یکی از نام‌های begin یا init را بسته به نوع کاربرد، به جای morse دوم آن قرار می‌دهیم. همچنین نوع خروجی تابع را نیز مشخص می‌کنیم.

 

انتقال متغیر ها

در فایل هدر زبان C، نباید هیچ متغیری تعریف شود. بنابراین تمام متغیرهایی که درون فایل هدر CPP تعریف شده‌اند را حذف و به فایل سورس منتقل کنید. در این مثال  ;int _pin  را جابجا می‌کنیم.

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

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

تغییرات فایل سرآیند

قاعدتاً چون ما در زبان C چیزی به اسم کلاس و شی‌ء نداریم، پس عبارت  } class Morse   را به همراه کروشه باز و بسته  ;{  از ابتدا و انتهای فایل هدر پاک می‌کنیم. همچنین توابع عمومی و خصوصی معنایی ندارند. پس عبارات  :public  و  :private  را نیز حذف می‌کنیم. توجه داشته باشید که هدف برنامه نویس از خصوصی کردن توابع، این است که شما مستقیماً آن را در برنامه صدا نزنید! پس حواستان به این موضوع نیز باشد. اگر کتابخانه شما دارای متد خصوصی است، نیازی نیست امضای آن تابع را در فایل هدر وارد کنید. با این کار توابع شما تنها درون فایل سورس قابل استفاده هستند.

سپس تغییراتی که در مرحله قبل روی فایل سورس دادیم، بر روی فایل سرآیند نیز اعمال می‌کنیم. در فایل سورس، ما یک متد شروع کننده ساختیم، به ابتدای تمامی توابع _morse اضافه کردیم و همه آن‌ها را به حروف کوچک تغییر دادیم. همچنین تمام متغیرها را نیز به فایل سورس منتقل کرده‌ایم.

نتیجه:

 

حال برای استفاده از توابع در برنامه اصلی، دیگر نیازی نیست تا یک شی‌ء از روی آن بسازیم، در عوض باید کلاس را راه اندازی اولیه کنیم:

 

برنامه اصلی، بدون شی‌ء گرایی به شکل زیر در می‌آید:

خوب! تا اینجا توانستیم متدها را از داخل کلاس خارج کنیم. همیشه اول کتابخانه آردوینو را از حالت شی‌ء گرایی خارج کنید و درون خود آردوینو توابع تبدیل شده را تست کنید، تا قبل از تبدیل آن‌ها به AVR، از صحت عملکرد کدهای جدید اطمینان حاصل کنید.

 

مرحله دوم – تبدیل توابع سطح بالای آردوینو به AVR

همان طور که می دانید، آردوینو یک زبان مالتی پلت فرم است که به کمک آن می‌توانید برای انواع بردها و میکروکنترلر ها (مثل AVR, ARM, ESP8266 و…) برنامه بنویسید. کدی که شما می‌نویسید، تقریباً برای همه‌ی بردها یکسان است. برای مثال، پین‌ها خیلی راحت و با یک شماره در دسترس شما هستند و یا استفاده از یک تابع، می‌توانید پورت سریال را پیکربندی کنید. در حالی که هر برد و میکروکنترلری، رجیستر های مخصوص خود را دارد. در واقع، آردوینو هنگام کامپایل کردن به طور خودکار مطابق با نوع بردی که انتخاب کرده‌اید، رجیستر های آن را قرار می‌دهد.

 

شما برای تبدیل کدهای سطح بالای آردوینو به رجیستر های AVR در زبان C، دو راه دارید، که راه دوم کمی منطقی تر است:

  • مطالعه کردن سورس آردوینو و استخراج رجیستر ها برای برد مورد نظر
  • درک کردن عملی که تابع آردوینو انجام می‌دهد (بدون نیاز به خواندن سورس) و بازنویسی آن برای AVR

بازنویسی فایل منبع

اگر شما برنامه نویس AVR باشید، خیلی راحت می‌توانید منظور آردوینو را از توابع مختلف را متوجه شده و به راحتی آن را برای یک تراشه خاص (مثلاً ATmega32) باز نویسی کنید. برای مثال، برای تغییر جهت ورودی پین‌ها در آردوینو از تابع pinMode استفاده می‌شود که معادل همان DDRx در AVR است. همچنین برای صفر و یک کردن یک پایه نیز، در آردوینو از digitalWrite استفاده می‌شود که در AVR معادل همان رجیستر PORTx می‌باشد. برای اینکه این رجیستر ها را تنها یک بار در برنامه تعریف کنیم و در جاهای دیگری از برنامه از آن‌ها استفاده کنیم، از دستورات پیش پردازنده define استفاده می‌کنیم. برای صفر و یک کردن یک بیت از یک بایت (رجیستر مورد نظر) نیز از عملیات بیتی کمک می‌گیریم. همچنین توابع تأخیر در فایل سرآیند util/delay.h وجود دارند، اما کمی در فرم نوشتاری فرق دارند. (در این آموزش از کامپایلر GCC استفاده شده است. در کدویژن نیز کدها کمی تفاوت دارند.)

 

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

 

ترفند کمکی

اگر دقت کنید، بعضی از توابع تنها در نوشتار اختلاف کوچکی دارند. برای مثال تابع delay در آردوینو، معادل همان ‎_delay_ms در کامپایلر GCC یا delay_ms در کامپایلر کدویژن است. شما می‌توانید پس از اضافه کردن کتابخانه مورد نظر، بدون اینکه تغییری در کد ایجاد کنید، به کمک دستورات پیش پردازنده به کامپایلر بفهمانید که تابع صدا زده شده معادل چیست!

 

بازنویسی فایل هدر

در این پروژه، فایل هدر کمترین تغییر را دارد. تنها فایل سرآیند arduino.h از ابتدای خطوط حذف شده است، همچنین تابع init نیز دیگر به ورودی احتیاج ندارد. بنابراین امضای آن تغییر می‌کند.

 

برنامه اصلی در AVR

تابع Loop در واقع همان while(1) در AVR است و تابع setup نیز، همان قسمت ابتدایی تابع main تا قبل از while(1) است.

بنابراین فرم کلی یک برنامه در AVR به‌صورت زیر است:

 

برنامه اصلی مورس ما که در فایل main.c قرار دارد نیز، به شکل زیر در می‌آید:

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

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

16 دیدگاه در “تبدیل کتابخانه های CPP آردوینو به C برای AVR

  1. Avatar for محمد محمد گفت:

    سلام،ممنون از مطلب جالبتون، اگه ممکنه یه توضیح مختصر درباره کاربرد و تبدیل کردن به زبان سی برای اشاره گر <-this در اردوینو بدید.

    1. Avatar photo Digi Boy گفت:

      درود بر شما.
      زبان سی پلاس پلاس شی گراست. this درون یک تابع، به متغیری اشاره دارد که درون کلاس تعریف شده است.
      مثال:
      class T
      {
      int x;

      void foo()
      {
      x = 6; // same as this->x = 6;
      this->x = 5; // explicit use of this->
      }
      }

  2. Avatar for محمد جواد عبادی محمد جواد عبادی گفت:

    یعنی خدایی بدون اغراق میگم کلی تو سایتای خارجی گشتم . . . فروما رو زیرو رو کردم . . . اما دست آخر موقعی که اصن فکرشم نمیکردم دنبال یه چیز دیگه بودم اونو توی یه سایت فارسی زبان پیدا کنم. یعنی فقط انتظار چنین مطالب توپی رو از سیسوگ دارم و از نویسنده خوبش تشکر میکنم که این قدر با حوصله همه چیز رو از اول اول و با زبانی خیلی ساده برای ما تازه کار ها تشریح کرده. این وااقعا عالیه. وظیفه خودم دونستم تا حداقل با یک تشکر ساده بگم که مطلبتون رو دوست داشتم ازین به بعد همیشه شما رو دنبال می کنم………..

    1. Avatar for زئوس Zeus زئوس Zeus گفت:

      سلام
      خوشحالم که این مطلب تونسته به شما کمک کنه 🙂
      و خوشحالم از همراهی شما 🙂

  3. Avatar for پیمان پیمان گفت:

    خیلی عالیه واقعا نجاتم دادید

  4. Avatar for مهدی مهدی گفت:

    سلام و تشکر از شما
    به مورد بسیار جالب و کاربردی اشاره کردید. احتمالا کامپایل برخی پروژه های آدروئینو تو کامپایلرهای CPP (مثل IAR) هم یه مشکلاتی داره. حداقل کلاس String رو من باهاش مشکل داشتم و تو خیلی از پروژه ها هم استفاده شده. یا باید از اول نوشته بشه که کار بسیار زمان بری هست چرا که توی این کلاس از توابعی استفاده شده که اون ها هم استاندارد C یا CPP نیستند (مثل توابع موجود در هدر util)، یا باید کلا ازشون صرف نظر بشه (چون اکثرا برای پرینت کردن و دیباگ کردن استفاده شده).

    1. Avatar photo Digi Boy گفت:

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

  5. Avatar for اصغر اصغر گفت:

    تا سایت ها و نویسنده هایی مثل شما رو میبینم واقعا به آینده الکترونیک ایران امیدوار تر میشم

  6. Avatar for احسان احسان گفت:

    بسیار ممنون از زحماتی ک میکشید
    واقعا باید افتخار کرد منبع اوپن سورسی عین سیسوگ برای فارسی زبان ها داریم!

    1. Avatar photo Digi Boy گفت:

      درود بر شما!
      دوست عزیز شما می توانید با معرفی سیسوگ به دیگران از ما حمایت کنید!

  7. Avatar for هادی هادی گفت:

    دمت گرم، خسته نباشید
    واقعا لذت میبرم از مقاله های شما
    خدا قوت

    1. Avatar photo Digi Boy گفت:

      خیلی ممنون.
      قطعاً نظرات گرم شما باعث دلگرمی ما در این مسیر خواهد بود.

  8. Avatar for مهدی مهدی گفت:

    نرم افزارهای winavr , و atmel studio از برنامه ++C پشتیبانی میکنند .چرا برگشت به عقب و سخت تر شدن برنامه نویسی؟؟؟
    please mention to the source that you and your team use to translate this tutorials
    انتشار مطالب با ذکر نام و آدرس وب سایت سیسوگ، بلامانع است.(??why)

    1. Avatar photo Digi Boy گفت:

      سلام.
      دوست عزیز، مطلب توسط نویسنده نوشته شده و از هیچ جایی ترجمه نشده است.
      همچنین در ابتدای مقاله نیز ذکر شده است که شما با استفاده از آردوینو می توانید برای میکرو برنامه بنویسید.

  9. Avatar for رحیم رحیم گفت:

    سیسوگ عاشقتم!!!

    1. Avatar photo Digi Boy گفت:

      خیلی ممنون دوست عزیز!

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

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