بخش چهارم آموزش AVR : آموزش برنامه نویسی C به همراه انجام پروژه

بازگشت به آموزشگاه

مقدمه

در فصل های گذشته به این نکته اشاره کردیم که قدرتمندترین زبان برنامه نویسی میکروکنترلرها زبان c و c++ می باشد . همچنین اشاره کردیم که برنامه نویسی برای یک ماشین بر مبنای پردازنده های RISC با برنامه نویسی برای یک ماشین بر مبنای پردازنده های CISC تفاوت اساسی دارد و آن هم حساسیت بیشتر RISC نسبت به CISC می باشد که برنامه نویس را مجبور می کند تا با دقت بیشتر و درک بیشتر سخت افزار برنامه نویسی کند . با این دید از میکروکنترلر ها در این فصل گذری بر برنامه نویسی به زبان C ویژه میکروکنترلر ها خواهیم داشت و نکات و مفاهیمی که یک برنامه نویس میکرو باید آنها را رعایت کند به همراه انجام مثال ها و پروژه های عملی مربوطه شبیه سازی خواهیم کرد .

embedded-c


معرفی کوتاه زبان C

زبان برنامه‌نویسی سی ، زبانی همه منظوره، ساخت یافته و روندگرا می‌باشد که در سال ۱۹۷۲ توسط دنیس ریچی در آزمایشگاه‌های بل ساخته شد . به طور کلی زبان های برنامه نویسی را می توان در سه سطح دسته بندی کرد :  ٫زبان های سطح بالا  ٫زبان های سطح میانی ٫زبان های سطح پایین . زبان سی یک زبان سطح میانی است که در آن هم می توان به سطح بیت و بایت و آدرس دسترسی داشت و هم از مفاهیم سطح بالا که به زبان محاوره ای انسان نزدیکتر است ( مانند حلقه های شرطی if … else و حلقه های تکرار for و while و … ) ، بهره گرفت . در زبان سی هیچ محدودیتی برای برنامه نویس وجود ندارد و هر آنچه را که فکر می کنید ، می توانید پیاده سازی کنید . ارتباط تنگاتنگی بین زبان c و اسمبلی وجود دارد ، به این صورت که می توان از برنامه نویسی اسمبلی در هر کجای برنامه زبان سی استفاده کرد .

c-programming-tutorial


کلمات کلیدی در زبان C

زبان سی زبان کوچکی است چرا که در آن تعداد کلمات کلیدی ۳۲ کلمه است . کم بودن کلمات کلیدی در یک زبان مبنی بر ضعف آن نیست . زبان بیسیک حاوی ۱۵۰ کلمه کلیدی است اما قدرت زبان سی به مراتب بالاتر است . زبان سی به حروف کوچک و بزرگ حساس است ( Case Sensitive ) . در این زبان بین حروف کوچک و بزرگ تفاوت است و تمام کلمات کلیدی باید با حروف کوچک نوشته شوند . در شکل زیر تمام کلمات کلیدی زبان سی را مشاهده می کنید .

C_KeyWords

 

نکته ۱ : کلمه کلیدی auto از کامپایلر Codevision حذف شده است.

 

نکته ۲ : کلمات کلیدی زیر به کامپایلر کدویژن اضافه شده است :

interrupt defined bit
inline eeprom flash
sfrw sfrb

 


ویژگی های یک برنامه به زبان C

– هر دستور در زبان سی با ; به پایان می رسد .

– حداکثر طول هر دستور ۲۵۵ کاراکتر است .

– هر دستور می تواند در یک یا چند سطر نوشته شود .

– برای توضیحات تک خطی از // در ابتدای خط استفاده می شود و یا توضیحات چند خطی در بین */ و /* قرار می گیرد .

 


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

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

بنابراین همانطور که مشاهده می شود :

  1. خطوط ابتدایی برنامه ، دستور فراخوانی فایل های سرآمد ( Header Files ) می باشد . فایل های سرآمد فایل هایی با پسوند h هستند که حاوی پیش تعریف ها و الگو های توابع می باشند .
  2. قالب اصلی برنامه ب مبنای تابعی به نام main بنا شده است . تابعی که اصولا ورودی و خروجی ندارد و کدهای اصلی برنامه را در خود دارد .

 


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

ساختار فوق یک قالب کلی در برنامه نویسی زبان C در کامپیوتر ( ماشین CISC ) با هدف اجرا در کامپیوتر را نشان می دهد . برنامه نویسی میکروکنترلر ها ( ماشین RISC ) با هدف اجرا در میکروکنترلر ، با برنامه نویسی در کامپیوتر کمی متفاوت است . تفاوت اصلی در کامپیوتر این است که عامل اجرای برنامه ، در زمان نیاز به عملکرد آن ، یک کاربر است . هر زمان که کاربر نیاز به عملکرد برنامه داشته باشد آن را اجرا می کند و نتیجه را بررسی می کند . اما در میکروکنترلر رفتار یک آی سی است که عامل اجرای برنامه منبع تغذیه است . با وصل منبع تغذیه برنامه شروع به کار می کند و تا زمانی که منبع تغذیه وصل است باید کارهای مورد نیاز را دائما اجرا نماید .

 


ساختار برنامه میکروکنترلر به زبان C

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

 


متغیرها در زبان C

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

Variable_CodeVision


نحوه تعریف متغیرها

متغیر ها به صورت زیر تعریف می شوند :

مثال :

توضیح : در خط اول یک متغیر ۸ بیتی بدون علامت با نام A که تنها میتواند مقادیر ۰ تا ۲۵۵ بگیرد ، با مقدار اولیه ۱۲ تعریف شده است . در خط دوم نیز ۳ متغیر علامت دار با نام های a و X و j که هر سه مقدار اولیه ۰ دارند تعریف شده است .

نکته : در صورت عدم تعریف مقدار اولیه در هنگام تعریف یک متغیر ، مقدار اولیه در حالت default برابر ۰ تعریف می شود .

 


ویژگی های نام متغیر

– اولین کاراکتر نام متغیر عدد نمیتواند باشد .

– نام متغیر بیشتر از ۳۱ کاراکتر مورد استفاده نیست .

– نام متغیر تنها ترکیبی از حروف a تا z و A تا Z و اعداد و کاراکتر _ می تواند باشد .

 


انواع متغیر ها از نظر محل تعریف در برنامه

متغیرها از نظر مکانی که در برنامه تعریف می شوند ، به دو دسته کلی تقسیم می شوند :

  1. متغیرهای عمومی ( Global )
  2. متغیرهای محلی ( Local )

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

 


محل تعریف متغیرها در حافظه میکروکنترلر

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

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

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

 


توابع در زبان c

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

function_in_cزبان سی دارای توابعی است که از قبل نوشته شده‌اند، و توابع کتابخانه‌ای نامیده می‌شوند. در واقع فرایندهایی که پر کاربرد هستند و در اغلب برنامه‌ها مورد استفاده قرار می‌گیرند به صورت توابع مستقل قبلاً نوشته شده‌اند و درون فایلهایی قرار داده شده اند . با اضافه کردن فایل های سرآمد که تعریف آن توابع در آنها قرار دارد می توان از آن توابع استفاده کرد .

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

 


انواع توابع در زبان c

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

  1. تابع با ورودی ، با خروجی

مثال : تابع با دو ورودی از جنس کاراکتر و یک خروجی از جنس کاراکتر

  1. تابع با ورودی ، بدون خروجی

مثال : تابع دارای یک ورودی int و بدون خروجی

  1. تابع بدون ورودی ، با خروجی

مثال : تابع بدون ورودی اما دارای خروجی int

  1. تابع بدون ورودی ، بدون خروجی

مثال : تابع بدون ورودی و خروجی

بنابراین در اولین قدم باید مشخص کنیم که این تابع چه خروجی را به ما می دهد ( در اصطلاح برنامه نویسی بر می گرداند ) و فقط به ذکر نوع خروجی بسنده می کنیم ، یعنی مثلا اگر عدد صحیح برگرداند از int ، اگر کاراکتر برگرداند از char و به همین ترتیب برای انواع دیگر و اگر هیچ مقداری را برنگرداند از void استفاده می کنیم .

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

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

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

 


تعریف توابع در زبان c

برای نوشتن و اضافه کردن یک تابع باید دقت کرد که هر تابع سه بخش دارد : اعلان تابع ، بدنه تابع و فراخوانی تابع

نحوه تعریف تابع به یکی از سه صورت زیر است :

1- اعلان تابع قبل از تابع main باشد و بدنه تابع بعد از تابع main باشد .

2- اعلان تابع و بدنه تابع هر دو قبل از تابع main باشد .

3- اعلان تابع و بدنه تابع درون فایل کتابخانه ای باشد .

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

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

 


اعلان و بدنه تابع :

;( … , نام ورودی دوم  نوع ورودی دوم , نام ورودی اول  نوع ورودی اول ) نام تابع  نوع داده خروجی تابع

مثال :

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

} ( … , نام ورودی دوم  نوع ورودی دوم , نام ورودی اول  نوع ورودی اول ) نام تابع  نوع داده خروجی تابع

{ بدنه تابع : دستوراتی که تابع انجام می دهد

مثال :

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


فراخوانی تابع :

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

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

توضیح : در برنامه فوق ابتدا هدرفایل مربوط به میکروکنترلر Atmega32 به برنامه اضافه می شود . با اضافه شدن این فایل برنامه تمام رجیسترهای میکروکنترلر را می شناسد . سپس هدر فایل delay برای اینکه بتوان از تابع delay_ms استفاده کرد به برنامه اضافه شده است . سپس یک متغیر ۸ بیتی از نوع عدد بدون علامت ( unsigned char ) با مقدار اولیه صفر تعریف می شود . یک تابع دارای خروجی و بدون ورودی اعلان و بدنه آن تعریف شده است . در تابع main ابتدا رجیستر DDRA به منظور اینکه تمام ۸ بیت موجود در پورت A خروجی شود ، به صورت ۰xff مقدار دهی شده است . مقدار اولیه منطق پایه های خروجی پورت A در خط بعدی همگی برابر ۰ شده است . در نهایت در حلقه بی نهایت while ، تابع فراخوانی شده است و مقدار خروجی که تابع برمیگرداند در درون PORTA ریخته می شود . در صورتی که روی هر پایه از پورت LED قرار دهیم ، برنامه به صورت شمارنده عمل خواهد کرد و در هر مرحله تعدادی LED روشن می گردد .

نکته : نوع متغیر رجیسترها در هدرفایل mega32.h همگی به علت ۸ بیتی بودن رجیسترها در میکروکنترلرهای AVR ، از نوع unsigned char می باشد .

 


ثابت ها در زبان C

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

  1. استفاده از دستور Const

مثال :

  1. استفاده از دستور #define

مثال :

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

 


دستورات شرطی

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

 

دستور شرطی if

IF_define

در حلقه شرطی if ، اگر شرط موردنظر برقرار باشد، کدهای درون {  } در زیر if اجرا خواهند شد. اگر شرط موردنظر برقرار نباشد، کدهای درون { } در زیر else اجرا خواهند شد به مثال زیر توجه کنید:

مثال :

توضیح : در مثال بالا اگر متغیر a برابر با عدد ۷ باشد، مقدار باینری ۱۱۱۱۰۰۰۰ به رجیستر PORTDنسبت داده می‌شود و اگر برابر با ۷ نباشد، مقدار باینری ۰۰۰۰۱۱۱۱ به رجیستر PORTD نسبت داده می‌شود. دقت شود، در سطرهای بالا دو علامت { } وجود ندارد و این به‌این‌علت است در زیر دستور if و else تنها یک دستور وجود دارد، اگر تعداد دستورات بیشتر از یک دستور باشد حتماً باید از { } استفاده شود. وجود دستور else در if ضروری نیست و بسته به نیاز کاربر قرار داده می‌شود.

 

دستور شرطی switch

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

گزینه Default در ساختار دستور switch ضروری نیست و بسته به نیاز کاربر قرار داده می شود. در دستور switch مقادیر صحیح مورد بررسی قرار می گیرند . هر دستور case یک شرط برابری را مورد بررسی قرار می دهد و در صورت برابر بودن ، کد های قرار گرفته در زیر آن اجرا شده و توسط دستور Break از ساختار switch خارج می شود. اگر در زیر هر case دستور Break قرار داده نشود، هر case با case بعدی orمنطقی (یا) می شود. در بعضی شرایط به این صورت می توان ۲ مقدار را بررسی کرد.

 


حلقه های تکرار

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

 

حلقه while

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

مثال :

حلقه do…while

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

حلقه for

از این حلقه در حالتی که تعداد دفعات تکرار حلقه از قبل مشخص باشد، به کار می رود. در این حلقه، متغیری وجود دارد که تعداد دفعات تکرار حلقه را کنترل می کند. این متغیر را اندیس حلقه تکرار یا شمارنده می گویند. اندیس حلقه دارای یک مقدار اولیه است که طی هر بار اجرای دستورات حلقه، مقداری به آن اضافه می شود. به این مقدار اضافه شده در هر بار اجرای حلقه، گام حرکت گویند. گام حرکت می تواند عددی صحیح یا اعشاری، مثبت یا منفی ویا کاراکتری باشد. یکی دیگر از اجزای حلقه for شرط حلقه است. شرط حلقه مشخص می کند که دستورات داخل حلقه for تا کی باید اجرا شوند. اگر این شرط دارای ارزش درستی باشد، دستورات داخل حلقه اجرا می شوند وگرنه کنترل برنامه از حلقه خارج می شود. حلقه for دارای یک متغیر شمارشی است که نسبت به تعداد تکرار حلقه، طول آن مشخص شده و در ابتدای برنامه باید معرفی شود. به طور مثال اگر تعداد تکرار حلقه ایی ۲۰۰ مرتبه باشد، می توان متغیر شمارشی از نوع unsigned char معرفی کرد، اما اگر تعداد تکرار حلقه ۱۰۰۰ مرتبه باشد، باید متغیری با طول بیشتر مثل نوع int را برای متغیر شمارشی انتخاب کرد. این متغیر شمارشی در بدنه حلقه کاربرد فراوانی دارد. دستور for را به شکل زیر می توان به کار برد:

 

مثال :

 

توضیح : در ابتدای حلقه for مقدار متغیر i برابر با مقدار صفر قرار داده شده است و شرط حلقه تا وقتی برقرار است که مقدار متغیر i کوچکتر از عدد ۸ باشد. گام حلقه به شکلی تنظیم شده که هر بار یک واحد به متغیر شمارشی اضافه می کند. در ابتدا مقدار متغیر i برابر با صفر است و حلقه شروع می شود، کد های درون حلقه اجرا شده سپس یک واحد به متغیر i اضافه می شود. تکرار کد های درون این حلقه، طبق شرط حلقه ۸ مرتبه می باشد و به متغیر i مقادیر ۰ تا ۷ تعلق می گیرد. از تغییرات متوالی مقدار متغیر i می توان در حلقه استفاده کرد. همان طور که در مثال بالا مشاهده می شود، یک آرایه با نام a قبلا معرفی شده است، به جای اندیس آرایه a، متغیر i قرار گرفته است؛ بنابراین با هر بار تکرار حلقه و تغییر مقدار متغیر i، اندیس آرایه نیز تغییر می کند و هر بار مقدار i به عضو i ام آرایه a انتساب داده می شود. به طور مثال اگر حلقه در حرکت سوم قرار گیرد، یعنی مقدار i برابر با عدد ۲ است. در این حالت کد داخل حلقه به صورت a[2]=2 می شود.

 

دستور break و continue در حلقه ها

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

 


 اتصال کلید به میکرو

یکی از ساده ترین و پرکاربرد ترین دستگاههای ورودی کلید است . توسط کلید میتوان منطق ۰ یا ۱ را به میکرو وارد کرد و بر اساس آن پردازش را انجام داد. برای خواندن منطق کلید از رجیستر PIN استفاده می شود . نحوه استفاده از رجیستر PIN به این صورت است که : ” اگر کلید زده شد آنگاه کار مورد نظر انجام شود ” . عبارت اخیر معادل استفاده از دستور شرطی if به صورتی است که اگر کلید زده شده بود یک منطق و در غیر این صورت منطق دیگری وارد پایه میکرو شود . بنابراین اتصال کلید را به دو صورت PullUp و PullDown انجام می شود که در شکل زیر مشاهده می کنید . در کلید pull up در حالتی که کلید زده نشده منطق ۱ و در حالت فشردن کلید منطق ۰ وارد میکرو می شود . معمولا از مقاومت ۱۰k برای این کار استفاده می شود .

Atmega32_Button

بنابراین برای فهماندن کلید به میکرو به صورتی که ” اگر کلید زده شد آنگاه کار مورد نظر انجام شود ”  برای کلیدهای فوق به صورت زیر می شود :

اما مشکلی که در کلید وجود دارد ، بوجود آمدن لرزش یا bounce در هنگام قطع و وصل کلید است . در زمانی که کاربر کلید را فشار می دهد تقریبا ۲۰ میلی ثانیه طول می کشد تا منطق کلید از ۰ به ۱ ( یا بالعکس ) ثابت شود تا قبل این بعلت وجود جرقه کلید منطق ثابتی ندارد . در زمانی که کاربر دست خود را از روی کلید بر می دارد نیز تقریبا ۲۰ میلی ثانیه طول می کشد تا ۰ و ۱ شدن های کلید تمام شده و کلید به منطق اولیه خود برگردد . در واقع این مشکل زمانی برای ما مسئله ساز می شود که زمانی که کاربر کلید را یکبار فشار می دهد و انتظار دارد تا میکرو متوجه یکبار فشار دادن آن شود اما به علت قرار گرفتن if در درون حلقه نامتناهی while چندین بار شرط PINB.0==0 برقرار شده و کار مورد نظر چندین بار انجام می شود . راه حل این مشکل ساده است و آن هم قرار دادن مقداری delay در حلقه if است . بنابراین برای حل این مشکل بسته به نوع برنامه یکی از سه روش زیر قابل استفاده است :

کلید نوع ۱ :

توضیح : به محض فشار دادن کلید توسط کاربر شرط if برقرار شده و دستورات مورد نظر اجرا می شود سپس به علت ایجاد تاخیر زیاد توسط تابع delay_ms ( در اینجا ۲۰۰ میلی ثانیه ) با این کار احتمال اینکه زمانی که برنامه در حلقه while به if می رسد و شرط برقرار باشد ، کاهش می یابد . مزیت این کلید این است که در صورتی که کاربر کلید را فشار داده و نگه دارد تقریبا در هر ۲۰۰ میلی ثانیه یکبار کار مورد نظر صورت می گیرد . عیب این روش نیز این است که هنوز احتمال دارد که زمانی که یکبار کلید زده شود دوبار کار مورد نظر انجام شود .

 

کلید نوع ۲ :

توضیح : به محض فشار دادن کلید توسط کاربر شرط if برقرار شده و برنامه به مدت ۲۰ میلی ثانیه صبر می کند تا منطق کلید ثابت شود و از منطقه bounce عبور کند سپس توسط حلقه while با همان شرط برقراری کلید در این مرحله برنامه تا زمانی که کلید توسط کاربر فشرده شده است در حلقه گیر می کند و هیچ کاری انجام نمی دهد . به محض اینکه کاربر دست خود را بر می دارد ، شرط برقرار نبوده و خط بعدی یعنی دستورات مربوطه اجرا می شود . مزیت این روش این است که در هر بار فشردن کلید برنامه تنها یکبار اجرا می شود . معایب این روش این است که تا زمانی که کاربر کلید را نگه داشته اتفاقی نمی افتد و به محض رها کردن کلید کار مورد نظر انجام می شود .

 

کلید نوع ۳ :

توضیح : این کلید به صورت start/stop عمل می کند یعنی بار اولی که کاربر کلید را فشار می دهد دستورات مربوط به بعد از زدن کلید دائما اجرا می شود تا زمانی که کاربر دست خود را از روی کلید رها کرده و دوباره کلید را فشار دهد ، در این صورت دستورات دیگر اجرا نمی شود . دو متغیر از نوع bit با نام های flag و start با مقدار اولیه ۰ برای این کلید باید تعریف شود . زمانی که کاربر برای اولین بار کلید را فشار می دهد شرط if برقرار شده و flag=1 و start=1 می شود . در این صورت شرط if دوم برقرار بوده و دستورات مربوطه با هر بار چرخش برنامه درون حلقه نامتناهی while یکبار اجرا می شود . زمانی که کاربر دست خود را از روی کلید بر می دارد و منطق ۱ وارد میکرو می شود flag=0 شده و برنامه دوباره آماده این می شود که کاربر برای بار دوم کلید را فشار دهد . زمانی که کاربر بار دوم کلید را می فشارد start=0 شده و دستوراط مربوطه اجرا نخواهد شد سپس با برداشته شدن دست کاربر از روی کلید ، همه چیز به حالت اول بر میگردد . این کلید طوری نوشته شده است که bounce در آن کمترین تاثیر مخرب ممکن را دارد .

 


مثال عملی شماره ۲

برنامه ای بنویسید که یک کلید روی پورت PA0 و ۸ عدد LED روی پورت B وجود داشته باشد و با هر بار زدن کلید ، led های موجود به صورت ۱٫ شمارنده بالا شمار  ۲٫ شمارنده پایین شمار  ۳٫شمارنده جانسون  ۴٫ شمارنده حلقوی  عمل نماید . سعی کنید برنامه کمترین عیب ممکن را داشته باشد و کلید به بهترین نحو ممکن کار کند .

حل :

مرحله اول : طراحی سخت افزار

Atmega32_Mesal2

مرحله دوم : طراحی نرم افزار

سپس به سراغ نرم افزار CodeVision رفته و طبق مراحل گفته شده در فصل قبل پروژه جدید را می سازیم و فرکانس میکرو را روی ۱Mhz داخلی قرار می دهیم . برنامه خواسته شده به صورت زیر است .

توضیح : متغیر i حالت کار میکرو را نشان می دهد که با هر باز زدن کلید یک واحد به متغیر i اضافه می شود . در حالت پیش فرض مقدار این متغیر ۰ است و برنامه هیچ کاری انجام نمی دهد تا زمانی که کاربر کلید را فشار دهد . با اولین باری که کلید زده می شود i=1 شده و برنامه مربوط به شمارنده بالا شمار اجرا می شود . با دومین باری که کلید زده می شود i=2 شده و برنامه مربوط به شمارنده پایین شمار اجرا می شود . دفعه سوم i=3 شده و برنامه به صورت شمارنده حلقوی و در نهایت زمانی که برای بار چهارم کلید زده شود i=4 شده و برنامه شمارنده جانسون می شود . متغیر flag از آن جهت ایجاد شده است که زمانی که شمارنده جانسون و حلقوی به آخر رسیدند ، برنامه از آخر به اول شروع به کار کند و زیباتر می شود .

نکته : همانطور که مشاهده کردید در برنامه از حلقه for استفاده نکردیم تا برنامه روان تر و حرفه ای تر باشد .

دانلود مثال عملی شماره ۲

 


 آرایه ها در C

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

 

تعریف آرایه یک بعدی :

Array_definition

با تعریف آرایه به همان مقدار خانه های حافظه بسته به نوع متغیر و تعداد خانه های آرایه تخصیص می یابد که در شکل زیر مثالی از آن را مشاهده می کنید

array_in_c

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

( طول آرایه ) ضرب در (طول نوع آرایه) = میزان حافظه آرایه (برحسب بایت)

برای دسترسی به هر یک از خانه ها آدرس آن را لازم داریم. آدرس هر خانه از ۰ تا n-1 است که در آن n تعداد خانه های تعریف شده است . هر عضو آرایه به تنهایی می تواند در محاسبات شرکت کند . مثال :

نکته ۱ : اندیس آرایه خود می تواند متغیر باشد و این قابلیت می تواند در برنامه ها کاربرد زیادی داشته باشد .

نکته ۲ : در صورتی که می خواهید آرایه به صورت دائمی ذخیره شود ( مثلا وقتی که میخواهید لوگو شرکت خود را همیشه داشته باشید ) باید به ابتدای تعریف کلمه کلیدی eeprom یا flash را اضافه کنید تا در حافظه های دائمی ذخیره گردد .

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

 

آرایه های چند بعدی

در تعریف آرایه دو بعدی باید ۲ اندیس و در تعریف آرایه سه بعدی باید ۳ اندیس و در تعریف آرایه n بعدی باید n اندیس را ذکر کرد .

2d_array_c

آرایه های چند بعدی در نمایشگر های lcd کاربرد دارند .به عنوان مثال :

یک آرایه دو بعدی بنام table را تعریف میکند که دارای ۱۰ سطر و ۱۰ ستون است و نوع عناصر آن int است .

آرایه ای سه بعدی بنام k را تعریف می کند که دارای ۵ سطر ، ۱۰ ستون و ۱۵ ارتفاع است و نوع عناصر آن int می باشد .

نکته : تعریف آرایه ها با مجموعه عناصر زیاد در حافظه SRAM به علت محدودیت در حجم حافظه ممکن است باعث ایجاد مشکل شود. بنابراین معمولا آرایه های با حجم زیاد را در بخش خالی حافظه flash ذخیره می کنند.

 

مقدار دهی به آرایه های چند بعدی

برای مقدار دهی اولیه به آرایه های دو بعدی سطر ها را به ترتیب پر می کنیم . مثال :

برای مقدار دهی به آرایه های سه بعدی ابتدا سطرهای طبقه اول و سپس سطرهای بقیه طبقات را مقدار دهی می کنیم . مثال :

برای مقدار دهی ثانویه در حین برنامه میتوان به صورت زیر عمل کرد :

 

نکته 1 : برای مقدار دهی ثانویه اندیس ها از 0 تا n-1 میتواند باشد.

نکته 2 : در مقدار اندیس آرایه های چند بعدی ، به جای عدد میتوان از متغیر استفاده کرد.

 


رشته ها در C

در زبان سی برای نمایش کلمات و جملات از رشته ها استفاده می شود . رشته همان آرایه ای از کاراکتر ها است که حاوی اطلاعاتی می باشد . تمام کاراکتر ها شامل اعداد و حروف و برخی کاراکترهای دیگر که روی صفحه کلید کامپیوتر وجود دارند ، دارای کد شناسایی ASCII ( American Standard Code For Information Interchange ) می باشند . کدهای اسکی که توسط استاندارد آمریکایی در سال ۱۹۶۷ ابداع شد و در سال ۱۹۸۶ دست خوش تغییراتی شد .

کاراکتر ست اسکی خود به دو نوع تقسیم می‌شود. نوع ۷ بیتی که با نام اسکی استاندارد (Standard ASCII) شناخته شده و دارای ۲ به توان ۷ یعنی ۱۲۸ کاراکتر مختلف است که از ۰ تا ۱۲۷ استفاده می‌شوند. نوع دیگر آن حالت ۸ بیتی است که با نام اسکی توسعه یافته (Extended ASCII) شناخته شده و دارای ۲ به توان ۸ یعنی ۲۵۶ کاراکتر مختلف است که از ۰ تا ۲۵۵ استفاده می‌شود. حالت توسعه یافته جدا از حالت استاندارد نیست بلکه از ۰ تا ۱۲۷ کاراکتر اول آن درست مانند حالت استاندارد بوده و فقط بقیه کاراکترها (از ۱۲۸ تا ۲۵۵) به آن اضافه شده است. کاراکترهای اضافی دارای هیچ استانداردی نبوده و ممکن است در دستگاه‌ها و کامپیوترهای مختلف فرق داشته باشد و به منظور ایجاد کاراکترهای زبان دوم ( مثلا زبان فارسی ) ایجاد شده است . یعنی ممکن است در یک کامپیوتر کاراکتر اسکی ۱۵۰ معادل حرف û و در کامپیوتر دیگر که روی زبان دوم فارسی تنظیم شده است ، معادل حرف ب باشد . اما کاراکترهای قبل از ۱۲۸ همگی ثابت هستند. کاراکترهای فارسی در اینکدینگ Iranian System شرکت ایرانیان سیستم که یکی از قدیمی ترین اینکدینگ‌های ASCII فارسی است را می‌توانید در این لینک ببینید.

در هر دو نوع ذکر شده (۷ و ۸ بیتی) تعداد ۳۲ کاراکتر اول (یعنی از ۰ تا ۳۱) و آخرین کاراکتر (۱۲۷) با عنوان کاراکترهای کنترلی (Control Characters) شناخته می‌شود. این کاراکترها غیرقابل چاپ بوده و فقط برای کنترل متن مورد استفاده قرار می‌گیرد (مثلاً مشخص کننده ابتدای هدر، حذف، کنسل و …). بقیه کاراکترها یعنی از ۳۲ تا ۱۲۶ قابل چاپ هستند. این کاراکترها شامل نمادها، حروف و اعداد انگلیسی هستند. در حالت توسعه یافته، از کاراکترهای ۱۲۸ تا ۲۵۵ نیز قابل چاپ هستند.

در شکل زیر این ۹۵ کاراکتر قابل چاپ انگلیسی را به همراه کد اسکی آن در مبنای دسیمال مشاهده می کنید .

Ascii printable characters

تعریف یک کاراکتر

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

تعریف رشته ( آرایه ای از کاراکتر ها )

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

string_in_c

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

string_in_c_2

کاراکترهای کنترلی

در محتویات یک رشته‌ علاوه بر کاراکترهای قابل‌چاپ می‌توان کاراکترهای کنترلی قرارداد. این کاراکتر ها برای کنترل صفحه نمایش میباشند و به شکل جدول زیر میباشند:

 کاراکتر کنترلی  کاری که انجام میشود
\n  به خط بعد میرود
\t  به اندازه 8 فاصله به جلو میرود(تب)
\a  بوق سیستم را به صدا در می آورد
 \\  کاراکتر \ را چاپ میکند
\”  کاراکتر ” را چاپ میکند
\v  به 8 خط بعد میرود
\b  کاراکتر قبل از خودش را حذف میکند(بک اسپیس)
\r  کلید را مشخص میکند
\?  علامت ? را چاپ میکند
\:  علامت : را چاپ میکند

 


عملگرها در C

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

 

عملگرهای محاسباتی

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

Operator_1

تقدم عملگر های محاسباتی

Operator_2

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

همان‌طور که در مثال مشاهده می‌کنید، در دو دستور اول به متغیر x یک واحد اضافه می‌شود. در دستور سوم، ابتدا یک واحد به مقدار متغیر x اضافه‌شده و سپس درون متغیر y قرار می‌گیرد. در دستور چهارم، ابتدا مقدار متغیر x درون متغیر y قرارگرفته و سپس یک واحد به آن اضافه می‌شود. اگر تا قبل از رسیدن به دستور چهارم، مقدار x برابر با ۱۰ باشد، پس از گذشتن از دستور چهارم، مقدار y برابر ۱۰ و x برابر با ۱۱ است.

 

عملگرهای مقایسه ای و منطقی

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

Operator_3

تقدم عملگرهای رابطه ای و منطقی

Operator_4

عملگرهای ترکیبی

این عملگر ها ترکیبی از عملگر مساوی و عملگرهای دیگر هستند. به طور مثال عملگر =+ در نظر بگیرید، اگر به شکل x += a نوشته شود، برابر با x = x+a است؛ یعنی هر بار متغیر x را با متغیر a جمع می کند و درون متغیر x قرار می‌دهد. برای دیگر عملگر های ترکیبی نیز به همین صورت است. این عملگر ها پایین ترین تقدم را در بین عملگرهای دیگر دارند. این عملگر ها، عملگر های حسابی را شامل می شوند. در جداول زیر عملگرهای ترکیبی و تقدم آنها را میبینید.

Operator_5

تقدم عملگرهای ترکیبی

Operator_6

تعریف عملگرهای بیتی

عملگر های بیتی بر روی هر بیت یک بایت اثر می گذارند . به طور مثال ، a یک متغیر ۸ بیتی با مقدار باینری ۱۱۱۰۰۱۰۱ است ، اگر عملگر not را روی a اثر دهیم ، نتیجه معکوس شدن هر بیت هست .  a =~ a برابر با مقدار باینری ۰۰۰۱۱۰۱۰ است . عملگرهای دیگر نیز به همین شکل اثر خود را اعمال می‌کنند

Operator_9

در جدول‌های زیر عملگرهای بیتی و تقدم آن‌ها را مشاهده می‌کنید:

Operator_7

تقدم عملگرهای بیتی

Operator_8.png

تقدم کلی در عملگرها

Operator_10

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

همان‌طور که در مثال بالا مشاهده می‌کنید، ابتدا g+3 انجام می‌شود، در مرحله بعد ((a/(3+g) انجام می‌شود، در مرحله بعدی (((x+(a/(3+g) انجام می‌شود و در انتها (x+(a/(3+g)))*2 انجام می‌شود.

 


تبدیل نوع در محاسبات

برای درک بهتر در مورد تبدیل نوع در محاسبات ، به مثال زیر توجه کنید.

در مثال بالا با اینکه متغیرهای x و y و z هر سه از نوع float هستند ولی مقدار x برابر با ۴ و مقدار y و z برابر با ۴٫۵ است. اگر متغیر های a و b از نوع float بودند ، مقدار x نیز برابر ۴٫۵ می شد اما چون متغیر های a و b از نوع int هستند باید یک تبدیل نوع در محاسبه توسط عبارت (float) در ابتدای محاسبه انجام شود.

 


 اتصال سون سگمنت به میکرو

یکی از نمایشگرهای پرکاربرد سون سگمنت است که می توان توسط آن اعداد و برخی حروف ها را نشان داد . روش های متفاوت و مختلفی برای راه اندازی سون سگمنت توسط avr وجود دارد . ساده ترین روش اتصال سون سگمنت به میکرو استفاده از مداری به شکل زیر است . همانطور که مشاهده می شود در این روش از ۸ بیت ( یک پورت ) به طور کامل استفاده می شود . ( نرم افزار proteus بیت هشتم که به digit سون سگمنت وصل می شود را ندارد )

Atmega32_7Segment

برای نشان دادن اعداد روی سون سگمنت کافی است پایه مربوطه را پس از خروجی کردن یک کنیم برای مثال برای نشان دادن عدد یک باید PA1 و PA2 را ۱ نمود بنابراین دستور PORTA=0x06 عدد ۱ را روی سگمنت نمایش می دهد . بنابراین در این روش برای راحتی هنگام کار با سون سگمنت آرایه زیر را که شامل کد سون سگمنت اعداد ۰ تا ۹ می باشد ، تعریف می کنیم .

هر عددی که بخواهیم نمایش دهیم کافی است داخل [ ] قرار دهیم تا به کد سون سگمنت تبدیل شود . برای مثال :

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

Atmega32_7seg


راهنمای آی سی ۷۴۴۸ :

کار این آی سی خواندن یک عدد باینری ۴بیتی بوسیله پایه های ورودی اش و نمایش آن روی سون سگمنت می باشد . این آی سی ۱۶ پایه دارد و نحوه شماره بندی پایه های آن بصورت زیر می باشد:

۷۴۴۸

نکته : در استفاده از آی سی ۷۴۴۸ ، حتما می بایست از سون سگمنت کاتد مشترک استفاده کنید. برای استفاده از سون سگمنت آند مشترک آی سی دیگری به نام ۷۴۴۷ وجود دارد .

۷۴۴۸_pin
نحوه کار آی سی :
ورودی این آی سی همانطور که در جدول مشاهده کردید ، شامل چهار پایه ۱ ، ۲ ،۶ و ۷ ( که با حروف A ، B ، C و D نشان داده می شود ) می باشد. هر کدام از این پایه می توانند ۰ یا ۱ باشند (ولتاژ ۰ یا ۵ ولت داشته باشند). پس عدد ورودی ما به آی سی یک عدد باینری (در مبنای ۲ ) می باشد که فقط چهار رقم دارد.
از طرفی خروجی این آی سی کد های مخصوص سون سگمنت است که پس از نمایش روی سون سگمنت و در مبنای ۱۰ نمایش می یابد. ( خروجی این آی سی تنها اعداد ۰ تا ۹ میتواند باشد )

تغذیه آی سی :
آی سی هایی که شماره آنها با ۷۴ شروع می شود ، اصطلاحا TTL نامیده می شوند. این آی سی ها نسبت به ولتاژ تغذیه بسیار حساسند و ولتاژ آنها می بایست دقیقا ۵ ولت باشد. حداکثر تغییرات ولتاژی که می توان اعمال کرد در حد ۴٫۷۵ تا ۵٫۲۵ ولت است .

پیاده سازی مدار روی بردبورد :

-ابتدا آی سی ۷۴۴۸ را روی بردبورد جا می زنیم (روی شیار وسط برد بورد قرار می گیرد)
-در قسمت دیگری از برد بورد یک سون سگمنت کاتد مشترک قرار داده و جا می زنیم(سون سگمنت نیز روی شیار برد بورد قرار می گیرد و هر دسته از پایه ها در یک سمت )
– مطابق جدول مربوط به پایه های آی سی ۷۴۴۸ ، پایه های ۳ و ۴ و ۱۶ را به ردیف ولتاژ مثبت برد بورد وصل می کنیم.
– پایه ۸ به ولتاژ منفی وصل می شود.
– یکی از پایه های مشترک سون سگمنت را به ولتاژ منفی وصل می کنیم.
– هر کدام از پایه های خروجی آی سی را با سیم به پایه هم نامش روی سون سگمنت وصل می کنیم.
– ورودی های ۷۴۴۸ نیز که باید به میکرو وصل شود مطابق شکل وصل می کنیم .

۷۴۴۸_board

– در گوشه دیگری از بردبورد یک رگولاتور ۷۸۰۵ جا می زنیم.
– سیمی که ولتاز مثبت آداپتور را حمل می کند به پایه input وصل می کنیم.
– سیمی که ولتاژ منفی آداپتور را حمل می کند به پایه Ground وصل می کنیم.
– پایه های output و Goround رگولاتور را به ردیف های مثبت و منفی کنار بردبورد وصل می کنیم تا آی سی ها از این خطوط تغذیه شوند.

۷۴۴۸_reg

 


سون سگمنت های مالتی پلکس

در برخی طراحی ها ممکن است به بیش از یک سون سگمنت نیاز باشد . در این طراحی ها از سون سگمنت مالتی پلکس شده استفاده می شود. تنها تفاوت این سون سگمنت در این است که ۸ بیت دیتا ( a ، b ، c … ) برای همه سگمنت ها با هم یکی شده است ( مشترک هستند ) .۷Seg_Mux4پایه های سون سگمنت مالتی پلکس شده ۴ تایی را در شکل زیر مشاهده می کنید . در صورت اتصال پایه های Com سون سگمنت مربوطه روشن می شود .

۷Seg_mux4_pin

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

۷Seg_mpx4_cc

روش نمایش بر روی این نمایشگر به این صورت است که ابتدا همه کاتد ها خاموش است یعنی دارای منطق یک است ( مقاومت های ۱۰ کیلو اهمی برای همین منظور طراحی شده اند ) سپس دیتایی که میخواهیم روی سگمنت اول نمایش دهیم روی پایه های دیتا قرار می گیرد . سپس کاتد سگمنت اول را برای مدت کوتاهی صفر می کنیم تا عدد مورد نظر نشان داده شود ( یک کردن Base ترانزیستور توسط میکرو باعث اتصال زمین به کاتد سون سگمنت می شود ) سپس دوباره کاتد سگمنت اول را یک می کنیم و این کار را برای سگمنت های بعدی نیز تکرار می کنیم . اگر این کار با سرعت انجام شود همه سون سگمنت ها همزمان روشن دیده خواهد شد . برای استفاده از سون سگمنت شکل فوق تابعی به نام display به صورت زیر تعریف می کنیم .

توضیح : قبل از این تابع در برنامه آرایه data از نوع unsigned char و سایز ۴ تعریف شده و در برنامه این آرایه مقدار مورد نظری که میخواهیم نمایش دهیم را به خود می گیرد . سپس با فراخوانی تابع display در این تابع ابتدا دیتای مربوط به سون سگمنت اول روی پورت قرار می گیرد سپس با ۱ کردن پایه com و صبر کردن به مدت ۵ میلی ثانیه ، دیتای مورد نظر روی سون سگمنت به نمایش در می آید . سپس سون سگمنت اول را خاموش کرده و دیتای دوم روی پورت قرار می گیرد و …

 


اتصال صفحه کلید به میکرو

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

Proteus_KeyBoard

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

KeyBoard

بنابراین در حالت عادی همه سطرها ۱ و ستون ها نیز چون توسط مقاومت به Vcc متصل هستند ۱ خوانده می شوند . در شکل فوق اگر Row0 توسط میکرو ۰ شود و بقیه ردیف ها همان ۱ باشند ، هر کدام از دکمه های ردیف اول که زده شود ، سیگنال ۰ مستقیم توسط ستون ها به پایه میکرو منتقل شده و توسط میکرو خوانده می شود . بدین ترتیب می توان با خواندن منطق ستون ها به دکمه زده شده پی برد .

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

Keypad_pinout

بنابراین برای اتصال هرگونه صفحه کلید کافی است همه ستون ها از یک طرف به مقاومت pullup و از طرف دیگر به میکرو ، و همه سطر ها نیز مستقیم به میکرو متصل گردد . در اینجا صفحه کلید ۴ در ۳ را به صورت زیر به پورت D میکرو متصل کردیم .

KeyPad_Config

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

توضیح : قبل از این تابع در برنامه متغیر key را از جنس unsigned char و مقدار اولیه دلخواه به جز اعداد ۰ تا ۹ تعریف کرده ایم . با فراخوانی تابع keyboard در برنامه تابع فوق اجرا می شود . این تابع برای همه سطرها ابتدا سطر مورد نظر را صفر کرده و بعد از تاخیر منطق ستون ها را می خواند در صورت ۰ بودن منطق هر یک یعنی کلید مورد نظر زده شده است و بنابراین مقدار متغیر key برابر با عدد کلید زده شده می شود . متغیر key نماینده کلید زده شده است که در برنامه از آن استفاده می شود .

 


مثال عملی شماره ۳

یک صفحه کلید ۴ در ۳ و یک سون سگمنت مالتی پلکس شده mpx4 کاتد مشترک را به میکروکنترلر Atmega32 وصل نمایید . برنامه ای بنویسید که با فشار دادن صفحه کلید عدد مربوطه از صفحه کلید دریافت و روی سون سگمنت نمایش داده شود .

 

حل :

مرحله اول : طراحی سخت افزار

Atmega32_Mesal2

مرحله دوم : طراحی نرم افزار

در این مرحله به سراغ نرم افزار CodeVision رفته و طبق مراحل گفته شده در فصل قبل پروژه جدید را می سازیم و فرکانس میکرو را روی ۱Mhz داخلی قرار می دهیم . برنامه نهایی به صورت زیر است .

 

توضیح : آرایه data همان اعداد روی سگمنت هستند که چون در تمام برنامه به آن احتیاج داریم در ابتدای برنامه و به صورت global تعریف شده است . توابع display و keyboard دقیقا کار همان توابع گفته شده را انجام می دهند و حتی میتوان آن ها را با هم جایگزین کرد . تنها تفاوت این دو تابع با قبل این است که به صورت برنامه وار و حرفه ای تر نوشته شده اند تا خطوط کمتری اشغال و حجم حافظه برنامه را کاهش دهد . در حلقه while ابتدا عدد گرفته شده از صفحه کلید درون متغیر key ریخته می شود . تابع keyboard در صورتی که هیچ کلیدی زده نشده باشد مقدار ۲۰ را بر می گرداند و اگر مقدار key برابر ۱۱ باشد یعنی عدد ۰ را کاربر فشار داده و توسط if مقدار آن اصلاح می شود . در صورتی که کاربر کلیدی را زده باشد و کلیدی که زده شده یکی از کلید های ۰ تا ۹ باشد شرط if دوم برابر شده و داخل آن می شود . متغیر i همان عددی است که روی ۴ عدد سون سگمنت توسط متغیرهای data باید نمایش داده شود . بنابراین در حلقه for موجود عدد i به ۴ قسمت (یکان ، دهگان و …) تبدیل می شود و هر کدام روی متغیر data مربوطه قرار می گیرد . و در نهایت تابع display برای ۱۰ بار اجرا می شود که اگر یک بار اجرا شود برنامه بسیار سریع عمل میکند .

دانلود مثال عملی شماره ۳

 


اتصال صفحه کلید 4 در 4 به میکرو

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

keypad4in4_c

در این صورت برای خواندن از صفحه کلید به روش سطری/ستونی که برای صفحه کلید ۳ در ۴ نیز گفته شد ، دقیقا به همان صورت عمل می کنیم. بنابراین برنامه به صورت زیر در می آید.

تمرین : برنامه فوق را با برنامه صفحه کلید ۳ در ۴ مقایسه کنید. مشاهده می شود در هر سطر برای خواندن ستون ها از ۴ دستور if اسفاده شده است.
نتیجه : برای خواندن صفحه کلید به صورت ستونی ، به تعداد ستون ها از دستور شرطی if استفاده می شود.

 


برنامه حرفه ای تر اتصال صفحه کلید 4 در 4 به میکرو

روش خواندن از صفحه کلید در برنامه قبلی به صورت سطری/ستونی بود. برای حرفه ای تر شدن برنامه یک آرایه select تعریف می کنیم که بتوان از آن آرایه در حلقه for استفاده کرد و اندیس حلقه for را به جای آرگومان آرایه استفاده کرد. بنابراین با فرض اتصال یک صفحه کلید ۴ در ۴ به همان صورت شکل قبلی به میکروکنترلر ، برنامه زیر را داریم :

توضیح : عملکرد این تابع نیز دقیقا به همان صورت گفته شده در مثال عملی شماره ۳ است با این تفاوت که یک آرایه به نام code برای اصلاح اعداد صفحه کلید در نظر گرفته شده است. در صورتی که این آرایه نباشد با زدن مثلا کلید ۷ عدد ۰ نمایش داده می شود ! بنابراین به جای اینکه i*4+j به خروجی فرستاده شود ،  [code[i*j+j به خروجی فرستاده می شود تا بدین وسیله اعداد اصلاح شود.

 

نکته : آرایه code را میتوان به صورت char یا unsigned char تعریف کرد. زمانی که در پروژه از 7segment استفاده می شود باید آرایه code را به صورت unsigned char تعریف کرد و در صورت استفاده از LCD باید آرایه code را به صورت char تعریف کرد. البته در صورت استفاده از سون سگمنت نمیتوان کاراکترهایی مثل ضرب ، جمع و … را روی آن نمایش داد.

 

تذکر : به تفاوت های میان برنامه نوشته شده برای صفحه کلید ۳ در ۴ با صفحه کلید ۴ در ۴ توجه کنید.

 


با کلیک بر روی تصویر زیر به بخش بعدی آموزش بروید

next-image



در صورتی که این مطلب مورد پسندتان بود لایک و اشتراک گذاری فراموش نشود.

دیدگاه (34)

  • moslem ghanbar پاسخ

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

    1394-02-07 در 21:13
    • محمد حسین پاسخ

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

      1394-02-07 در 22:11
  • حیدری پاسخ

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

    1394-02-08 در 10:03
    • محمد حسین پاسخ

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

      1394-02-08 در 14:53
  • reza پاسخ

    سلام دوستان.من یه متغیر در eepromتعریف کردم از نوع int و متوجه شدم که هر مقداری که بهش بدم اون فقط مقدار -۲۲۱۱۷ رو داره.و اگه از نوع unsigned char تعریف کنم فقط ۱۵۵ رو داره هر چند که من مقدار دیگه ای بهش بدم.این کارو بعد از نمایش روی lcd متوجه شدم.کسی میدونه مشکل از کجاس؟

    1394-05-04 در 11:24
  • مسعود پاسخ

    سلام
    ازتون راهنمایی می خواستم
    چطور می تونم یک شمارنده باینری با mega16 درست کنم . یعنی چهارتا یایه رو انتخاب کنم و ابتدا led های متصل به آن ها خاموش باشند ( ۰۰۰۰) بعد با یکم تاخیر یکی یکی به اون اضافه بشه تا اینکه همه led ها روشن بشن (۱۱۱۱ ) . یعنی در واقع برنامه یک شمارنده باینری رو می خواستم.
    ممنون

    1394-08-12 در 12:41
    • محمد حسین پاسخ

      سلام دوست عزیز در واقع شما یک شمارنده باینری بالا شمار می خواهید که در همین تایپیک مثال عملی شماره ۲ توضیح داده شده است …

      1394-08-12 در 19:03
  • نگار پاسخ

    سلام
    ببخشید یه سوال داشتم. آی سی ۷۴۴۷ سه تا پایه داره به اسم های BI/RBO – RBI – LT . این پایه ها برای چی هستن؟
    الان دیدم شما برای ۷۴۴۸ اون ۳ پایه رو دادین به تغذیه. ولی من یه برنامه نوشتم که آی سی ۷۴۴۷ رو بدون این که اون ۳ تا پایه به جایی وصل باشند گذاشتم و کامل هم درست جواب داد. حالا حتمآ باید وصل باشند؟

    1394-09-07 در 19:40
    • محمد حسین پاسخ

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

      1394-09-08 در 12:11
      • نگار پاسخ

        کلا این ۳ تا پایه برای ۷۴۴۸ یا ۷۴۴۷ یا اگه تو هر آی سی دیگه ای بود باید به Vcc وصل بشن؟ یا بسته به دیتاشیت اونها ممکنه به زمین باید وصل بشن؟

        خیلی خیلی ممنون از پاسختون.

        1394-09-08 در 14:59
  • نگار پاسخ

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

    1394-09-08 در 15:10
    • محمد حسین پاسخ

      خواهش میکنم … شاید سوال شما سوال بقیه هم باشه …
      در کل نمیشه به پروتئوس اعتماد کرد و باید به دیتاشیت قطعه مراجعه کرد …
      کلید انواع مختلفی داره که توی پروتئوس شامل DIP Switch ، Switch ، Push Button میشه که هر کدوم کاربرد خاص خودشو داره و اگه تو پروتئوس این اسم ها رو بزنید میاره …

      1394-09-08 در 20:34
  • mojahe پاسخ

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

    1394-11-06 در 07:18
    • محمد حسین پاسخ

      سلام ممنونم
      برای صفر کردن یک آرایه یا یک رشته از کاراکترها باید تمامی عناصر آن را با استفاده از حلقه فور صفر کرد مثلا برای یک آرایه 8 کاراکتری به نام str باید نوشت :
      for(i=0;i<8;i++) str[i]=0

      1394-11-06 در 09:38
  • hameddd پاسخ

    سلام
    من یه سوال دارم
    من وقتی صفحه کلید 3*4 رو به پایه های میکرو وصل میکنم ومدارو تو پروتئوس ران میکنم, ارور میده که پایه های AتاD
    صفحه کلید به تغذیه وصل نشده.چیکار کنم؟
    یعنی بیام سطرهارو مثل ستونها PULL UP کنم؟

    1394-12-09 در 09:14
  • رامین پاسخ

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

    1395-10-05 در 09:56
    • ادمین الکترو ولت پاسخ

      سلام دوست عزیز ممنونم
      بله میتونید تایمر یک ثانیه ایجاد کنید و داخل روتین وقفه هر ثانیه یک واحد اضافه کنید و به محض ۶۰ شدن خروجی را تغییر وضعیت دهید. به بخش تایمر مراجعه کنید

      1395-10-07 در 19:08
  • رضا پاسخ

    سلام با تشکر از مطالب خیلی مفیدتون
    میخواستم بدونم چطور میشه مقدار متغیرها رو طوری حفظ کرد که با ریست شدن میکرو از بین نره. البته میدونم همون طور که گفتید باید محل تعریف اونها رو flash یا eeprom در نظر بگیرم مثلا بنویسیم flash int; یا eeprom int; اما من میخوام بدونم دقیقا چطور باید عمل کنیم یا اگر مثلا بخواهیم این متغیرهایی که در حافظه فلش هستن رو با یک متغیر موجود در sram مقدار دهی کنیم چه کار باید کرد چون من این کارو که میکنم توی کدویژن خطای زیر رو به من میده:

    the expression must be a modifiable ivalue

    سوال دیگه اینکه دلیل اینکه میکرو AVR هر چند وقت یک بار به طور خودکار ریست میشه چیه و چطور این مشکل حل میشه؟ آیا مشکل از تغذیه است؟ حتی وقتی که از رگولاتور 7405 با ورودی 12 ولت هم استفاده میکنم این مشکل وجود داره. و در کل به نظر شما استفاده از سری MEGA AVR برای یک کاربرد واقعی یا صنعتی که نیاز به عملکرد 24 ساعته میکرو داره مناسب هست یا نه باید سراغ میکروکنترلر دیگه ای برم.
    خواهش میکنم کمکم کنید بنده یک پروژه واقعی در دست اجرا دارم و باید در قبال آن جوابگو باشم خدا خیرتون بده
    یا علی

    1395-10-10 در 11:19
    • ادمین الکترو ولت پاسخ

      عرض سلام و معذرت بابت تاخیر در پاسخگویی
      بله فقط کافیه در هنگام تعریف از نوع flash یا eeprom تعریف شوند
      خطایی که به شما میدهد برای چیز دیگری است
      علت ریست شدن میکرو از تغذیه میتونه باشه یا واحد تایمر Watchdog آن فعال است
      میکروکنترلرهای AVR در صورت رعایت تمهیدات سخت افزاری و نرم افزاری کاملا صنعتی بوده و میتوان در محیط های پر نویز هم از آن ها استفاده نمود موفق باشید

      1396-02-21 در 08:03
  • بهزاد پاسخ

    سلام وخسته نباشید
    برنامه ledدر قسمت ششم اموزش مستقیمابا#includeنوشته شده
    اما همون برنامه در این قسمت اموزش باspan styleشرو شده میخواستم بدونم تفاوت این دو نوع برنامه نویسی که هر دو یک کارو انجام میدن چیه دقیقا؟

    1396-05-16 در 15:21
    • ادمین الکترو ولت پاسخ

      سلام دوست عزیز span style یک اشتباه تایپی هستش و شما نباید در نظر بگیرید

      1396-05-16 در 17:10
  • بهزاد پاسخ

    اها مرسی.
    سوال دیگرم اینه که
    دستورamp& در کلید نوع سه چی هستش دقیقا؟
    چون بالاتر در موردش توضیح ندادین

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

    1396-05-18 در 15:29
    • بهزاد پاسخ

      اصلاح میکنم سوال دومم رو که گفتم کلید نوع دو اما باید مینوشتم کلید نوع یک
      bounceو…

      1396-05-18 در 15:30
  • vahid پاسخ

    سلام و درود فراوان
    من این شرط رو (if(flag متوجه نمیشم مثال عملی 2
    میشه در موردش توضیح بدین
    فلگ چه نوع متغییری هست که ایف داره اونو بررسی می کنه

    1396-09-11 در 10:00
  • ادمین الکترو ولت پاسخ

    سلام دوست عزیز
    متغیر flag یک متغیر کمکی هست برای زمانی که دو حالت عملکرد داریم در حالت اول flag=0 و یک کار خاصی انجام می شود و در حالت دوم flag=1 و یک کار خاص دیگری انجام می شود

    1396-09-12 در 13:57
  • sina پاسخ

    سلام دوست عزیز،
    من یه سوال دارم
    چطور میشه به ال سی دی کاراکتری، کاراکتر های کنترلی رو ارسال کرد، من فایل alcd.h رو خوندم اما بنظرم تابع خاصی برای این کار نداره، یا من نمی دونم، حتی با خود lcd_putchar هم عدد اسکی مربوط به کاراکترهای کنترلی مثلا 1 تا 30 رو فرستادم اما تغییری ندیدم، من می خوام مکان نما برای رفتن روی کاراکتری خاص جابجا بشه، تا مثلا روی ساعت تغییر ایجاد کنم، یعنی کاربر بتونه ساعت رو تنظیم کنه، خب باید کاربر بدونه الآن داره چی رو تغییر میده، بخاطر همین می خوام کاربر مکان نما رو جابجا کنه تا به کاراکتر مخصوص برسه و اون رو تغییر بده، ممنون میشم راهنماییم کنی،
    راستی یه سوال دیگه، میگن تو السیدی کاراکتری فقط میشه 8 تا کاراکتر فارسی ایجاد کرد، بنظرت راسته، یعنی نمیشه بیشتر بشه؟
    بازم ممنون
    یا علی

    1397-02-13 در 09:40
    • ادمین الکترو ولت پاسخ

      سلام بله میتوان به LCD کاراکترهای کنترلی ارسال کرد. برای اطلاعات بیشتر کافی است به help نرم افزار کدویژن سپس help topic سپس Library Function Refference و سپس Alphanumeric LCD Function مراجعه نمایید. ضمنا به علت محدودیت حافظه LCD تنها میتوان 8 کاراکتر ایجاد کرد.

      1397-02-14 در 09:57
  • ahmad پاسخ

    سلام
    segment اعداد ناقص نمایش میده مثلا برای صفر تمامی led ها روشن میشن به جز d مشکل کجاست

    1397-07-27 در 22:33
  • مجید پاسخ

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

    1397-09-16 در 00:12
    • ادمین الکترو ولت پاسخ

      سلام دوست عزیز ممنون از نظرتون حتما سعی میکنم مجددا توضیح جامع تری دهم

      1397-09-18 در 13:46
  • یوناتان پاسخ

    با سلام و عرض ادب
    من میخوام روی atmega8 از سه تا پورت مختلف به صورت همزمان استفاده کنم
    یعنی همزمان که پورت B چشمک میزنه پورت C و D یه کار متفاوت کنن
    چجوری باید دستورش رو بنویسم

    1397-12-20 در 18:06
  • امیر خیراندیش پاسخ

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

    1398-02-04 در 21:46
  • David پاسخ

    سلام. ممنون از توضیحات جامع و خوبتون. در مثال عملی دوم، توی پروتئوس قبل سوئیچ فشاری یک مقاومت 10k اهمی هست بعدش با یک فلش زده بالا. فلشه رو از کجا باید پیدا کرد؟ و کارش چیه؟
    بعد شما با مقاومت ساختین سوئیچ رو با خازن هم میشه درسته؟

    1398-05-14 در 17:23
  • امیر حسین پاسخ

    سلام
    سپاس از توضیحات عالی این سایت! من می خواهم چند سنسور را از طریق مد باس rs485 به هم ارتباط بدهم. حال برای هر میکرو(سنسور) چطور باید یک آدرس تخصیص دهم؟

    1398-08-07 در 11:11

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

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

بازگشت به آموزشگاه