پنج شنبه , ۲ آذر ۱۳۹۶
آخرین نوشته‌ها
خانه | سیستم های نهفته | میکروکنترلر | دوره آموزشی AVR | پورت های ورودی و خروجی در AVR (جلسه ۱)

پورت های ورودی و خروجی در AVR (جلسه ۱)

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

در پایان این پست:

• در مورد تراشه ی رایج AVR و تعداد پورت ها و امکاناتشون خوندید.

• در مورد پورت ها و رجیسترهای مربوطه شون می دونید.

• برنامه نویسی و کار با پورت های ورودی و خروجی در AVR رو یاد گرفتید.

• یه پروژه ی ساده برای کار با پورت ها رو در محیط CodeVision برنامه نویسی و در محیط Proteus شبیه سازی خواهید کرد.

برای یادگیری بهتر انتظار میره که موارد زیر رو بدونید:

¤ آشنایی مقدماتی با زبان C (برای یادگیری زبان C اینجا کلیک کنید.)

¤ آشنایی با اعداد باینری و گیت های منطقی (برای یادگیری مدارهای منطقی اینجا کلیک کنید.)

¤ و در صورت علاقه زبان اسمبلی بلد باشید. (برای یادگیری زبان اسمبلی اینجا کلیک کنید.)

پورت های ورودی و خروجی در AVR

در میکروکنترلرهای AVR پورت های زیادی برای انجام عملیات ورودی/خروجی وجود دارند. بسته به اینکه تراشه ی مورد نظر کدام عضو از خانواده ی AVR باشد، تعداد پورت ها، تعداد پایه‌های هر پورت و کاربرد پورت ها متفاوت خواهد بود. نامگذاری پورت ها با حروف بزرگ انگلیسی و با شروع از حرف A انجام می شود. مثلاً اگر تراشه ای ۴ پورت داشته باشد، داریم: PORTA، PORTB، PORTC و PORTD. پورت های AVR علاوه بر ورودی و خروجی بودن کاربردها و قابلیت‌های دیگری نیز دارند که در جلسات آتی در مورد آن‌ها بحث خواهد شد. جدول زیر تراشه های رایج و تعداد پورت هایشان را نشان می دهد.

PortAVRtable

برای به کارگیری پورت ها جهت استفاده به عنوان ورودی و خروجی باید آن‌ها را برنامه‌ریزی نمود. پورت های ورودی و خروجی در AVR هرکدام  دارای سه ثبات به نام های PORT و DDR و PIN می باشد. به عنوان مثال سه ثبات مربوط به پورت C عبارتند از: PORTC و DDRC و PINC.

پورت های ورودی و خروجی

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

رجیستر DDRx

یک پورت می‌تواند هم نقش ورودی داشته باشد و هم نقش خروجی. اما چگونه؟ این کار با برنامه‌ریزی ثبات DDR انجام می گیرد. DDR که مخفف عبارت Data Direction Register می باشد، ثباتی هشت بیتی است. برای هر پورت یک ثبات DDR داریم که هم نام پورت است. به عنوان مثال ثبات DDR مربوط به پورت A به صورت DDRA شناخته می شود. هریک از بیت‌های ثبات DDRx یکی از پین های پورت x را کنترل می‌کند. برای مثال بیت پنجم ثبات، پنجمین پین پورت را کنترل می کند. ddrx-explanation به منظور تنظیم کردن یک پین به عنوان ورودی، باید بیت مربوط به آن پین در ثبات DDR مربوطه روی مقدار صفر برنامه‌ریزی شود. به طور عکس برای تنظیم کردن یک پین به عنوان خروجی، باید بیت مربوط به آن پین در ثبات DDR مربوطه روی مقدار یک برنامه‌ریزی شود. به عنوان مثال فرض کنید می‌خواهیم پین ۳ و ۷ از پورت B را به عنوان خروجی و بقیه ی پین ها را به عنوان ورودی تنظیم کنیم. در زبان C باید بنویسیم:

و در زبان اسمبلی باید بنویسیم:

توجه شود که بیت ۳ و ۷ یک و دیگر بیت‌ها صفر شده‌اند. برای انجام این کار برای دیگر پورت ها نیز به همین صورت باید عمل کرد.

سؤالی که در اینجا پیش می‌آید این است که: «در پورت های ورودی و خروجی در AVR که تعداد پین ها کمتر از هشت عدد است تکلیف بیت‌های اضافی در رجیستر DDR چیست؟ و اگر ما مقدار آن ثبات را روی یک عدد هشت بیتی تنظیم کنیم چه اتفاقی برای بیت‌های اضافی می افتد؟» در جواب باید گفت که اتفاقی نمی‌افتد و میکروکنترلر بیت‌های اضافی را نادیده می گیرد.

رجیستر PORTx

یکی دیگر از رجیسترهایی که وضعیت صفر/یک پین را کنترل می‌کند رجیستر PORTx است. هر بیت در این رجیستر پین متناظر در پورت را کنترل می کند. به عنوان مثال بیت پنجم از این رجیستر پین پنجم از پورت مورد نظر را کنترل خواهد کرد. این رجیستر بر حسب این که پورت به عنوان خروجی و یا ورودی تنظیم شده باشد (توسط تنظیم رجیستر DDRx)، دو وظیفه دارد:

حالت ۱)‌ صفر یا یک کردن پین (در صورتی که پین مورد نظر در نقش خروجی عمل کند): portx-0xff-explained1همان طور که در شکل بالا مشاهده می شود، در حالتی که پین به عنوان خروجی عمل کند (بیت مربوط به آن در رجیستر DDRx روی یک تنطیم شده باشد) با یک کردن بیت مربوط به آن پین در رجیستر PORTx ، مقدار آن پین در خروجی یک (high) خواهد شد. و به طور عکس با صفر کردن بیت مربوط به آن پین در رجیستر PORTx مقدار آن پین در خروجی صفر (low) خواهد شد. به برنامه‌های زیر که به دو زبان C و اسمبلی نوشته شده‌اند توجه کنید:

در برنامه‌های بالا بیت‌های صفر، سه و هفت ست (set) و بیت‌های صفر و دو ریست (reset) می شوند. دیگر بیت‌ها در حالت امپدانس بالا قرار می‌گیرند چرا که به عنوان پین های ورودی تنظیم شده اند.

حالت ۲) فعال/غیرفعال کردن مقاومت‌های پول آپ داخلی (در صورتی که پین مورد نظر در نقش ورودی عمل کند):

portx-internal-pullup1در میکروکنترلر AVR همه ی پین ها به مقاومت پول آپ مجهزند. در حالتی که یک پین در نقش ورودی عمل کند، مقاومت پول آپ مربوط به آن را می‌توان با برنامه‌ریزی بیت مربوط به آن در رجیستر PORTx فعال یا غیر فعال کرد. در صورتی که آن را با یک برنامه‌ریزی کنیم مقاومت پول آپ فعال می‌شود و به طور عکس اگر آن را با صفر برنامه‌ریزی کنیم مقاومت پول آپ غیر فعال می شود. فعال کردن مقاومت‌های پول آپ ورودی را به حالت یک می برد. با فعال کردن مقاومت‌های پول آپ از نویزی شدن ورودی جلوگیری می کنیم.

در برنامه های زیر که به ترتیب به زبان C و اسمبلی نوشته شده اند، پورت B به عنوان ورودی برنامه‌ریزی شده و سپس مقاومت‌های پول آپ پین های ۱، ۳، ۵، ۶ و ۷ آن فعال شده اند.

✓ به طور پیش‌فرض پین های AVR در حالت ورودی و امپدانس بالا قرار دارند. یعنی هم بیت‌های رجیستر DDRx و هم بیت‌های رجیسترPORTx با صفر برنامه‌ریزی شده اند.

رجیستر PINx

pinx-explanation1

رجیستر PINx شامل وضعیت تمام پین های مربوط به آن پورت است. اگر پین مربوطه به عنوان ورودی تنظیم شده باشد، بیت مربوط به آن پین در رجیستر PINx سطح منطقی آن پین را نشان می دهد. و اگر پین مربوطه به عنوان خروجی تنظیم شده باشد، بیت مربوط به آن پین در رجیستر PINx شامل آخرین داده ی خروجی بر روی آن پین می باشد. برنامه‌های زیر وضعیت پورت D را خوانده و ذخیره می کنند:

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

inside_AVR_IO_port انجام یک پروژه ی ساده:

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

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

درباره‌ی مجتبی

کارشناس الکترونیک و کارشناس ارشد مخابرات سیستم | زمینه ی تحقیقاتی : پردازش تصویر و تعقیب اشیاء متحرک |‌فعال در حوزه ی الکترونیک مبتنی بر میکروکنترلر | برنامه نویس و طراح بردهای الکترونیکی مبتنی بر میکروکنترلر

۲۰ ديدگاه

  1. سلام ببخشید میشه یه کمک بهم بکنید در مورد پروتئوس!
    میخوام بدونم مدار and و or رو که بخوایم ببنیدم چطوریه؟ورودی های صفر و یکش چیه؟!برای خروجی که نشون بده صفر و یک رو از چی باید استفاده کنیم؟؟؟
    هیچی بلد نیستم ازش ولی پروژه باید تحویل بدیم ترخدا بهم یاد بدین!!
    از چیا باید استفاده کنیم؟؟

  2. مطلبتان خیلی مفید بود متشکرم

  3. البته باید اضافه کنم که در حالت وقتی port را ٠ یا ١ (pull up)تعریف میکنم وقتی خروجی ها را قطع می کنم بعد از کلیک کردن مثل حالت وصل خروجی ها عمل می کند و تفاوت بین وصل خروجی و قطع خروجی در زمانی نمایان هست که پورت تعریف نشود و همان ٠ و٣ که در بالا گفتم نمایش داده می شود
    با تشکر از راهنماییتون

  4. سلام
    وقت بخیر
    لطفا بفرمایید امپدانس بالا چطور تعریف میشه؟
    برای dtmf :
    Ddrرا بطور کلی ورودی قرار دادم
    هنگامی که port را pull up قرار می دم یا صفر قرار می دم و هنگامی که پورت را تعریف نمی کنم خروجی در lcd پس از کلیک اعداد فقط ٠یا١یا٢یا٣
    می باشد البته این در حالی هست از دستو. PIN.3*8+…
    استفاده می کنم و هنگاهمی port تعریف نشده و بجای pin از port استفاده می شود خروجی فقط ٠ است
    خروجی دارم چون وقتی خروجی ها رو قطع می کنم در حالت اول (pull up) خروجی یا صفر است یا ٣
    برای ارسال خروجی از دستور sprint (buffer,”%d”);a
    لطفا بفرمایید مشکل از کجا هست؟
    متشکرم

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

  5. درود بر شما واقعا عالی بود

  6. ببخشید عوامل اینکه باهم متفاومت میشوند چیه ؟ چرا اینجوری میشه؟ راهایی برای جلوگیری از این وضعیت هست؟

    • می تونه عامل های مختلفی وجود داشته باشن.
      یکی از عوامل نامطلوب تداخل یه سیگنال دیگه بر روی پین خروجیه که مقدار ولتاژ پین خروجی رو تحت تاثیر قرار میده و ما اون خروجی ای که میخوایم رو دیگه نخواهیم داشت. این سیگنال نامطلوب میتونه ناشی از مداربندی های خارج از میکروکنترلر باشه، چون در هرصورت میکروکنترلر ما درون یک مدار قرار داره. در این صورت باید مداربندی رو طوری انجام داد که این اثرات نامطلوب اتفاق نیفته.
      مثال دیگه ای که میتونم از عوامل نا مطلوب بزنم اتصال کوتاه شدن یه پین خروجی با مقدار high (یک منطقی) هست. یعنی پین خروجی ای که مقدارش یک هست به زمین وصل باشه. در این صورت مقدار PORT.x یک و مقدار PIN.x صفر میشه. البته با این اتفاق ممکنه پین آسیب ببینه و گاهی مواقع هم چون پین ها تا حدودی جریان محدود هستن ممکنه فقط باعث داغی میکروکنترلر بشه. در هر صورت نامطلوبه.
      اما همیشه هم عوامل نامطلوب نیستن. به عنوان مثال فرض کنیم که یک LED رو مستقیما و بدون مقاومت واسط، به پین میکروکنترلر وصل کنیم و اون پین رو یک کنیم. با این کار LED بایاس شده و روشن میشه. حتما این کار رو تجربه ش کردی. در این صورت اتفاقی هم برای میکروکنترلر نمیفته. اما ولتاژ پین دقیقا برابر با ولتاژ وصل LED میشه (که میشه فرض کرد زیر ۳ ولت هست) . در این حالت درسته که مقدار PORT.x برابر با یک هست. ولی مقدار PIN.x صفر خواهد بود.

      در خدمتم.

  7. در واقع اینجوری میشه گفت که وقتی پینی بصورت خروجی تعریف شود مقدارش در رجیستر PORTX.n ذخیره میوشد یعنی عملیاتی در میکروکنترلر انجام میوشد و نتیجش در رجیستر PORTX.n ذخیره میشود و و چون در حالت خروجی هست هر نتیجه ای که در رجیستر PORTX باشد همان نتیجه در پین های مربوط به آن پورت ظاهر میوشد و اگر بصورت ورودی باشد دیگر ارتباط پین ها با رجیستر PORTX قطع میوشد در این حالت محتوای رجیستر PORTX ، پول آپ بودن و امپدانس بودن ورودی را نشان میدهد و در حالت کلی چه ورودی چه خروجی باشد مقادیر پین ها در رجیستر PINX ظاهر میوشد و بنابراین اگر حالت خروجی در نظر بگیریم چون رجیستر PORTX با پین ها ارتباط دارد و در هر صورت هم پین ها با رجیستر PINX ارتباط دارند لذا در این حالت بیت های متناظر رجیستر PORTX در رجستر PINX ظاهر می شوند.
    ببخشید ببینید برداشتم کلا درست هست یا نه؟

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

  8. ببخشید من رجیستر pin رو خوب نفهمیدم خب وقتی مقادیر پین ها در رجیستر port قرار میگیرد اونوقت رجیستر pin به چه دردی میخورد؟

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

      – وقتی بخوای یه پین (در حالت خروجی) رو صفر یا یک کنی، مقدار مورد نظرت رو بر روی PORT.x می ریزی.
      – وقتی بخوای بدونی که چه ولتاژی بر روی یک پین اعمال شده و اون پین در چه حالت دیجیتالی (۰ یا ۱) قرار داره، مقدار PIN.x اون رو میخونی.
      – رجیستر PORT هم قابل خوندنه و هم قابل نوشتن. ولی رجیستر PIN فقط قابل خوندن هست.
      – وقتی بخوای مقدار رجیستر یک پین از PORT رو بخونی، باید PORT.x رو بخونی.
      – وقتی بخوای مقدار ولتاژی که به صورت خارجی و فیزیکی روی یک پین اعمال شده رو بخونی، PIN.x رو میخونی.

      عبارت های بالا رو چند بار بخون و به ادامه ی توضیحاتم دقت کن:

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

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

  9. با سلام
    ببخشید مقاومت های پول آب برای کاهش نویزی شدن پین های در نظر گرفته شده است یا برای آسیب ندیدن میکرو؟

    • سلام،
      در مورد کاربردهای مقاومت پول آپ من تا به حال موردی برخورد نکرده م که مربوط به آسیب دیدن یا ندیدن میکروکنترلر باشه. در صورتی که این مطلب رو جایی خوندین حتما من رو در جریان بذارین. چون خود من هم همیشه در حال یادگیری هستم.
      فرض کنید یه سوییچ داریم که به هنگام بسته شدن، پین میکروکنترلر رو به زمین وصل می کنه. و میکروکنترلر با تشخیص صفر شدن مقدار پین، کار خاصی رو انجام می ده. ولی وقتی که کلید باز باشه پین میکرو در چه حالتی قرار داره؟ و به کجا وصله؟ عملا به جایی وصل نیست. به این وضعیت میگن امپدانس بالا یا حالت شناور. در این حالت پین ممکنه هر مقداری داشته باشه و نامشخصه. به همین خاطر پین می تونه نویزی بشه و میکروکنترلر اشتباها فشرده شدن کلید رو تشخیص بده و مشکلات ایجاد بشه. برای جلوگیری از این کار باید پین رو به Vcc وصل کنیم تا مقدار پین فقط وقتی صفر بشه که کلید فشرده شده باشه و در غیر این صورت به طور پایدار مقدارش یک باقی بمونه. با استفاده از مقاومت پول آپ به هدفمون می رسیم.
      پس استفاده از مقاومت پول آپ دو مزیت داره:
      ۱) پین رو از حالت شناور در میاره.
      ۲) مقدار پین رو به طور پیشفرض با یک (ولتاژ بالا) برابر می کنه.

      در خدمتم.

  10. سلام . ممنون از مطلبتون . در قسمت رجیستر PORTX در عنوان (حالت دوم) به جای ورودی ، خروجی نوشته شده بود .

پاسخ دهید

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

Time limit is exhausted. Please reload CAPTCHA.