آموزش میکروکنترلر XMEGA – قسمت سوم;
در قسمت دوم آموزش میکروکنترلر XMEGA به مباحث کلی در مورد خانواده XMEGA از جمله محدوده دما و تغذیه و کلاک پرداختیم. در این قسمت از آموزش میکروکنترلر XMEGA به آشنایی با رجیسترهای پورت در این خانواده میپردازیم.
پیش فرض این آموزش داشتن آشنایی نسبی با رجیسترهای خانواده AVR و عملکرد آنها است.
PORTA.DIR:
در خانواده AVR برای تعیین جهت یک پورت و پینهای مربوطه از رجیستر DDR استفاده میشود و بعد از آن نام پورت قرار میگیرد مانند DDRA.
در خانواده XMEGA برای تعیین جهت پورتها از رجیستر PORTA.DIR استفاده میشود که DIR به معنای DIRECTION است. از این رجیستر به شکل PORTA_DIR هم میتوان استفاده کرد. پس اگر در این رجیستر بیتی را یک قرار دهیم پین متناظر در پورت به عنوان خروجی تعریف میشود.
PORTA.OUT:
در AVR برای تعیین وضعیت HIGH/LOW پایهها از رجیستر PORT استفاده میشود، این رجیستر در خانواده XMEGA به صورت PORTA.OUT وظیفه تعیین صفر و یک بودن پورتها را بر عهده دارد.
البته این رجیستر در AVR وظیفه فعال کردن PULL UP داخلی برای پینهای ورودی را نیز دارد، بدین معنا که اگر یک پین به صورت وروردی تعیین شده باشد و بیت متناظر در رجیستر پورت یک قرار داده شود PULL UP فعال میشود.
اما مسئله فعال شدن PULL UP در رجیستر متناظر در XMEGA ،که PORTA.OUT است برقرار نیست. این رجیستر برای تعیین وضعیت پینهایی است که به صورت خروجی تعریف شدهاند، اما برای پینهای ورودی وظیفه فعال کردن PULL UP به عهده این رجیستر نیست.
برای مثال میخواهیم پین شماره صفر از پورت A را به صورت خروجی تعریف کنیم;
برای اینکار باید بیت شماره صفر در PORTA.DIR را یک قرار دهیم. حال اگر بخواهیم این پین در وضعیت LOW باشد باید در بیت شماره صفر در PORTA.OUT صفر نوشته شود و اگر بخواهیم در وضعیت HIGH باشد باید بیت مربوطه یک نوشته شود.
PORTA.IN
در AVR برای دسترسی به وضعیت پینها از دستور PINA استفاده میشود با این تفاوت که در XMEGA از دستور PORTA.IN استفاده میشود، این دستور امکان دسترسی CPU به پینهای PORTA برای تعیین وضعیت HIGH/LOW را فراهم میکند .
به عنوان یک قاعده کلی در مقداردهی به رجیسترها سعی میشود از اعداد استفاده نشود. بلکه از عبارتهای معنی دار معادل که در فایلهای هدر کامپایلر وجود دارد استفاده میکنیم.
با استفاده از دستور ;PORTA.DIR=0X01 میتوان PA.0 را در وضعیت خروجی قرار دهیم. میتوان به جای این دستور از PORTA.DIR=1<<0 استفاده کرد. اما به جای این دو دستور بهتر است از ;PORTA.DIR=PIN0_bm که در فایل هدر iox64a3.h تعریف شده است استفاده کنیم.
همانطور که در قبل اشاره شد مبنای کار ما atmel studio است و این فایل هدر هم در کتابخانه atmel studio وجود دارد. همچنین در برد آموزشی از ATXMEGA 64 A3 استفاده میکنیم.
عباراتی در کدها وجود دارد که دستور را خواناتر میکند. پس به همین دلیل سعی بر این است که به جای مقداردهی عددی از عبارات تعریف شده در هدرها استفاده کنیم. اهمیت این مساله در زمانی مشخص است که تناظری در مقداردهی رجیستر و خروجی وجود ندارد، مثلاً در رجیستر مربوط به تایمر کانتر، USART ،SPI و … باید به طور کلی از عبارات معنیدار استفاده کنیم که هم برای خود ما و هم برای کسانی که میخواهند از این کدها استفاده کنند قابلیت استفاده مجدد داشته باشد و اصلاحات بعدی که ممکن است روی کد انجام گیرد به سادگی انجام شود.
برای فهم این مساله به مثال زیر توجه کنید.
اگر بخواهیم از طریق رجیستر PORTA.OUT پینهای شماره 0 و 1 را در وضعیت HIGH قرار دهیم و پینهای شماره 2 تا 7 را در وضعیت قبلی خودشان باقی بمانند، باید از عملگر OR استفاده کنیم.
1 | PORTA.OUT|=PIN1_bm|PIN0_bm; |
اگر بخواهیم مقدار پینهای صفر و یک را با صفر کردن بیتهای متناظر انجام دهیم، باید به جای OR از AND کنیم. اگر PORTA.OUT را بخوانیم و 0XFC را با آن ،AND کنیم، بیتهای شماره 2 تا 7 در وضعیت قبلی خود باقی میمانند و فقط بیتهای 0 و 1 صفر میشوند. این عملیات را اصطلاحا READ MODIFY WRITE مینامند. در زیر عبارت ;(PIN1_bm|PIN0_bm) برابر 0XFC است.
1 | PORTA.OUT & =~(PIN1_bm|PIN0_bm); |
عمل بعدی عملیات NOT یا TOGGLE کردن وضعیت برخی بیتها با حفظ وضعیت باقی بیتها است، که برای این حالت به وسیله XOR این کار را انجام میدهیم.
هر بیتی که با یک XOR شود وضعیت آن NOT میشود، یعنی اگر صفر است یک میشود و اگر یک است صفر میشود. این عملیات READ MODIFY WRITE تامیده میشود.
این نوع عملیات زمان بیشتری را به دلیل چند مرحلهای بودن دستور اشغال میکند. این زمان شامل خواندن رجیستر، سپس با مقدار مورد نظر OR یا AND و … کردن و در آخر نوشتن در محل است. هرچند یک دستور داریم ولی باید توجه داشت زمانی که به کدهای اسمبلی ترجمه میشود به چندین مرحله تقسیم میشود.
افزایش مراحل انجام دستور علاوه بر افزایش زمان باعث افزایش حجم اشغال شده حافظه FLASH میشود.
در خانواده XMEGA امکانی فراهم شده است که نیاز نیست از عملیات READ MODIFY WRITE استفاده شود. علاوه بر اینکه رجیستر PORTA.OUT وجود دارد، متناظر با هر پورت رجیسترهای زیر نیز وجود دارند.
1 2 3 4 5 | PORTA.OUTSET PORTA.OUTCLR PORTA.OUTTGL |
اگر مقداری در این رجیسترها نوشته شود، در بیتهایی که یک هستند عملیات SET,CLR و TGL انجام میشود.
برای مثال اگر بخواهیم فقط پینهای 0 و 1 را یک کنیم از دستور زیر استفاده میکنیم.
1 | PORTA.OUTSET=PIN1_bm|PIN0_bm; |
برای پاک کردن مقدار یک پین از دستور PORTA.OUTCLR استفاده میشود. در این دستور هر بیتی که در رجیستر OUTCLR یک باشد پاک میشود.
با استفاده از دستور PORTA.OUTTGL میتوان بیت متناظر با پین را تغییر وضعیت داد، اگر یک باید صفر میشود و اگر یک باشد صفر میشود.
همچنین این عملیات برای ورودی و خروجی کردن پورتها مورد استفاده قرار میگیرد:
1 2 3 4 5 | PORTA.DIRSET PORTA.DIRTCLR PORTA.DIRTGL |
به عنوان مثال و با استفاده از برد آموزشی که بر اساس این آموزشها و دستورها است به مثال زیر توجه کنید:
برای روشن شدن LEDها باید PE1 تا PE7 و PF0 به صورت خروجی تنظیم شود. وضعیت PF0 باید HIGH باشد و برای روشن شدن هر LED نیاز است پین مربوطه یک شود.
در قسمت چهارم آموزش میکروکنترلر XMEGA با نحوه ایجاد پروژه و کامپایل و پروگرم کردن آن در AtmelStudio آشنا میشویم. با سیسوگ همراه باشید.
- آموزش میکروکنترلر XMEGA – قسمت اول – مقدمه
- آموزش میکروکنترلر XMEGA – قسمت دوم – مقدمه
- آموزش میکروکنترلر XMEGA – قسمت چهارم – نحوه ایجاد پروژه و کامپایل و پروگرام کردن آن در AtmelStudio + دو مثال
- آموزش میکروکنترلر XMEGA – قسمت پنجم – مدهای ورودی و خروجی پورتها
- آموزش میکروکنترلر XMEGA – قسمت ششم – رجیستر های پورت
سری مقالات آموزش میکروکنترلر XMEGA توسط آقای مهندس کینژاد تهیه شده است.
ممنون خیلی کار راه بنداز بود
خواهش میکنم دوست عزیز
باید از جناب استاد کی نژاد تشکر کرد برای تهیه این مجموعه پربار