آموزش CooCox CoIDE جهت برنامه نویسی میکروکنترلر های Cortex-M4

ROBOTICS

کاربر فعال مهندسی رباتیک
آموزش CooCox CoIDE جهت برنامه نویسی میکروکنترلر های Cortex-M4



این تاپیک برای مبتدی ها می باشد. در صورتی که چیزی می دانید لطفا ادامه ندهید چون فقط وقت شمار را تلف می کند



میکروکنترلر های سری Cortex-M4

همان طور که می دانید میکروکنترلر های 8051 - AVR - PIC - ... دیگر منسوخ شده اند و امروزه از Cortex-M4 استفاده می شود.

Cortex-M4 توسط شرکت های مختلفی تولید می شود از جمله شرکت های زیر

Atmel - Energy Micro - Freescale - Holtek - NXP - Nuvoton - ST - TI - Toshiba

تو ایران شرکت Atmel پر فروش ترین شرکت سازنده میکرو هست که تمام چیز هایی که تو انبار دارد و مشتری ندارد را به ایران می فرستد

تو جهان Freescale پرفروش ترین شرکت میکرو ساز است

NXP بعد از تحریم ها تو ایران جا باز کرد و بعد از Atmel پرفروش ترین شرکت در بازار ایران است

شرکت ST هم چون اروپایی است تحت تاثیر تحریم کمتر واقع شده است

چون تمام این شرکت ها میکروکنترلر Cortex-M4 می سازند برنامه نویسی مشابه داند. اما برنامه نویسی آن ها یکیان نیست. تقریبا 90 کد ها یکسان است. آن اختلاف کم هم می شود با جند روز کار کردن جبران نمود.

با توجه به امکانات در این تاپیک میکروکنترلر های شرکت ST خانواده ی STM32F4 برنامه نوشته می شود و قابل تعمیم به سایر شرکت ها است.

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

Discovery kit for STM32 F4 series

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

IDE & compiler & debugger

IDE مخفف Integrated Development Environment به معنی «محیط یکپارچه توسعه نرم‌افزار» است. در واقع محیطی است که کاربر در آن برنامه می نوسید. در بین مبتدی ها اشتباها به کامپایلر معرف است !

چهار IDE معروف به شرح زیرند:

Keil
IAR
MikroC
CooCox CoIDE

البته نرم افزار های دیگری نیز وجود دارد که کمتر مورد استفاده قرار می گیرند. در بین چهار نمر افزار فوق، سه تای اول پولی هستند و برای آن یا باید پول زیادی بدهید و یا آن ها را کرک نمایید. نرم افزار Keil در بین ایرانی ها محبوبیت بیشتری دارد. نرم افزار IAR در بین ایرانی هایی که با میکروکنترلر های 8051 برنامه می نوشتند محبوبیت دارد. نرم افزار MikroC بین ایرانی هایی که با میکروکنترلر های PIC کار می کردند طرفدار دارد. اما در این تاپیک ما راه دیگر، یعنی نرم افزار رایگان را انتخاب می کنیم.

کامپایلر نمر افزار است که کد شما را از یک زبان به زبان دیگری تبدیل می کند. در این جا کد شما از زبان سی یا سی پلاس پلاس یا هر زبان دیگری به زبان ماشین (هگز) تبدیل می شود. محیط یکپارچه توسعه نرم‌افزار CooCox CoIDE به شما این اجازه را می دهد که از کامپایلر های متفاوتی استفاده نمیاید. ما در این جا از کامپایلر رایگان GCC استفاده می کنیم.

ادامه در پست های آتی
 

ROBOTICS

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

کد:
C++

آموزش سریع از سی پلاس پلاس برای برنامه نویسی کامپیوتر در فایل زیر موجود است. می توانید آن را دانلود نمایید و مرور نمایید.

کد:
http://www.cplusplus.com/files/tutorial.pdf

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

ابتدا در سی پلاس پلاس باید با موارد زیر آشنا باشید

کد:
Variables and types
strings
Constants
Preprocessor (#include, #pragma, #define, #undef, #ifdef, #ifndef, #if, #endif, #else, #elif, #line, #error)
Operators
Basic Input/Output (cout, cin)
if and else
switch
goto
while loop
do-while loop
for loop
Jump statements (break, continue)
Functions
Overloaded functions
Arrays
Pointers
Dynamic memory (new, delete, malloc, calloc, realloc, free)
structures
typedef 
Unions
enum

پس از موارد فوق به مبحث کلاس می رسیم که تفاوت اساسی زبان سی پلاس پلاس با زبان سی است. در مورد کلاس ها باید با موارد زیر آشنا باشید.

کد:
Structure of a Class
Constructors
Overloading constructors
Uniform initialization
Member initialization in constructors
Pointers to classes
Overloading operators
The keyword this
Static members
Const member functions
Class templates
Template specialization
Special members
Default constructor
Destructor
Copy constructor
Copy assignment
Move constructor and assignment
Implicit members
Friend functions
Friend classes
Inheritance between classes
Multiple inheritance
Base class
Polymorphism
Pointers to base class
Virtual members
Abstract base classes

در انتها می توانید مباحث زیر را یاد بگیرید. اما ضروری نیست. معمولا کسانی که رشته ی شان نرم افزار است از دستورات زیر را به کار می برند. اگر خودتان از صفر برنامه می نویسید لازم نیست یاد بگیرید اما اگر در قسمتی از برنامه هایتان می خواهید از کد های دیگران استفاده نمایید ممکن است با موارد زیر برخورد نمایید.

کد:
Exceptions (throw, try, catch)
Implicit conversion
explicit
Type casting (dynamic_cast, static_cast, reinterpret_cast, const_cast)
typeid

اگر موافق هستید پیشفرض را بگذاریم که شما سی پلاس پلاس بلدید ( یا اگر بلد نیستید از فایل بالا استفاده می کنید و یا هر منبع دیگر) و مستقیم برویم سراغ میکروکنترلر.
اگر هم فکر می کنید لازم است ابتدا سی پلاس پلاس را آموزش دهیم اعلام کنید.
 

yosoufe

متخصص خودرو
کاربر ممتاز
من بلد نیستم ولی قبلا تو codevision که فک کنم سی هست زبونش نوشتم

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

یه کتاب قابل دانلود هم واسه خوده میکرو معرفی کن بی زحمت! کمی هم اگه می شه راجه به object oriented programming بگو! تو متلب هم هست! ولی درس حسابی نمی فهمش! منظور از کلاس که گفتی همین نوع برنامه نویسیه؟

واقعا ممنون
 
آخرین ویرایش:

ROBOTICS

کاربر فعال مهندسی رباتیک
کمی هم اگه می شه راجه به object oriented programming بگو! تو متلب هم هست! ولی درس حسابی نمی فهمش! منظور از کلاس که گفتی همین نوع برنامه نویسیه؟

کلاس که در این تاپیک استفاده می کنم فارسی نیست یعنی من به جای Class می نویسم کلاس. از نظر لغوی Class معادل واژه فارسی «خوشه» است. کلاس (خوشه) همون بانه نویسی شی گرا نیست. برنامه می تواند کلاس داشته باشد اما شی گرا نباشد. اما تمامی برنامه های شی گرا باید کلاس داشته باشند.

این «... گرا » که می گویند نوعی تفکر است. یعنی نوعی دیدگاه به چگونگی نوشتن برنامه.
الان یادم نمی آید که چند تا ...گرا وجود دارد. اما سه تا که تو میکروکنترلر ها استفاده می شود را می گویم.


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

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

شی گرا: در این برنامه نویسی، شما تمرکز خود را روی اشیا می گذارید و این که چه شی با چه اشیا دوست است، کدام شی از کدام شی به ارث می برد، روابط بین این اشیا چیست، این شی چه میزان حریم شخصی دارد. به عنوان مثال بازی رایانه ای فیفا، هر بازیکن یک شی است هر بازیکن یک سری داده دارد نظیر قدرت شوت، قدرت دو، خستگی و ...

از نظر سرعت اجرای برنامه عمل گرا بسیار سریع تر از برنامه تابع گرا است و همین طور برنامه تابع گرا بسیار سریع تر از برنامه شی گرا است.

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

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

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


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

ROBOTICS

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

=============================

برنامه‌نویسی شیءگرا (به انگلیسی Object-Oriented Programming مخفف OOP) یک شیوه برنامه نویسی است که ساختار یا بلوک اصلی اجزای آن، شی ها می باشند. در واقع دراین شیوه برنامه نویسی، برنامه به شیء گرایش پیدا می کند. به این معنا که داده ها و توابعی که قرار است بر روی این داده ها عمل کنند، تا حد امکان در قالبی به نام شی در کنار یکدیگر قرار گرفته، جمع بندی شده و یک واحد(شی) را تشکیل داده و نسبت به محیط بیرونِ خود، کپسوله می شوند و از این طریق، توابع بیگانه ی خارج از آن شی، دیگر امکان ایجاد تغییر در داده های درون آن شی را ندارند. به طور مثال حساب بانکی شما که شامل مشخصات فردی شما و میزان سپرده ی شما در بانک است، تشکیل یک شی را می دهند و به دلیل دارا بودن ویژه گی کپسوله، امکان دستکاری در میزان سپرده یا مشخصات شما، توسط دیگران وجود ندارد. از دیگر ویژه گی های برنامه نویسی شی گرا، پیچیدگی کم، هزینه ی کم، امکان گسترش سریع برنامه با خطای کمتر نسبت به سایر پارادیام های برنامه نویسی است.

کلاس
کلاس نوع خاصی از داده است که امکان ذخیره و جمع بندی تعداد زیادی المان را (که شامل داده ها و توابع هستند) برای یک شی جدید فراهم آورده و تحت یک نام مشترک ذخیره می کند. کلاس می تواند داده هایی از جنس های مختلف را ذخیره نماید. به طور مثال در نظر بگیرید که می خواهیم تاریخ 13 نوامبر 2006 را که تشکیل شده از روز، ماه و سال است مورد استفاده قرار دهیم.برای این منظور سه نوع متغییر متفاوت مورد نیاز است:

کد:
int day;
String month;
int year;

حال در نظر بگیرید که نه فقط یک تاریخ، بلکه n تاریخ متفاوت مورد نیاز است. این بدان معنی ست که می بایستی به تعداد n بار، سه متغییر بالا، جداگانه تعریف شوند و تعریفِ تک تک و پیاپی متغییرها، نه فقط از لحاظ زمانی بسیار وقت گیر می نماید، بلکه از لحاظ میزان کد مورد نیاز نیز بسیار غیر عملی ست، چرا که هر بار می بایستی نام جدیدی برای متغییرها در نظر گرفته شود (دو متغییر متفاوت نمی‌توانند هم نام باشند). در اینجاست که کلاس ها به خوبی وارد عمل می شوند. با استفاده از کلاس ها می توان متغییرهای متعدد (در مثال بالا: int day ;String month, ;int year) را زیر عنوان یک جنسیت مشترک جدید(به طور مثال هر سه را در یک کلاس با نام Date)، تعریف و جمع بندی نمود. و بعد از آن، بدون نیاز به تعریف مجدد روز، ماه و سال،از کلاس Date به میزان مورد نیاز استفاده کرد:

HTML:
class Date{
int day;
String month;
int year; 
}


وراثت
وراثت یا ارث بری (Inheritance) از مفاهیم اساسی برنامه نویسی شیءگراست. هر شیء یک نمونه از یک کلاس است و هر کلاس می‌تواند از کلاس یا کلاسهای دیگری مشتق شده باشد (خواص متدها یا رویدادهای کلاس‌های دیگر را به ارث ببرد). در یک مثال ساده می‌توان اتومبیلی را در نظر گرفت که برای جلوگیری از بازنویسی خواص عمومی اتومبیل شامل: چهار چرخ، متدهای حرکت چرخ، متد چرخاندن فرمان، فرمان، بدنه، در و غیره، می‌توان یک کلاس پایه از اتومبیل ایجاد کرد سپس مثلاً برای اتومبیل زانتیا مدل C۵ یک کلاس جدید ایجاد کرده که خواص، متدها و رویدادهای عمومی اتومبیل را داشته باشد و فقط برای خواص، متدها و رویدادهای جدید این اتومبیل کد نوشته شود. این ویژگی باعث صرفه‌جویی در نوشتن کد و تا حدودی تضمین صحت کد موجود می‌شود. به عنوان مثال اگر کلاس پایه مشکلی داشته باشد فقط کافی است کلاس پایه تغییر داده شود و در تمامی کلاس‌هایی که از این کلاس پایه ویژگی‌ای ا به ارث برده‌اند این تغییر اعمال خواهد شد.

مخفی‌سازی
کپسوله سازی، مخفی‌سازی (Encapsulation)، یا لفافه‌بندی، به این مفهوم اشاره دارد که باید بعضی خصوصیات یا رفتارهای شیء را از دید دیگران پنهان کرد. فرض کنید شما به عنوان یک راننده می‌خواهید اتومبیل شخصی تان را روشن کنید و به محل کارتان عزیمت کنید سوییچ را بر می‌دارید، استارت می‌زنید و با فشار آوردن به پدال‌های گاز و ترمز و چرخش فرمان و ... به محل کارتان خواهید رسید. در طول این مسیر در اتومبیل شما به عنوان یک شیء اعمال مختلفی در حال انجام بود. مثلاً لنت ترمز به دیسک چرخ برخورد می‌کرد و باعث کم شدن سرعت می‌شد یا شمع‌ها شروع به جرقه زدن در زمانی بخصوصی می‌کردند. حال فرض کنید که عمل مخفی سازی وجود نداشت و شما مجبور بودید که جرقه زدن شمعها را کنترل می‌کردید و به سیستم سوخت رسانی در موقع لزوم دستور می‌دادید که سوخت را بداخل سیلندرها ارسال کند و... یا هیچ‌گاه به مقصد نمی‌رسیدید! یا سالم نمی‌رسیدید!
عمل مخفی سازی باعث می‌شود که اشیاء بدون آنکه از چگونگی کارکرد یکدیگر اطلاع داشته باشند با هم کار کنند.

چندریختی
چند ریختی(Polymorphism) چند ریختی، کمیتی است که به یک رابط امکان می‌دهد تا از عملیات یکسانی در قالب یک کلاس عمومی استفاده کند.عمل خاص کلاس را ذات حقیقی شیء تعیین می‌کند.مثال ساده‌ای از چند ریختی، فرمان اتومبیل است.عمل فرمان اتومبیل برای تمام اتومبیل‌ها بدون توجه به ساز و کاری که دارند، یکسان است.فرمان برای اتومبیل که به طور مکانیکی کار می‌کند یا با نیروی برق یا هر چیز دیگری، عمل یکسانی را انجام می‌دهد.بنابراین، پس از اینکه شما عملکرد فرمان را یاد گرفتید، می توانید فرمان هر اتومبیلی را کنترل کنید.همین هدف در برنامه نویسی نیز اعمال می‌شود. به طور کلی، مفهوم چند ریختی، اغلب با عبارت ((یک رابط، چندین روش))بیان می‌شود. این بدین معنی است که امکان طراحی رابط عمومی برای گروهی از عملیات مرتبط وجود دارد. چند ریختی یا چندشکلی (Polymorphism) به این معنا است که اشیاء می‌توانند در موقعیت‌های مختلف، رفتارهای متفاوتی بروز دهند. مثلاً یک تابع در صورتی که بر روی نمونه‌ای از کلاس آ فراخوانی شود، رفتار ب را بروز دهد در حالی که اگر بر روی کلاس ج (که فرزند کلاس آ است) فراخوانی شود، رفتاری متفاوت انجام دهد.

انتزاع / تجرید
به این معنا است که بخشی از یک موجودیّت یک مفهوم را که میان همهٔ وارثان مشترک است، پیش تعریف کنیم. این توانایی منجر به داشتن نگاه مشابه به موجودیّت‌های مشابه می‌گردد.


=============================


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

نوع داده انتزاعی یا تجریدی (Data Abstract)
در زبان C++ انواع داده ای مختلفی مانند int,char,... تعریف شده اند و می توان از آنها در طول برنامه استفاده نمود اما نوع داده انتزاعی نوعی است که صرفا توسط خود کاربر تعریف می شود و نوع خاصی را شامل نمی شود و با ایجاد یک شی از آن نوع داده انتزاعی یا تجریدی می توان از داده ها و روال ها و رخدادهای درون آن بهره گرفت .
از این دسته می توان به Class, struct اشاره نمود که صدها و هزاران نوع از آنها را می توان با داده ها و روالهای مختلف تعریف نمود و با استفاده از یک یا چند شی آنها را در برنامه پیاده سازی کرد .

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

وراثت (Inheritance)
در کارخانه BMW ممکن است از یک سری خصوصیات و روالهای معینی برای مدلهای مختلف تولیدی استفاده نمود مانند آرم آن شرکت که در تمامی مدلهای تولیدی موجود است و در اصطلاح به آنها ارث رسیده است .
در برنامه نویسی شی گرا نیز همین گونه است یعنی برخی اوقات انواع داده انتزاعی به عنوان طرح کلی یا پدر ساخته می شود که در نوعهای دیگر یا فرزندان هم قابل استفاده است .

چند ریختی (polymorphism)
طرف میره کارخانه BMW و تقاضا می کند که روی همین دنده ای که وجود دارد یک دنده هوایی برای پرواز کردن هم قرار بگیرد. شرکت هم سیستمی را پیاد سازی می کند که مثلا دنده X مثل قبل کار کند و در این شرایط به دنده هوایی تبدیل شود .
در برنامه نویسی شی گرا هم این مورد صادق است و میتوان برای یک نمونه چندین تعریف مجزا را بیان نمود مثل عملگر جمع یا ... !!!

کلاس (Class)
همان طرح با خصوصیات و روالهای مشخص و تعریف شده در کارخانه است که با استفاده از آن یک نمونه را ساخته و به بازار وارد می کنند .

شی (Object)
همان مدلی است که در تهران زیر پای شخص خاصی است. یعنی استفاده از خصوصیات و روالهای تعریفی در Class برای استفاده از آن .


=============================

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

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

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

کپسوله سازی
همانطور که می دانید تمام برنامه ها از دو عنصر اصلی تشکیل می شوند : عبارت برنامه (کد) و داده ها . کد بخشی از برنامه است کد عملیات را اجرا می کند و داده ها اطلاعاتی است که توسط این عملیات تحت تاثیر قرار گرفته . کپسوله سازی یک مکانیزم برنامه نویسی است که کد و داده ها را با هم در یک جا قرار داده و هر دو را از استفاده نادرست و تداخل خارجی ایمن نگه می دارد .
در یک زبان شی گرا ، کد و داده ممکن است با هم در چنین روش محدود شوند که یک جعبه سیاه خود ظرف را ایجاد می کند . درون جعبه تمام داده های مورد نیاز و کد است . هنگامی که در این روش کد و داده ها با هم پیوند برقرار می کنند یک شی به وجود می آید . به عبارت دیگر یک شی ابزاری است که ازکپسوله سازی پشتیبانی می کند.
درون یک شی (کد وداده ها) یا هردو ممکن است برای آن شی محلی (خصوصی/Private) یا عمومی (Public) باشند.کد یا داده های محلی فقط توسط بخش دیگری از شی شناخته شده و قابل دست یابی هستند.
به همین دلیل کد یا داده محلی برای قطعه ای از برنامه که خارج از شی است قابل دسترس نمی باشد . هنگامی که کد یا داده ها عمومی هستند بخش ها دیگری از برنامه ممکن است به آنها دسترسی داشته باشند حتی اگر درون شی تعریف شده باشند بخش های عمومی یک شی برای ارائه یک ارتباط کنترل شده با عناصر محلی شی مورد استفاده قرار می گیرند.

چند ریختی
چند ریختی کمیتی است که به یک رابط امکان می دهد تا برای یک کلاس عمومی از عملیات مورد استفاده قرار می گیرد . عمل خاص توسط ذات حقیقی شی تعیین می شود.به عنوان مثال یک پشته را در نظر بگیرید . ممکن است برنامه ای داشته باشید که نیاز به سه نوع مختلف پشته داشته باشید یک پشته برای مقادیر صحیح ،یک پشته برای اعداد اعشاری و یک پشته برای کاراکترها مورد استفاده قرار می گیرد.در این صورت الگوریتمی که هر سه پشته را پیاده می کند یکسان است حتی اگر داده هایی که در آنها ذخیره می شود متفاوت باشند . در یک زبان غیر شی گرا نیاز خواهید داشت تا سه نوع مختلف از روال های پشته را ایجاد کرده . به هر کدام نام متفاوتی قرار داده و برای هر کدام از روابط خاص خودش استفاده کنید . به دلیل وجود چند ریختی در C++ می توانید یک مجموعه روال عمومی از پشته ایجاد کرده وآن را برای هر سه نوع به کار ببرید.
به طور کلی مفهوم چندریختی اغلب توسط عبارت "یک رابط چندین روشی" بیان می شود . این بدین معنی است که امکان طراحی یک رابط عمومی برای گروهی از عملیات مرتبط وجود دارد.
چند ریختی با اعمال رابط یکسانی که برای تعیین یک کلاس عمومی مورد استفاده قرار می گیرد . به کاهش پیچیدگی کمک می کند . این است وظیفه کامپایلر تا فعالیت خاصی (مثل متد) را برای اعمال روی آن انتخاب کند . شما به عنوان برنامه نویس نیاز ندارید تا این انتخاب را انجام دهید شما فقط نیاز دارید روابط عمومی را به خاطر سپرده و استفاده کنید.
زبان های برنامه نویسی شی گرای اولیه چون به صورت مفسری بودند از چند ریختی در زمان اجرا پشتیبانی می کردند. ولی چون C++ کامپایلری است پس هم در زمان اجرا و هم در زمان کامپایل از چند ریختی پشتیبانی می کند.

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

ROBOTICS

کاربر فعال مهندسی رباتیک
این پست از وب سایت شخصی «محمد ذات خواهی» کارشناس ارشد مهندسی شیمی گرایش کنترل برداشته شده است.

ایشان شی گرایی را در سی پلاس پلاس توضیح مفصلی داده است. اگر بیش از این می خواهید دیگر باید به کتب مرجع مراجعه نمایید.

==============

برنامه نویسی شی گرا یا Object Oriented Programming یا به صورت ساده OOP یک شیوه برنامه نویسی است که از اشیا برای برنامه نویسی و ساخت برنامه استفاده می کند. برای این که شما بتوانید یک برنامه شی گرا بنویسید باید با یک زبان برنامه نویسی مناسب که این ساختار را پشتیبانی می کند، برنامه بنویسید. بسیاری از زبان های برنامه نویسی روز نظیر JAVA و C++ و #C و PHP و ... OOP را پشتیبانی می کنند. برای آموزش مفاهیم OOP فرض را بر این قرار می دهم که خواننده با یکی از زبان های فوق آشنا ست و توانایی برنامه نویسی ساده شامل تعریف کردن متغیر ها، حلقه ، شرط و ... را می داند.

با این پیش فرض، در این جا قصد دارم مفاهیم و نحوه برنامه نویسی شی گرا را با مثال های مناسب خصوصا از نگاه مهندسی شیمی به زبان C++ توضیح دهم. در حال حاضر اکثر نرم افزار های حرفه ای مهندسی شیمی مثل ASPEN و HYSYS و FlUENT و ... با C++ نوشته شده اند. در هر صورت به نظر من بهترین زبان برنامه نویسی برای کار های مهندسی شیمی C++ است، چرا که هم از یک طرف می توان با قابلیت های فوق العاده سطح بالای آن کد نوشت و هم می توان در برنامه آن کد C نوشت.

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

فرض کنید که شما یک برنامه بازی می نویسید. در این بازی ممکن است اشیا مختلفی وجود داشته باشد. برای مثال یک ماشین را به عنوان یک شی در نظر بگیرید. اگر تصور کنیم که یک بازی 2 بعدی داریم که ماشین شما فقط در روی صفحه حرکت می کند، چه ویژگی هایی را می توان برای این شی تصور کرد؟ مثالا می توان در نظر گرفت این ماشین نام دارد، رنگ دارد، موقعیت کنونی آن در صفحه چیست و ... به این خصوصیت های شی ماشین در زبان برنامه نویسی data field می گوییم. همچنین تصور کنید که چه اعمالی را می توان از این ماشین تصور کرد. مثلا شروع به حرکت کن. بایست. به سمت راست بچرخ و ... در واقع یک سری تابع را می توان به این شی نسبت داد که قابلیت انجام آن را دارد. به این دستورات method می گوییم.

حال به این نکته می پردازیم که چگونه یک برنامه بنویسیم و این شی ماشین را به کامپیوتر بفهمانیم. برای این منظور یک مثال ساده با زبان C++ می نویسیم:

می دانید که در زبان C++ متغیر هایی که می توانید تعریف کنیم به صورت پایه ای به صورت char (یک بایت) ، عدد صحیح (int)و حقیقی (double یا float) و انواع مختلف مشابه این ها هستند. مثل int64 , bool , ...

ساختار داده با تعریف ساده تر در واقع یک متغیر جدید هستند. مثلا می خواهیم به این متغیر ها یک متغیر دیگر اضافه کنیم به نام Car . این قابلیت در زبان های شی گرا وجود دارد. در این صورت ما می توانیم هر جا که به یک متغیر از نوع ماشین نیاز داشتیم از آن استفاده کنیم. مثلا:

کد:
Car myCar;

هم چنان که اگر نیاز داشتیم به یک متغیر از نوع عدد حقیقی می نوشتیم:

کد:
float myFloat;

می بینید که ما به راحتی یک مفهوم یا در واقع یک شی به مفاهیم قابل فهم برای کامپیوتر تعریف نمودیم. و هر جا که آن را لازم داشته باشیم می توانیم از آن و ویژگی ها و متد هایش استفاده نماییم.

قبلا متوجه شدیم که توسط اشیا می توانیم در واقع متغیر های جدید به زبان برنامه نویسی اضافه کنیم. متغیر هایی که مفهوم فیزیکی یا ذهنی دارند. مثلا متغیری از جنس شی ماشین ، ماتریس، بردار و ... در واقع هر چه که در ذهن ما وجود داشته باشد می تواند یک شی یا کلاس باشد. در این قسمت نحوه تعریف یک کلاس در زبان C++ را نشان می دهم:

کد:
class Student {

};

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

کد:
int x;
double d2;
Student st1;
Student st2
;

در مثال بالا st1 و st2 دو شی از جنس Student هستند. ( همانطور که d2 از جنس double و x از جنس int است)

توجه کنید که واژه کلاس(class) به نوع متغیر اتلاق می شود و شی (object) به نمونه ای از آن متغیر که حافظه اشغال کرده است می گویند. یعنی در این جا Student کلاس و st1 شی است.

شما می توانید به کلاسی که تعریف کرده اید خواص جدیدی اضافه کنید. مثلا Student می تواند خواصی مثل شماره دانشجویی، نام، فامیلی، تعداد واحد گذرانده، معدل و ... داشته باشد. مثلا من این خواص را به کلاس Student اضافه می کنم:

کد:
class Student {

int number;
string name;
string family_name;
int passed_units;
double average_grade;

};

در کد های بالا خواص جدید از نوع متغیر های پیش فرض C++ (مثل int, double و .. ) و متغیر string (که خود یک کلاس در کتابخانه stl است) اضافه کردم که به کلاس Student مفهوم یک کلاس از نوع " دانشجو" می دهد.
شما می توانید هر خاصیت جدید را که مد نظر دارید به این کلاس اضافه کنید تا مفهوم و کاربرد بیشتری به آن بدهید.

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

کد:
// sample function to print student information
void print_student_information( Student  st )  {

cout << "Student Number: " << st.number << "\t"
  << "Name: " << st.name << st.family_name << "\n"
<< "Average grade: " << st.average_grade << "\n";

}

در کدهای بالا مشاهده می کنید که برای دسترسی به خاصیت های یک شی از عملگر نقطه (.) استفاده می کنیم. بعد از نام شی مورد نظر با تایپ نقطه معمولا محیط های برنامه نویسی لیستی از اعضای کلاس را برای راحتی کار شما نمایش می دهند. تابع print_student_information یک ورودی از جنس Student به نام st دریافت می کند و برخی از خواص آن را در صفحه کنسول نمایش می دهد. حال در کدهای زیر تابع بالا را فراخوانی می کنیم:

کد:
Student student1;

student1.number = 88103456;
student1.name = "Reza";
student1.family_name = "Rezaie";
student1.passed_units = 144;
student1.average_grade = 16.2;
 

print_student_information (student1);

در کد های بالا ابتدا یک شی به نام student1 ایجاد کردیم. سپس با استفاده از نقطه (.) کلیه خواص این شی (data members یا data fields) را مقدار دهی کردیم. سپس تابع print_student_information را فراخوانی کردیم تا اطلاعات این شی را چاپ کند.

نکته دیگر در کلاس ها سطح دسترسی به اعضای کلاس ها است. اگر کد فوق را در کامپایلر C++ اجرا کنید قطعا پیغام خطای مبنی براین که "اعضای کلاس Student قابل دسترسی نیستند" به شما خواهد داد. زیرا در C++ هر عضو کلاس می تواند public یا private یا protected باشد. وقتی یک عضو public باشد می توان توسط عملگر نقطه به اعضای آن دسترسی پیدا کرد (در بیرون از کلاس). در صورتی که private یا protected باشد نمی توان در خارج از کلاس به آن دسترسی داشت. توضیح بیشتر این مفهموم را در پست دیگری بیان خواهم کرد. ولی برای اجرا شدن کدهای بالا کلمه public را در کلاس به این صورت قرار می دهیم تا بتوان به اعضای آن دسترسی پیدا کرد:

کد:
class Student {

      public:

int number;
string name;
string family_name;
int passed_units;
double average_grade;

};


آن چه که در این جا قابل تامل است، این است که تک تک فیلد ها یا خاصیت ها باید جدا مقدار دهی شوند و در زمان استفاده هم، هر کدام جدا توسط نقطه مورد استفاده قرار می گیرند. آن چه که ما در واقع در این جا انجام داده ایم کپسوله کردن داده ها در یک مفهوم جدید به نام Student است. این در حالی است که ما می توانستیم هرکدام از متغیر ها را جدا بدون تعریف کلاس نیز مقدار دهی کرده و استفاده کنیم ولی در آن صورت هیچ مفهومی به نام "دانشجو" نداشتیم. کپسوله کردن داده ها ( data encapsulation) اولین خاصیت برنامه نویسی شی گرا است که در این بخش شما با آن آشنا شدید. کپسوله کردن داده ها یعنی کنار هم قرار دادن متغیرهای موجود و ایجاد یک تعریف جدید. مثل کلاس Student که از متغیر های موجود int و double و string ایجاد شده است. 2 خاصیت مهم دیگر در برنامه نویسی شی گرا به نام وراثت (inheritance) و چندشکلی بودن( polymorphism) نیز وجود دارد که در درس های بعدی بررسی خواهیم کرد.

برای پایان این درس نیز مقایسه بین حالت کپسوله کردن داده ها و کپسوله نکردن آن را با مثال نشان می دهم:

تصور کنید برای مثال بالا در متن درس، بخواهیم 10 دانشجو ایجاد کرده و اطلاعات آن ها را چاپ کنیم، در این صورت می توانیم کد زیر را اجرا کنیم:

کد:
 const int students_count = 10;
  Student students[students_count];
  for (int i=0; i< students_count; i++) {
    students[i].number = i;
    students[i].name = "Test Name";
    students[i].family_name = "Family Name";
    students[i].passed_units = 144;
    students[i].average_grade = 15.2;
  }
  
  for (int i=0; i< students_count; i++) { 
   print_student_information(students[i]);
  }


کد بالا یک آرایه 10 تایی از Student به نام students ایجاد می کند و همه آن ها به صورت یکسان مقدار دهی می کند. سپس در یک حلقه دیگر تابع print_student_information را 10 بار فراخوانی کرده و هر بار یکی از Student ها را برای چاپ می فرستد. در ادامه همین عملیات را بدون تعریف کلاس Student انجام می دهیم:

کد:
 int students_number[ students_count ]; 
  string students_name[ students_count ];
  string students_family_name[ students_count ];
  int students_passed_units[ students_count ];
  double students_average_grade[ students_count ];
 
  for (int i=0; i< students_count; i++) {
    students_number[i] = i;
    students_name[i] = "Test Name";
    students_family_name[i] = "Family Name";
    students_passed_units[i] = 144;
    students_average_grade[i] = 15.2;
  }
 
   for (int i=0; i< students_count; i++) { 
     print_student_information( students_number[i], students_name[i],
      students_family_name[i], students_passed_units[i], students_average_grade[i]);
   }


در کدهای بالا هر کدام از خاصیت های name و family_name و ... به طور مجزا در یک آرایه ذخیره شده است. و برای چاپ آن باید به تابع print_student_information هر 5 خاصیت را پاس کنید در صورتی که در حالت کپسوله شده فقط یک شی از جنس Student پاس می شد. تصور کنید که برنامه شما دارای تابع های فراوانی باشد که با اطلاعات "دانشجو" سروکار دارد. در این صورت شما باید به همه آن توابع، تمام 5 خاصیت را پاس کنید ( ممکن است خاصیت ها خیلی بیشتر هم باشند.) در صورتی که اگر کلیه خواص (یا داده ها) در کلاسی به نام Student کپسوله شده باشد، به تمامی توابع مورد نیاز فقط شی Student را پاس خواهید کرد. وجود مفهوم یا متغیر Student به شما کمک می کند که داده های مربوط به یک Student در یک بلوک با مفهوم "دانشجو" ذخیره شده باشند تا این که هر کدام جدا گانه در آرایه های مختلف باشند.

این در حالی است که از کلاس های تعریف شده در کلاس های جدید هم می توان استفاده کرد و کلاس ها به صورت تودرتو از یکدیگر استفاده می کنند. ( مثل string که یک کلاس از پیش تعریف شده است و ما در این جا به عنوان خاصیت از آن استفاده کردیم.) در نتیجه اگر داده ها کپسوله نباشند کار کردن با آنها به مراتب سخت تر و سخت تر می شود و شما باید آرایه ها و متغیر های زیادی ایجاد کرده و تعداد آرگومان های توابع به سرعت زیاد می شوند. طوری که هرچه برنامه شما کد بیشتری داشته باشد، نامفهوم تر و گنگ تر می شود. در صورتی که استفاده از مفاهیمی که با ذهن بیشتر مانوس هستند ( در این جا "دانشجو") کد را خوانا تر می کند و حجم کد ها کم تر می شود.
 

ROBOTICS

کاربر فعال مهندسی رباتیک
اولین تجربه کار با میکروکنترلر!

ممکن است شما تا پیش از این میکروکنترلر ندیده باشید و نمی دانید چه شکلی است. در این صورت نگران نباشید و به این پست را بخوانید

بردی که تهیه کردید یعنی را Discovery kit for STM32 F4 series در جهتی که در تصویر زیر می بینید قرار دهید




مربعی سیاه رنگ در وسط برد هست. در شکل فوق دور آن با دایره زرد رنگ مشخص شده است. این همان میکروکنترلر است! اگر رویش را بخوانید (بر عکس کنید) موارد زیر را نوشته است

کد:
STM32F407
VGT6     Z
...

یعنی مدل میکروکنترلر STM32F407 است

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

اگر سمت چپ پروگرامر (بالا سمت چپ تصویر) را نگاه کنید یک پین هدر 6 تایی می بینید. این خروجی پروگرامر برای میکروکنترلر های دیگر است. یعنی اگر شما خودتان بعدا مداری طراحی کردید با این پین هدر می توانید میکروی آن را پروگرام کنید.

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

بقیه موارد روی شکل کاملا واضح اند و نیاز به توضیح ندارند. نارنجی شتاب سنج ؛ سبز مبدل دیجیتال به آنالوگ ؛ فیروزه ای میکروفون ؛ آبی خروجی صدا (نیازمند اتصال به هدفون یا اسپیکر) ؛ بنفش پورت usb میکروکنترلر هست

هنگامی که برد را می خرید برنامه ای پیشفرض روی آن نصب است. جهت دیدن آن شما از طرق پورت بالا (پورت پروگرامر) بورد را به کامپیوتر متصل کنید. می بینید چراغ های روشن شدند یعنی برد شما سالم است. سپس دکمه آبی رنگ را فشار داده و رها نمایید. اکنون سنسور شتاب سنج فعال شده و برنامه بر اساس شتاب led ها را روشن و خاموش می کند. برد را در دست گرفته و تکان دهید. می بینید که LED ها تغییر وضعیت می دهند. اگر هم اکنون بورد را از USB پاین نیز به کامپیوتر وصل کنید کار موس را انجام می دهد.

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

ROBOTICS

کاربر فعال مهندسی رباتیک
چند فایل ضروری

با توجه به این که سرعت بروزرسانی سایت ST بالا است لینک مستقیم نمی دهم. فقط صفحه را معرفی میکنم و می گویم چه فایلی را دانلود کنید

نام صفجه : Discovery kit for STM32F407/417 lines - with STM32F407VG MCU
آدرس صفحه: http://www.st.com/web/en/catalog/tools/PF252419
نام فایل اول: Programming Manual
نام فایل دوم: User Manual Discovery kit for STM32F407/417 lines


نام صفجه : STM32F407VG
آدرس صفحه: http://www.st.com/web/en/catalog/mmc/FM141/SC1169/SS1577/LN11/PF252140
نام فایل اول: Datasheet
نام فایل دوم: Reference Manual

علاوه بر چهار فایل فوق، فایل زیر را نیز دریافت نمایید

CoIDE User Guide
کد:
www.ece.nus.edu.sg/ee3032/html/Common/CoIDE_Guide.pdf


مرجع اصلی Reference Manual است.
فایل Programming Manual مرجع اصلی و کامل زبان اسمبلی است. این جا چون ما با سی پلاس پلاس برنامه می نویسیم لازم به دانستن آن نداریم.
 

ROBOTICS

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

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

۱- کامپایلر

سایت زیر بروید

کد:
https://launchpad.net/gcc-arm-embedded

اگر از ویندوز استفاده می کنید فایل زیر را دانلود و نصب نمایید. چون نصبش راحت است توضیح نمی دهم

کد:
gcc-arm-none-eabi-...-win32.exe

توجه کنید که حتما فایل exe رادانلود نمایید. فایل zip نصب دستی است که کار راحتی نیست.

بعد از نصب فایل زیر را اجرا نمایید

کد:
INSTALL_DIR\bin\gccvar.bat

اگر از لینوکس استفاده می کنید فایل زیر را دانلود نمایید

کد:
 gcc-arm-none-eabi-...-linux.tar.bz2

جهت راهنمای نصب (لینوکس) فایل readme.txt را مطالعه نمایید

۲- محیط یکپارچه توسعه نرم‌افزار

به سایت زیر بروید

کد:
http://www.coocox.org/CooCox_CoIDE.htm

در پایین صفحه روی

کد:
Download the latest CoIDE directly

کلیک کنید و دانلود نمایید. در صورت نیاز حساب کاربری بسازید

۳- نصب درایور STM32 ST-LINK

به سایت www.st.com بروید و مسیر زیر را دنبال نمایید

کد:
Home > Tools and Software > Development Tool Hardware > Development Tool Hardware for MCUs > Development Tool Hardware for STM8 MCUs > Debug Hardware for STM8 MCUs > ST-LINK/V2

فعلا معادل آدرس زیر است. با توجه به بروزرسانی های زیاد ممکن است لینک زیر از کار بیافتد. در صورتی که لینک زیر کار نکرد از همان روش بالا استفاده کنید

http://www.st.com/web/catalog/tools/FM146/CL1984/SC724/SS1677/PF251168

در این سایت فایل زیر را دانلود نمایید و آن را از حالت فشرده خارج نمایید

کد:
ST-LINK/V2 USB driver for Windows ...

در صورتی که برد به رایانه وصل است آن را قطع نمایید و تا آخر این قسمت و قسمت آتی به رایانه متصل نکنید.

فایل زیر را با حالت administrator اجرا کنید.

کد:
stlink_winusb_install.bat

سپس یکی از دو فایل زیر را بر اساس ۲۳ یا ۶۴ بیتی یودن ویندوزتان اجرا نمایید و مراحل آن را بروید (این قسمت ساده است و توضیح نمی خواهد)

کد:
dpinst_amd64.exe    // windows 64 bit
dpinst_x86.exe      // windows 32 bit

۴- نصب واسط کاربری STM32 ST-LINK

از همان صفحه ای که در بخش قبل گفته شد فایل زیر را دانلود نمایید

کد:
STM32 ST-LINK utility

این فایل را اجرا کرده و آن را نصب کنید. (این قسمت ساده است و توضیح نمی خواهد)

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

ROBOTICS

کاربر فعال مهندسی رباتیک
اولین برنامه

برنامه CoIDE را اجرا نمایید.

اگر اولین بار است که نرم افزار را اجرا کی کنید ، ابتدا از منوی Project گزینه ی "Select Toolchain path" را انتخاب نمایید. سپس آدرس محلی را که کامپیلر را در آن نصب کردید وارید نمایید. مثلا من از آدرس زیر استفاده کردم.

کد:
C:\Program Files (x86)\GNU Tools ARM Embedded\4.8 2013q4\bin


اکنون از منوی Project گزینه ی "New Project" را انتخاب نمایید. در پنجره باز شده نام برنامه خود را وارد کنید. به عنوان مثال first را وارد می کنیم. در صورت تمایل محل پوشه برنامه را تغییر می دهید. سپس Next می زنید. در صفحه بعدی روی Chip کلیک کنید تا سبز شود. سپس Next می زنید. در سمت چپ پنجره جدید شرکت سازنده میکروکنترلر را انتخاب می کنید. برد خریداری شده محصول ST است پس روی آن کلیک کنید تا باز شود. حال باید سری میکروکنترلر را باید انتخاب کنید که در این جا STM32F4x را انتخاب می کنیم. در نهایت مدل میکروکنترلر (در اینجا STM32F407VG) انتخاب کرده و روی Finish کلیک کنید.

اکنون پروژه ساخته شده است. برای راحتی کار می توانید از مخزن (Repository) کتابخانه ها (امکانات داخلی میکرو و درایور وسایل خارجی) را تیک بزنید تا به پروژه تان اضافه شود.

چون برنامه اول است و نمی خواهیم پیچیده باشد فقط GPIO را تیک بزنید. چون این کتابخانه وابسته به کتابخانه های دیگر نیز هست با تیک زدن آن به طور خودکار بعضی از کتابخانه های دیگر نیز تیک می خورد. تیک هایی که به طور خودکار اضافه می شوند را تغییر ندهید.

در گوشه سمت چپ روی main.c کلیک کنید تا باز شود. برنامه به صورت زیر مشاهده می کنید.

PHP:
int main(void)
{

    while(1)
    {
    }
}

برنامه نوشته شده را به صورت زیر تغییر دهید و ذخیره کنید

PHP:
#include "stm32f4xx.h"
#include "stm32f4xx_rcc.h"
#include "stm32f4xx_gpio.h"


int main(void)
{
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE);


    while(1)
    {

    }

    return 0;
}


دکمه F7 را بزنید تا برنامه یتان کامپایل شود.

اگر در پایین عبارت "BUILD SUCCESSFUL" را مشاهد کرده اید یعنی برنامه شما به صورت صحیح کامپایل شده است.

اکنون برد را به رایانه متصل کنید (ارتباط USB از سمت پروگرامر). توجه کنید که دو جامپر ST-LINK وصل باشد. این جامپر زمانی متصل کنید که می خواهید برنامه را روی میکرو بریزید. وقتی که برنامه را ریختید این جامپر را قطع کنید تا برنامه بدون اتصال به پروگرامر اجرا شود (مانند این که برد درگر پروگرامر ندارد)

سپس در نوار ابزار (پایین منو) روی "Download Code to Flash" کلیک کنید و منتظر بمانید تا پیام زیر را مشاهده نمایید.

کد:
Erase:     Done
Program:     Done
Verify:     Done

اکنون می توانید جامپر پروگرامر را در بیارید و از برنامه یتان لذت ببرید!

تبریک می گویم شما یک برنامه خالی نوشتید که هیچ کار نمی کند و فقط میکروکنترلر را روشن نگه می دارد. سپس آن را کامپایل کردید و در نهایت آن را روی میکرو پروگرام کردید و اجرا کردید.

از این به بعد هر بار که خواستیم برنامه ای بنویسیم این مراحل را تکرار می کنید ( قسمت Select Toolchain path لازم نیست). تنها تفاوت این است که برنامه main.c دارای خطوط و دستورات بیشتری خواهد بود.
 

ROBOTICS

کاربر فعال مهندسی رباتیک
کار با پورت های ورودی و خروجی عمومی

کار با پورت های ورودی و خروجی عمومی

کار با پورت های ورودی و خروجی عمومی

میکروکنترلر های Cortex-M4 دارای تعدادی پورت ورودی و خروجی عمومی هستند که هر پایه آن (پین) را می توانید ورودی و یا خروجی تعریف کنید.

میکروکنترلر STM32F407 دارای پورت های ورودی و خروجی عمومی 16 پایه ای است. پورت های ورودی و خروجی عمومی به صورت GPIOx نام گذاری می شوند. که x نام اختصاصی هر پورت است. یعنی GPIOA و GPIOB و ...

برای فعال سازی هر پورت در تابع اصلی (main) لازم است که کد زیر وارد شود.

کد:
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOx, ENABLE);

به جای x در کد بالا نام پورت را وارد کنید. مثلا در پست قبلی ما پورت D را فعال کرده بودیم.



هر پورت دارای 10 رجیستر برای کار با آن است که آشنایی با آن ضروری است

به علت 32 بیتی بودن میکروکنترلر (در نتیجه 32 بیتی بودن رجیستر ها) بهتر است از عدد دهی هگزا دسیمال استفاده شود

کد:
0000 ==> 0
0001 ==> 1
0010 ==> 2
0011 ==> 3
0100 ==> 4
0101 ==> 5
0110 ==> 6
0111 ==> 7
1000 ==> 8
1001 ==> 9
1010 ==> A
1011 ==> B
1100 ==> C
1101 ==> D
1110 ==> E
1111 ==> F

بیت: کوچکتربن واحد حافظه که می تواند یک یا صفر باشد
نیمبل (نیم بایت): معادل چهار بیت
بایت: معادل هشت بیت
نیم کلمه: معادل 16 بیت
کلمه: معادل 32 بیت
جمله ، پارگراف ، صفحه معادل ...

یک رجیستر از 32 بیت (صفر یا یک) تشکیل شده است. بنابراین از 8 تا نیمبل تشکیل شده است. هر نیمبل را با یک عدد هگزا دسمیال تشکیل شده است.
بنابراین یک کلمه را با 8 رقم هگزا دسیمال نشان می دهند. برای این که کامپایلر بفهمد که عدد وارد شده هگزادسیمال است ابتدای آن صفر ایکس (کوچک) می گذاریم یعنی

کد:
0x00000000
0x00000001
.
.
.
0xFFFFFFF

رجیستر پورت های میکروکنترلر های Cortex-M4 به صورت زیر نام گذاری شده است

کد:
MODER  ==> mode register
OTYPER  ==> output type register
OSPEEDR  ==> output speed register
ODR  ==> output data register
PUPDR  ==> pull-up/pull-down register
IDR  ==> input data register
BSRR  ==> bit set/reset register
LCKR  ==> configuration lock register
AFRL  ==> alternate function low register
AFRH  ==> alternate function high register

در این پست شش تای اول را توضیح می دهیم و چهار تای دیگر را در پست های بعد شرح می دهیم.

MODER

این رجیستر از از شانزده قسمت دو بیتی تشکیل شده است. هر قسمت مشخص می کند که پایه متناظر آن ورودی، خروجی، جانشین یا آنالوگ باشد

کد:
00: Input (reset state)
01: General purpose output mode
10: Alternate function mode
11: Analog mode




OTYPER

این رجیستر مشخص می کند که نوع خروجی چه باشد.

هر بیت یه یک پایه اختصاص دارد. بنابراین 16 بیت پر ارزش به صورت رزرو هستند.

کد:
0: Output push-pull (reset state)
1: Output open-drain



OSPEEDR

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

کد:
00: Low speed
01: Medium speed
10: Fast speed
11: High speed





ODR

این رجیستر مشخص می کند که هر پایه پورت در صورتی که خروجی باشد یک باشد یا صفر.

هر بیت یه یک پایه اختصاص دارد. بنابراین 16 بیت پر ارزش به صورت رزرو هستند.





PUPDR

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

کد:
00: No pull-up, pull-down
01: Pull-up
10: Pull-down
11: Reserved



IDR

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

هر بیت یه یک پایه اختصاص دارد. بنابراین 16 بیت پر ارزش به صورت رزرو هستند.



تذکر: مقادیر رزرو باید مقادیر پیش فرض باقی بمانند. بنابراین آن ها را تغییر ندهید. در ادامه مقادیر پیش فرض آمده است.

کد:
MODER
• 0xA8000000 for port A
• 0x00000280 for port B
• 0x00000000 for other ports


OTYPER
• 0x00000000


OSPEEDR
• 0x000000C0 for port B
• 0x00000000 for other ports


ODR
• 0x00000000


PUPDR
• 0x6400 0000 for port A
• 0x0000 0100 for port B
• 0x0000 0000 for other ports


IDR
0x0000XXXX (where X means undefined)


مثال یک

با توجه به این که LED های برد به پایه های D12 تا D15 وصل هستند و با یک شدن آن (در این برد 3 ولت در حالت استاندارد 3/3 ولت) Led روشن و با صفر شدن آن خاموش می شود. در مثال ها از این پایه ها به عنوان خروجی استفاده می کنیم. شما می توانید با سیم پایه های دیگر را به بردبرد ببرید و با آن کار کنید.

برنامه ای بنویسید که ورودی های C12 تا C15 را بخواند و مقدار آن را در خروجی D12 تا D15 بنویسد.

PHP:
#include "stm32f4xx.h"
#include "stm32f4xx_rcc.h"
#include "stm32f4xx_gpio.h"

int main()
{
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, ENABLE);
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE);

    GPIOC->MODER=0x00000000;
    GPIOD->MODER=0x55000000;
    GPIOC->PUPDR=0x55000000;

    while(1)
    {
        GPIOD->ODR=GPIOC->IDR;
    }

    return 0;
}

یک روش ایجاد تاخیر

در مواقعی ای که زمان دقیق تاخیر برایتان اهمیت ندارد می توانید از روش زیر استفاده کنید.

PHP:
void delay()
{
    long double i,j,m,n;
    m=1;
    n=1;
    for(i=0;i<500000;i++)
    {
        for(j=0;i<50000;i++)
        {
            m=m/n;
        }
    }
}

مثال دو

برنامه ای بنویسید که LED های روی برد با همدیگر چشمک بزنند

PHP:
#include "stm32f4xx.h"
#include "stm32f4xx_rcc.h"
#include "stm32f4xx_gpio.h"

void delay()
{
    long double i,j,m,n;
    m=1;
    n=1;
    for(i=0;i<500000;i++)
    {
        for(j=0;i<50000;i++)
        {
            m=m/n;
        }
    }
}



int main()
{
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE);

    GPIOD->MODER=0x55000000;


    while(1)
    {

        GPIOD->ODR=0x0000F000;
        delay();
        GPIOD->ODR=0x00000000;
        delay();
    }

    return 0;
}


تمرین

1- در مثال یک ، ورودی ها را به صورت پایین کش، بالاکش و معمولی راه اندازی کنید و عملکرد برنامه ها را مقایسه کنید
2- در مثال دو ، سرعت خروجی و نوع خروجی را تغییر دهید و عملکرد برنامه ها را مقایسه کنید
3- برنامه چراغ راهنمایی بنویسید که به صورت خود کار ابتدا سبز 4 ثانیه سپس زرد 1 ثانیه و سپس قرمز شود 6 ثانیه. چون از روش غیر دقیق برای تاخیر استفاده می کنید لازم میست حتما دقیق باشد
4- برنامه ربات تعقیب خط دو سنسوره بنویسید با فرض این که مسیر درست آن است که خط بین دو سنسور باشد. (رویکرد سنسور بزرگ)
5- برنامه ربات تعقیب خط دو سنسوره بنویسید با فرض این که مسیر درست آن است دو سنسور درون خط باشند. (رویکرد سنسور کوچک)

در پست بعدی، دستورات بیشتری در مورد کار با این 6 رجیستر معرفی می کنیم و سپس تمرین های سخت تری هم مطرح می کنیم.
 

پیوست ها

  • GPIOx_PUPDR.jpg
    GPIOx_PUPDR.jpg
    16.3 کیلوبایت · بازدیدها: 0
آخرین ویرایش:

yosoufe

متخصص خودرو
کاربر ممتاز
آقا جایی نمی شناسی کیت آموزشی شو ارزون بده؟

یه روش محاسباتی سریع می شناسی واسه تبدیل این باینری به هگزا؟ آخه رجیسترهای 32 بیتی داره و همین جوری عدد دادن بهشون خیلی وقت گیره! یه بار به صورت باینری عدد باید بدم بعد بشمریم که کدوم بیت مربوط به کدوم پایه است بعد تبدیل ش کنیم به هگزا و .... احتمال خطا توش زیاده! تو AVR که پورت 8 تایی بود واسه خودش کلی اشتباه می کردم تازه رجیستر ها هم اکثرا 8 بیتی بودن ولی اینجا که پورت ها 16 تایی و بعضی رجیسترها 32 بیتی هستند احتمال جا به جا شدن، به اشتباه، صفر و یک ها زیاده! راهی نمی شناسی که این احتمال خطا کم بشه؟

مرسی
 
آخرین ویرایش:

ROBOTICS

کاربر فعال مهندسی رباتیک
آقا جایی نمی شناسی کیت آموزشی شو ارزون بده؟

یه روش محاسباتی سریع می شناسی واسه تبدیل این باینری به هگزا؟ آخه رجیسترهای 32 بیتی داره و همین جوری عدد دادن بهشون خیلی وقت گیره! یه بار به صورت باینری عدد باید بدم بعد بشمریم که کدوم بیت مربوط به کدوم پایه است بعد تبدیل ش کنیم به هگزا و .... احتمال خطا توش زیاده! تو AVR که پورت 8 تایی بود واسه خودش کلی اشتباه می کردم تازه رجیستر ها هم اکثرا 8 بیتی بودن ولی اینجا که پورت ها 16 تایی و بعضی رجیسترها 32 بیتی هستند احتمال جا به جا شدن، به اشتباه، صفر و یک ها زیاده! راهی نمی شناسی که این احتمال خطا کم بشه؟

مرسی

جایی ارزون نمی شناسم. فعلا ارزون ترین جای که دیدم 95 هزار تومان پولشه

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

1- روش دستی: هر رجیستر را به صورت 8 تا نیمبل بینویسی یعنی

کد:
 - - - -  , - - - -  , - - - -  , - - - -  , - - - -  , - - - -  , - - - -  , - - - -

بعد هر نیمبل را تبدیل کنی

2- استفاده از ماشین حساب ویندوز : یکی از حالت هاش Programer هست. اول تیک باینری را فعال می کنی. بعد عددت را وارد می کنی. بعد تیک هگزا دسیمال را می زنی و عدد را مشاهده می کنی.

3- از نرم فزار های ریاضی مانند متلب، اکتاو،سایلب

4- اصلا تبدیل نکنی و به صورت باینری بنویسی به جای صفر ایکس ، بنویس صفر بی و عددت را باینری وارد کن

کد:
0xAAB413E3
0b10101010101101000001001111100011

این روش باعث می شود که اصلا اشتباه نکنی
 

ROBOTICS

کاربر فعال مهندسی رباتیک
کار با پورت های ورودی و خروجی عمومی - قسمت دوم

دستور زیر یک پایه از پورت را صفر می کند.

کد:
GPIO_ResetBits(GPIOx,GPIO_Pin_y);

دستور زیر یک پایه از پورت را یک می کند.

کد:
GPIO_SetBits(GPIOx,GPIO_Pin_y);

دستور زیر یک پایه از پورت را معکوس می کند. یعنی اگر صفر باشد آن را یک می کند و اگر یک باشد آن را صفر می کند.

کد:
GPIO_ToggleBits(GPIOx,GPIO_Pin_y);

دستور زیر یک پایه از پورت را می خواند.

کد:
GPIO_ReadInputDataBit(GPIOx,GPIO_Pin_y);

دستور زیر پورت را می خواند.

کد:
GPIO_ReadInputData(GPIOx);

دستور زیر مقدار BitVal را در یک پایه ی پورت می نویسد.

کد:
GPIO_WriteBit(GPIOx,GPIO_Pin_y,BitVal);

دستور زیر مقدار PortVal را در پورت می نویسد.

کد:
GPIO_Write(GPIOx,PortVal);

دستور زیر پورت را غیر فعال می کند.

کد:
GPIO_DeInit(GPIOx);


تمرین

1- برنامه چشمک زن و برنامه چراغ راهنما را با دستورات GPIO_ResetBits و GPIO_SetBits بنویسید
2- برنامه چشمک زن را با دستور GPIO_ToggleBits بنویسید
3- برنامه ربات تعقیب خط با سه سنسور بنویسید. فرض شود مسیر درست وقتی است که سنسور وسط روی خط و دو سنسور دیگر خارج خط باشند. در این تمرین چینش سنسوز ها خطی یا مثلثی فرض شود.
4- برنامه ربات تعقیب خط با چهار سنسور (روی یک خط) بنویسید. فرض شود مسیر درست وقتی است که دو سنسور میانی روی خط و دو سنسور دیگر خارج خط باشند.
5- برنامه ربات تعقیب خط با چهار سنسور (چینش لوزی) بنویسید. فرض شود مسیر درست وقتی است که دو سنسور عقب و جلو روی خط و دو سنسور راست و چپ خارج خط باشند.
 

yosoufe

متخصص خودرو
کاربر ممتاز
می شه به جای این ها هم مستقیم به رجیستر ODR ش مقدار داد یا رجیستر IDR رو خوند دیگه؟

اینا هم احتمال خطا تو مقدار دهی پایه ها رو می اره پایین! درسته؟

یه سوال دیگه! تو اکثر دستورات دو تا آرگومان هست! آرگومان دوم شماره پایه (بیت) پورت است دیگه! درسته؟ این شماره از صفر شروع می شه تا 15 یا از یک تا 16؟

یه سوال دیگه! نرم افزارش کتابخونه delay نداره قبلش include کنیم و ازش استفاده کنیم؟
 

ROBOTICS

کاربر فعال مهندسی رباتیک
می شه به جای این ها هم مستقیم به رجیستر ODR ش مقدار داد یا رجیستر IDR رو خوند دیگه؟

صد در صد. من خودم کار با رجیستر ODR و IDR را ترجیح می دهم چون باعث افزایش سرعت اجرای برنامه می شود. در برنامه نویسی هر وقت می شود کاری را مستقیم با رجیستر انجام داد نباید رفت سراغ تابع.

اما بعضی ها، از رجیستر ها خوششان نمی آید! آن ها مختارند از توابع فوق استفاده کنند.


اینا هم احتمال خطا تو مقدار دهی پایه ها رو می اره پایین! درسته؟

توی تک پایه آری. اما تو کل پورت خیر

یه سوال دیگه! تو اکثر دستورات دو تا آرگومان هست! آرگومان دوم شماره پایه (بیت) پورت است دیگه! درسته؟ این شماره از صفر شروع می شه تا 15 یا از یک تا 16؟

از صفر تا پانزده است. مثال زیر را ببین

کد:
    GPIO_SetBits(GPIOD, GPIO_Pin_14);

در این جا پایه 14 ی پورت D را یک کردیم

نرم افزارش کتابخونه delay نداره قبلش include کنیم و ازش استفاده کنیم؟

ندارد.

ابتدا باید کار با رجیستر های کلاک و تایمر را یاد بگیرید. بعد تابع دقیق delay را می نویسیم که آرگومانش میکروثانیه،...، ثانیه، ...، یا ساعت باشد
 

ROBOTICS

کاربر فعال مهندسی رباتیک
کار با پورت USB در دسته Device در خوشه ی CDC با درایو VCP

پورت USB خود دارای چند خوشه است. موس، کیبرد، مودم، پرینتر، گیم پد و ... از خوشه های یکسانی استفاده نمی کنند. 256 خوشه وجود دارد! در ادامه چند تاش ذکر شده است

کد:
ADC  ==>  Audio Device Class 
CDC  ==>  Communications Device Class  
HID  ==>  Human Interface Device
MSC  ==>  Mass storage Class
PDC  ==>  Printer Device Class
PHD  ==>  Personal Healthcare device
PID  ==>  Physical Interface Device
SID  ==>  Still Imaging Device
VDC  ==>  Video Device Class

هر دستگاه USB جز یکی از 3 دسته زیر است

1- ابزار Device
2- مهمان Host
3- همزمان ابزار و مهمان Dual

دو راه برای ارتباطی برای USB وجود دارد
1- ارتباط مستقیم یک به یک (یکی مهمان و دیگری ابزار)
2- ارتباط چند به یک ( یک مهمان و بقیه با هاب به مهمان وصل می شوند)


همان طور که دیده می شود به علت تنوع خوشه ها ، دسته ها و راه ارتباطی نوشتن برنامه کار USB کار هر کس نیست. همچنین علاوه بر نوشتن برنامه میکرو ، لازم است برای کامپیوتر نیز درایور نوشت!!!

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

به علت تنوع روش ها و ... کتابخانه استانداردی وجود ندارد.

هر چند نرم افزار CooCox CoIDE کتابخانه های برای کار با USB قرار داده، اما کار نمی کند و مشکلات کد نویسی دارد!

چهار ماه پیش کاربر xenovacivus در یکی از سایت ها ! کد اصلاح شده کتابخانه کار با پورت USB در دسته Device در خوشه ی CDC با درایو VCP را منتشر کرد! کتابخانه را می توانید از لینک زیر دانلود کنید.

http://roboticseng.persiangig.com/Cortex-M4/STM32F4_VCP.zip

درایور آن را هم می توانید از سایت ST دانلود کنید:


کد:
STSW-STM32102
STM32 Virtual COM Port Driver 

http://www.st.com/web/en/catalog/tools/PF257938

ابتدا درایور را نصب کنید و سپس رایانه یتان را ریستارت نماید

برنامه نویسی میکروکنترلر جهت کار پورت USB در دسته Device در خوشه ی CDC با درایو VCP

اکنون یک پروژه جدید بسازید ، در مخزن تیک های CooCox CoIDE تیک های GPIO - EXTI - USART - MISC را فعال کنید.

کتابخانه را در پوشه ی پروژه کپی نمایید. سپس آن را به پروژه خود بیافزایید.

قبل تابع اصلی (main) دستورات زیر را وارد کنید.

کد:
#define HSE_VALUE ((uint32_t)8000000) // STM32 discovery uses a 8Mhz external crystal

#include "stm32f4xx.h"
#include "stm32f4xx_conf.h"
#include "stm32f4xx_gpio.h"
#include "stm32f4xx_rcc.h"
#include "stm32f4xx_exti.h"
#include "usbd_cdc_core.h"
#include "usbd_usr.h"
#include "usbd_desc.h"
#include "usbd_cdc_vcp.h"
#include "usb_dcd_int.h"

//The USB data must be 4 byte aligned if DMA is enabled. This macro handles the alignment, if necessary.
__ALIGN_BEGIN USB_OTG_CORE_HANDLE  USB_OTG_dev __ALIGN_END;

// The conditional "extern" ensures the weak declarations from startup_stm32f4xx.c are overridden.
#ifdef __cplusplus
 extern "C" {
#endif

void OTG_FS_IRQHandler(void)
{
  USBD_OTG_ISR_Handler (&USB_OTG_dev);
}

void OTG_FS_WKUP_IRQHandler(void)
{
  if(USB_OTG_dev.cfg.low_power)
  {
    *(uint32_t *)(0xE000ED10) &= 0xFFFFFFF9 ;
    SystemInit();
    USB_OTG_UngateClock(&USB_OTG_dev);
  }
  EXTI_ClearITPendingBit(EXTI_Line18);
}

#ifdef __cplusplus
}
#endif

دستور زیر به میکروکنترلر می گوید که کریستال خارجی ات 8 مگا هرتز است. این دستور برای افزایش دقت (زمانی) برنامه اضافه کردیم. از این به بعد در تمامی برنامه های که می نویسید از این دستور استفاده کنید.

کد:
#define HSE_VALUE ((uint32_t)8000000)

کتاب خانه های زیر به ترتیب شناسایی میکرو، پروت های ورودی خروجی، کلاک و وقفه (اینتراپت) است.

کد:
#include "stm32f4xx.h"
#include "stm32f4xx_conf.h"
#include "stm32f4xx_gpio.h"
#include "stm32f4xx_rcc.h"
#include "stm32f4xx_exti.h"

کتابخانه های زیر همان کتاب خانه های پورت USB هستند.

کد:
#include "usbd_cdc_core.h"
#include "usbd_usr.h"
#include "usbd_desc.h"
#include "usbd_cdc_vcp.h"
#include "usb_dcd_int.h"

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

SystemInit

تابع زیر جهت فعال سازی کلاک سیستم است و کاربرد آن منحصر به USB نمی شود

کد:
SystemInit();

از این به بعد این تایع را در تمامی برنامه های که می نویسید اضافه کنید. (در ایتدای تابع اصلی)

USBD_Init
تابع زیر برنامه می فهماند که شما می خواهد از بین کلیه روش های موجود در USB فقط و فقط از دسته Device در خوشه ی CDC با درایو VCP استفاده کنید

کد:
USBD_Init(&USB_OTG_dev, USB_OTG_FS_CORE_ID, &USR_desc, &USBD_CDC_cb, &USR_cb);

put_char

تابع زیر یک کاراکتر را ارسال می کند.

کد:
VCP_put_char(chr);

به عنوان مثال:

کد:
uint8_t chr = 'R';
VCP_put_char(chr);

------------------

VCP_put_char('G');

------------------

uint8_t *chr = 'B';
VCP_put_char(*chr);

put_char

تابع زیر یک کاراکتر را می گیرد می کند.

کد:
VCP_get_char(chr);

به عنوان مثال:

کد:
uint8_t chr;
VCP_get_char(&chr);

------------------

uint8_t *chr;
VCP_get_char(chr);

send_str

تابع زیر رشته را می فرستد

کد:
VCP_send_str(str);

به عنوان مثال:

کد:
uint8_t str[]="Robotics Engineering";
VCP_send_str(str);

------------------

VCP_send_str("CooCox CoIDE");

get_string

تابع زیر یک رشته را می خواند.

کد:
VCP_get_string(str);

به عنوان مثال:

کد:
uint8_t Name[20];
VCP_get_string(Name);

برنامه نویسی کامپیوتر جهت کار پورت USB در دسته Device در خوشه ی CDC با درایو VCP

VCP برگرفته از عبارت Virtual COM Port است. یعنی ویندوز فکر می کند که پورت USB اش حذف شده است و پورت COM به سیستم اضافه شده است.

شما می توانید برنامه های بنویسید (با استفاده از کتاب خانه های دیگر یا با استفاده از اسمبلی) که کامپیوتر فکر کند پورت موازی دارد یا فکر کند USB به موس وصل شده است و ...

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

کد:
s6 = serial('COM6','BaudRate',9600,'DataBits',8,'Timeout',5,'Terminator' ,' ');
fopen(s6);
fprintf(s6,'Robotics');
fscanf(s6)
fclose(s6);

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

در برنامه نویسی متلب بستن پورت ضروری است. اگر برنامه یتان وسطش خطا داد به تنهایی این دستور را اجرا کنید تا بتوانید مجددا از این دستورات فوق استفاده کنید.
در کامپیوتر من پورت COM6 نامیده شد. شما باید شماره پورت را در کنترل پنل قسمت دیوایس منیجر ببینید و از آن استفاده کنید.


مثال
برنامه ای بنویسید که با ارسال اول حرف هر رنگ (به در حرف درشت) از طریق کامپیوتر، مقدار LED متناظر آن روی برد تغییر وضعیت دهد.

PHP:
#define HSE_VALUE ((uint32_t)8000000) // STM32 discovery uses a 8Mhz external crystal

#include "stm32f4xx.h"
#include "stm32f4xx_conf.h"
#include "stm32f4xx_gpio.h"
#include "stm32f4xx_rcc.h"
#include "stm32f4xx_exti.h"
#include "usbd_cdc_core.h"
#include "usbd_usr.h"
#include "usbd_desc.h"
#include "usbd_cdc_vcp.h"
#include "usb_dcd_int.h"




//The USB data must be 4 byte aligned if DMA is enabled. This macro handles the alignment, if necessary.
__ALIGN_BEGIN USB_OTG_CORE_HANDLE  USB_OTG_dev __ALIGN_END;


// The conditional "extern" ensures the weak declarations from startup_stm32f4xx.c are overridden.
#ifdef __cplusplus
 extern "C" {
#endif

void OTG_FS_IRQHandler(void)
{
  USBD_OTG_ISR_Handler (&USB_OTG_dev);
}

void OTG_FS_WKUP_IRQHandler(void)
{
  if(USB_OTG_dev.cfg.low_power)
  {
    *(uint32_t *)(0xE000ED10) &= 0xFFFFFFF9 ;
    SystemInit();
    USB_OTG_UngateClock(&USB_OTG_dev);
  }
  EXTI_ClearITPendingBit(EXTI_Line18);
}

#ifdef __cplusplus
}
#endif



int main(void)
{
        uint8_t charac;

    SystemInit(); // Set up the system clocks
    //SysTick_Config(SystemCoreClock / 1000); // Setup SysTick
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE);

    GPIOD->MODER=0x55000000;

    USBD_Init(&USB_OTG_dev, USB_OTG_FS_CORE_ID, &USR_desc, &USBD_CDC_cb, &USR_cb); // Setup USB

    while (1)
    {
        VCP_get_char(&charac);
        VCP_put_char(charac);

        switch(charac)
        {
        case 'G':
              GPIO_ToggleBits(GPIOD, GPIO_Pin_12);
              break;
        case 'O':
           GPIO_ToggleBits(GPIOD, GPIO_Pin_13);
           break;
         case 'R':
           GPIO_ToggleBits(GPIOD, GPIO_Pin_14);
           break;
         case 'B':
           GPIO_ToggleBits(GPIOD, GPIO_Pin_15);
        }
    }

    return 0;
}

تمرین
در تمرینات زیر علاوه بر برنامه میکرو ، برنامه کامپیوتر را نیز بنویسید:
1- برنامه ای بنویید که رشته "Robotics Engineering" را به کامپیوتر ارسال کند. سپس کامپیوتر آن را مجدد به میکرو ارسال کند، در صورتی که عبارت درست ارسال شده بود چراغ سبز روشن شود و در صورتی که اشتباه شده بود چراغ قرمز روشن شود و دوباره رشته ارسال شود و این کار ادامه پیدا کند تا رشته درست ارسال شود.
2- برنامه شماره 1 را طوری بنویسید که حرف به حرف ارسال و تایید شود. برای تایید حرف به حرف می توانید از کارکتر های - و = برای اطمینان از صحت ارسال استفاده کنید.
3- برنامه ای بنویسید که با ارسال رشته "Traffic Lights" برد عمل چراغ راهنمایی اجرا دهد. در صورت ارسال رشته "Flashing Red" چراغ قرمز چشمک زن، در صورت ارسال رشته "Flashing Yellow" چراغ قرمز چشمک زن و در صورت ارسال "Off" همه ی LED ها خاموش شوند.
4- برنامه بات را بنویسید. در این برنامه برد به رشته ها جواب می دهد. مثلا اگر "Salam" در یافت کرد رشته ی "Salam Alaykom" را ارسال کند و یا مثلا وقتی "smkdgjnspkrjg" در یافت کند عبارت "I do not know" را ارسال کند و ...
5- برنامه شبیه ساز ربات تعقیب خط با پنج سنسور را بنویسید. در این شبیه ساز داده ها (اطلاعات سنسور) ار کامپیوتر ارسال می شوند و ربات پس از تحیلی سرعت هر موتور را به کامپیوتر ارسال می کند.
 

Similar threads

بالا