توسعه نرم افزار سیستم های Embedded سوم خرداد۳ نظر

یک سیستم embedded سامانه ای هوشمند و مجزا است که از زمان روشن شدن کارهایی را انجام میدهد و یا وظایفی بر عهده دارد . مشابه زمانی که برنامه ای بر روی رایانه اجرا میکنیم که نیاز به راه اندازی و بارگذاری برنامه ای دیگر نداریم عمل میکند.

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

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

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

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

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

میکروکنترلر چیست؟

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

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

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

رجیسترهای عمومی General purpose جهت نگهداری از عملیات CPU و همچنین نتایج عملیات استفاده می شوند.

در کنار رجیسترهای CPU این واحد به واحد های دیگری مانند درگاه های وروردی ، کنترل کننده وقفه ، تایمر ، درگاه سریال ، I2C ، SPI و در بعضی میکروهای پیشرفته درگاه ورودی و خروجی ویدیو و مدیریت حافظه متصل میشوند.

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

برای مثال یک کامپیوتر رومیزی ۶ ۱ MB حافظه RAM دارد ولی یک میکروکنترلر در حد ۲ K حافظه دارد.

همانطور که در ابتدا اشاره شد یک برنامه امبد یک سری کارها را انجام میدهد و به مثال ماشین لباسشویی بر میگردیم.

0

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

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

در این مثال کنترلر بصورت پیوسته ۳ مرحله زیر را انجام می دهد

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

۲ - ورودیها را پردازش کرده و کارهایی که می بایست انجام شود و زمان انجام آن را برآورد میکند.

۳ - موارد شامل مرحله دوم را انجام داده و خروجیهای مورد نظر را برای موتور و نمایشگر و ... ایجاد میکند.

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

میکروکنترلر ، حافظه و ادوات جانبی

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

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

حافظه SRAM معمولا به سه قسمت تقسیم میشود محیط عمومی برای نگهداری متغییرها حافظه stack (جهت توابع فراخوان شده و نگهداری از آرگومان استفاده میشود) و heap (بخشی از حافظه که زمانیکه نیاز است اشغال شده و سپس آزاد میشود تا توسط بقیه برنامه قابل استفاده باشد)

بعضی میکروکنترلرها همچنین EEPROM دارند که حافظه ای جدا و مانند فلش است که برای نگهداری داده های ثابت مانند کالیبراسیون و مقادیر اولیه کاربر استفاده میشود.

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

هر کدام از این ادوات رجیسترهایی برای کنترل و تنظیمات دارند که جدا از رجیسترهای CPU می باشد.

از آنجایی که این رجیسترها بصورت مستقیم توسط کاربر قابل دسترسی نیستند کاربر باید کدی بنویسد که در هنگام کار مقادیر را توسط CPU برای رجیسترهای مربوطه ارسال کند.

خلاصه ای از ادوات جانبی در زیر آمده است

GPIO – این ورودی و خروجیهای همه منظوره قابل برنامه ریزی در سطح منطقی هستند.

Timers – برای اندازه گیری زمان دقیق و بصورت پالس یا قطار پالس و یا اندازه گیری بین دو لبه پالس می باشد.

USARTS – برای ارتباط دو جهته سریال بین دو دستگاه بصورت گیرنده و فرستنده بیت به بیت است.

I2C – از این رابط برای بسیاری از سنسورها و یا نمایشگرها استفاده میشود و میتواند همزمان چندین دستگاه را آدرس دهی کند.

SPI – یک رابط دیگر مشابه I2C ولی سریعتر که معمولا ماژول ارتباطی نوع ارتباط را مشخص میکند.

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



0

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

نرم افزار کاربردی معمولا بر روی یک بستر توسعه ای مانند Windows یا Linux و یا Mac کامپایل می شود.

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

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

نمونه کد فرمور میکروکنترلر



// This is a single line comment in C

/*

Multi-line comments are braced with slash-asterisk and asterisk-slash as shown here.

Still a comment line.

*/


// Include header files

// These files contain function prototypes for functions used in this, or other source modules, as well as libraries.

// Some also contain constants and other pre-processor directives, or macros. C has very powerful macro processing capabilities.

// Here is a simple example based on using an AVR microcontroller such as is used in many Arduino boards such as the Uno.

#include <avr/io.h>

// In C, the program always start with the main() function, regardless of where it is located in the source module. Some

// prefer it to be at the top of the file; others place the main() function as the very last function in the file.

// In embedded applications, main() usually does not have any arguments since there is no command-line arguments to pass to the program at the start.

main() // Can also use void main(void) to emphasize that this main() function takes, and returns, no arguments.

{

// Put peripheral initialization code here, or call functions to do so.

// An embedded application is basically one that runs forever.

while(1)

{

// Application code goes here.

}

}


کد زیر یک نمونه واقعی برای میکروکنترلر AVR است که چراغ چشمک زن را بر روی ATMEGA328 پیاده سازی کرده است. LED به پورت GPIO5 متصل شده است.



<a href= "https://www.microchip.com/mplab/avr-support/atmel-studio-7" target= "_blank" rel="noopener noreferrer" >Atmel Studio</a> is a free and very suitable IDE plus compiler/linker that can be used for AVR microcontrollers.

// The io.h header file provides names matching those used in the specifications for the peripheral registers.

#include &lt;avr/io.h&gt;

// This one contains function prototypes for the delay functions defined in the avr-libc library.

#include &lt;util/delay.h&gt;

// Function prototypes must be declared if the functions are called before their actual definitions, as is the case here.

// Usually, these are put in a header file that is included in the source module, but they are actually declared here to show how this is done.

void setup(void);

void loop(void);

// Starting point for the program.

void main(void)

{

setup();

while(1)

{

loop();

}

}

// Actual function setup()

void setup(void)

{

// DDRB is the Data Direction Register of Port B, which is 8 bits wide. Each bit corresponds to an actual pin on the microcontroller.

// Setting a bit of this register to 1 means this corresponding pin is an output.

DDRB |= (1 &lt;&lt; PB5); // Same DDRB = DDRB | 0b0010000. This sets GPIO5 of PortB as a digital output, and leaves the other GPIO’s untouched.

}

// Actual function loop()

void loop(void)

{

<a id="post-18015-_Hlk29500129"></a>PORTB |= (1 &lt;&lt; PB5); // Set PB5 pin of PORTB to 1

_delay_ms(1000); // 1000ms delay

PORTB &amp;= ~(1 &lt;&lt; PB5); // Set PB5 pin of PORTB to 0

_delay_ms(1000);

}


نهایتا اگر سخت افزار آردینو را دراختیار دارید با نمونه کد فوق و کامپایل توسط GCC میتوانید LED آنرا بصورت چشمک زن دراورده لازم بذکر است که میکروکنترلر مربوطه AVR است.

0

نتیجه گیری

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

جهت برنامه ریزی محصول میتوانید از مقاله مربوطه کمک بگیرید

نظرات

مجید پاسخ
چهارم خرداد

مرسی از اطلاعات مفیدتون

علی پاسخ
چهارم خرداد

چه زبان برنامه نویسی برای سیستم های امبد بهتر است

رضا پاسخ
پنجم خرداد

فرق برنامه امبد و غیر امبد چیست؟

نظر خود را اضافه کنید