راه اندازی تایمر

شنبه 29 شهرویور 1393  •  دسته بندی: پروژه های آماده با میکروکنترلر AVR  •  بازدیدها: 5979  •  برچسب ها: |

هدف پروژه: راه اندازی و استفاده از تایمر/کانتر های میکرو و مد های کاری. در این مقاله یک کار روتین که نیاز به اجرا در زمان های مشخص دارد را برسی می کنیم. روال کلی این برنامه این است که هر 500 میلی ثانیه مستقل از زمان اجرای بقیه برنامه، میکرو یک led را روشن یا خاموش می کند. یعنی led با فرکانس دقیق 1 هرتز شروع به چشمک زدن می کند.

سخت افزار مورد نیاز: در این مثال از برد آموزشی avr شرکت نامینیک مبتنی بر تراشه ATMEGA32 استفاده کرده و تایمر صفر میکرو را به کار می گیریم. ضمن اینکه از led شماره d9 متصل به پین صفر پورت b استفاده می کنیم.

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

تشریح کد: تایمر/کانتر در میکرو وسیله ای برای زمان بندی و شمردن وقایع است. تراشه ATMEGA32 سه عدد تایمر/کانتر دارد که به صورت کانتر هم کار می کنند. در حالت تایمر، کلاک واحد از داخل خود میکرو تامین می شود یا منظم است. اما در حالت کانتر که معمولا برای شمارش وقایع استفاده می شود، منبع پالس کلاک واحد از خارج است و می تواند نامنظم باشد. مثلا اگر بخواهیم تعداد بطری های رد شده در یک خط تولید را در ثانیه بشماریم، ورودی کانتر که در حقیقت همان کلاک آن بوده، ممکن است در یک ثانیه 3 تا باشد یا ممکن است اصلا در یک ثانیه هیچ بطری از جلوی سنسور رد نشود و در آن یک ثانیه کانتر پالسی نخواهد داشت و مقدارش تغییری نخواهد کرد. تایمر/کانتر صفر 8 بیتی است. تایمر/ کانتر شماره یک 16 و 8 بیتی است. تایمر/کانتر دو شبیه تایمر صفر است، فقط غیر همزمان بوده و به گونه ای تنظیم شده که با یک کریستال اضافی 32.768 کیلو هرتز می تواند و در یکی از حالات، بدون هیچ برنامه اضافه ای دقیقا فرکانس 1 هرتز تولید کند که که برای سنجش دقیق زمان یعنی ثانیه، دقیقه، ساعت و ... کاربرد دارد. که برای اطلاعات بیشتر از شما دعوت می شود دیتاشیت میکرو را مطالعه فرمایید. تایمر/کانتر مورد بحث ما (تایمر صفر) چه تایمر باشد چه کانتر در 4 مد کار می کند. حالت معمولی، حالت ctc و دو حالت مربوط به تولید پالس pwm. ما از حالت تایمر و از مد ctc استفاده کرده ایم. در این مد تایمر از لحظه روشن شدن شروع به شمارش کرده و هرگاه به مقداری که ما در رجیستر ocr0 تعیین کرده ایم برسد، مقدار تایمر صفر شده و در صورت فعال بودن وقفه، یک وقفه رخ می دهد. تایمر همزمان بوده و هر تغییری در رجیستر ocr0 بدهید، همان لحظه اعمال می شود. قبل از ادامه بحث تایمر اندکی راجه به کتابخانه sleep.h صحبت می کنیم.

میکرو ما 6 مد کم توان دارد. در خط 43 حالت های کم توان در واحد power management فعال شده و در خط 47 در حلقه while پردازنده به مد idle (یکی از 6 مد مذکور) می رود. در این مد فقط کلاک پردازنده متوقف می شود و سایر واحد های جانبی در صورت روشن بودن، به کار خود ادامه می دهند. با خاموش شدن cpu برنامه هم دیگر اجرا نمی شود و میکرو به حالت کم توان رفته است. اما تایمر صفر که در خط 40 آن را استارت کرده ایم به شمارش خود ادامه می دهد. پس هنوز امیدی هست. به محض رسیدن تایمر به مقدار رجیستر ocr0 تایمر یک وقفه به پردازنده ارسال می کند. کلاک پردازنده روشن شده (اصطلاحا بیدار می شود) و سرویس وقفه را در خطوط 15 تا 28 اجرا می کند. پردازنده بعد از وقفه به همان خطی که از آن پرش کرده بود بر می گردد. یعنی انتهای تابع idle. (این تابع در آخرین خط خود کلاک cpu را غیر فعال می کند). چون دستوری بعد از این تایع نیست حلقه while دوباره تکرار می شود و دوباره تابع idle فراخوانی می شود و cpu از کار می افتد تا وقفه بعدی تایمر و به همین ترتیب روال کار ادامه می یابد. دقت کنید اگر می خواهید از مد های دیگر وقفه که کلاک های واحد های بیشتری را غیر فعال می کند استفاده کنید، قبلش حتما سری به دیتاشیت میکرو بزنید. در بعضی حالت ها فقط وقفه های خارجی یا وقفه واحد twi قادر به بیدار کردن cpu هستند.

بر می گردیم به تایمر. برای تولید فرکانس 1 هرتز در خروجی، باید هر 500 میلی ثانیه یک بار خروجی را معکوس کنیم. اما تایمر صفر 8 بیتی بوده و کلاک آن را 31.250 کیلو هرتز انتخاب کرده ایم. یعنی اگر تایمر از صفر تا حداکثر مقدار خود بشمارد، بیشتر از 8.1 میلی ثانیه طول نمی کشد. به عبارت دیگر تایمر در 500 میلی ثانیه 61 بار از اول تا آخر شمرده است. برای رفع این مشکل یک متغییر به نام  i تعریف می کنیم. هر بار که تایمر تا آخر شمرد و وقفه روی داد مقدارش را یکی زیاد می کنیم. تا اینکه 61 بار بشمارد در این هنگام 499.712 میلی ثانیه گذشته است. پس دیگر نباید تایمر تا آخر بشمارد. پس مقدار 9 را به رجیستر ocr0 می ریزیم. وقتی تایمر به این مقدار رسید  و وقفه روی داد، دقیقا 500 میلی ثانیه گذشته است (با خطای 2 یا 3 کلاک پردازنده نه تایمر). حال خروجی را معکوس می کنیم و تایمر را برای 500 میلی ثانیه بعدی آماده می کنیم. به این ترتیب یک فرکانس 1 هرتز با تقریب خیلی خوب در پین صفر پورت B  به دست می آوریم. البته این مثال صرفا جهت آشنایی با تایمر آورده شده و خیلی راحت تر از این می توان با تایمر ها کار کرد.

/*****************************************************
Chip type               : ATmega32
AVR Core Clock frequency: 8.000000 MHz
Memory model            : Small
External RAM size       : 0
Data Stack size         : 512
*****************************************************/

#include <mega32.h>
#include <sleep.h>

int i=0;

// Timer 0 output compare interrupt service routine
interrupt [TIM0_COMP] void timer0_comp_isr(void)
{
   i++;
   if(i==61)             
   {
      OCR0=0x09;                 
   }
   if(i==62)
   {
      PORTB.0 = ~PORTB.0;       //toggel pin 0 state.
      OCR0=0xFF;
      i=0;
   }
}

void main(void)
{

PORTB=0x00;     //set value of pin(0) to 0.
DDRB=0x01;      //pin(0)(led number D9) defined for output.

TCCR0=0x0C;     //initiate timer(0) for 31.250kHz clock frecuncy and CTC mode.
TCNT0=0x00;     //set timer(0) value register to 0x00.
OCR0=0xFF;      //set compare register to 0xFF.

TIMSK=0x02;     //enable timer(0) comper match interrupt. 

#asm("sei")     //enable  Golobal interrupts
sleep_enable();         //initiate sleep in power management unit.

while (1)
      {
        idle();     //disable cpu clock (first sleep mode).
      }
}

دانلود سورس کد

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

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

این مطلب را به اشتراک بگذارید:

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