تایمر/کانترها (Timer/Counters) یکی از حیاتیترین ماژولها در میکروکنترلرهای AVR هستند که امکان انجام طیف وسیعی از وظایف زمانبندی و شمارش را فراهم میکنند. درک نحوه عملکرد و پیکربندی آنها برای هر توسعهدهندهای که با AVR کار میکند، ضروری است. این مقاله به بررسی مبانی تایمر/کانترها، حالتهای عملکرد اصلی و نحوه استفاده از آنها میپردازد.
چرا تایمر/کانترها مهم هستند؟
تایمر/کانترها به میکروکنترلر اجازه میدهند تا بدون نیاز به درگیر کردن CPU در حلقههای تاخیر نرمافزاری، وظایف زمانبندی شده را انجام دهد. کاربردهای اصلی آنها عبارتند از:
اجزای اصلی یک تایمر/کانتر
هر تایمر/کانتر در AVR از چندین جزء کلیدی تشکیل شده است:
1. منبع کلاک (Clock Source): تایمر برای شمارش به یک منبع کلاک نیاز دارد. این منبع میتواند کلاک سیستم (CPU Clock) باشد که از طریق یک پیشتقسیمکننده (Prescaler) عبور میکند، یا یک منبع کلاک خارجی که به پایه Tnx متصل میشود.
2. پیشتقسیمکننده (Prescaler): این ماژول فرکانس کلاک ورودی را به نسبتهای مشخصی (مثلاً 1، 8، 64، 256، 1024) تقسیم میکند. این کار باعث میشود تایمر بتواند دورههای زمانی طولانیتری را شمارش کند.
3. رجیستر شمارنده (TCNTn): این رجیستر قلب تایمر است. با هر پالس کلاک، مقدار آن افزایش مییابد. تایمرهای AVR معمولاً 8 بیتی (TCNT0, TCNT2) یا 16 بیتی (TCNT1) هستند.
4. رجیستر مقایسه خروجی (OCRnx): این رجیستر برای حالتهای خاصی مانند CTC و PWM استفاده میشود. وقتی مقدار TCNTn با OCRnx برابر شود، یک رویداد (مانند تولید وقفه یا تغییر وضعیت پین خروجی) رخ میدهد.
حالتهای عملکرد اصلی تایمر/کانترها
تایمر/کانترهای AVR میتوانند در چندین حالت مختلف کار کنند. در اینجا به دو حالت پرکاربرد میپردازیم:
1. حالت عادی (Normal Mode):
* در این حالت، TCNTn به طور پیوسته از 0 تا حداکثر مقدار خود (0xFF برای 8 بیتی و 0xFFFF برای 16 بیتی) شمارش میکند.
* پس از رسیدن به حداکثر مقدار، سرریز (Overflow) رخ داده و TCNTn به 0 بازمیگردد و شمارش را از سر میگیرد.
* یک پرچم وقفه سرریز (TOVn) تنظیم میشود که میتواند باعث ایجاد وقفه شود.
* این حالت برای تولید تاخیرهای زمانی یا شمارش رویدادها استفاده میشود.
2. حالت CTC (Clear Timer on Compare Match):
* در این حالت، TCNTn از 0 شروع به شمارش میکند و تا زمانی که مقدار آن با رجیستر مقایسه خروجی (OCRnx) برابر شود، ادامه میدهد.
* هنگامی که TCNTn == OCRnx میشود، TCNTn به 0 ریست شده و شمارش را از سر میگیرد.
* یک پرچم وقفه مقایسه خروجی (OCFnx) تنظیم میشود که میتواند باعث ایجاد وقفه شود.
* این حالت برای تولید تاخیرهای دقیق و تولید فرکانسهای مشخص بسیار مفید است، زیرا میتوان دوره تناوب را با تنظیم OCRnx به دقت کنترل کرد.
رجیسترهای کلیدی برای پیکربندی تایمر
برای پیکربندی تایمرها، باید رجیسترهای کنترلی مربوطه را تنظیم کنید. برای مثال، برای Timer/Counter0 در ATmega328P:
مثال: تنظیم Timer0 در حالت CTC برای تولید وقفه هر 1 میلیثانیه
فرض کنید کلاک سیستم 16MHz است و میخواهیم هر 1 میلیثانیه یک وقفه داشته باشیم.
1. انتخاب پیشتقسیمکننده:
* فرکانس کلاک سیستم: 16,000,000 Hz
* دوره تناوب مورد نظر: 1 ms = 0.001 s
* تعداد تیکهای مورد نیاز:
* اگر Prescaler را 64 انتخاب کنیم:
* این مقدار (250) در محدوده 8 بیتی (0-255) قرار میگیرد. پس OCR0A را 249 تنظیم میکنیم (چون از 0 تا 249 شمارش میکند که 250 تیک است).
2. کد نمونه (با استفاده از C و avr-gcc):
نکات مهم:
با درک این مفاهیم پایه، میتوانید از تایمر/کانترهای AVR برای پیادهسازی طیف وسیعی از عملکردهای زمانبندی شده در پروژههای خود استفاده کنید.
چرا تایمر/کانترها مهم هستند؟
تایمر/کانترها به میکروکنترلر اجازه میدهند تا بدون نیاز به درگیر کردن CPU در حلقههای تاخیر نرمافزاری، وظایف زمانبندی شده را انجام دهد. کاربردهای اصلی آنها عبارتند از:
- تولید تاخیرهای دقیق (Delay Generation)
- اندازهگیری فرکانس و دوره تناوب (Frequency/Period Measurement)
- تولید سیگنال PWM (Pulse Width Modulation) برای کنترل موتورها، روشنایی LED و غیره
- شمارش رویدادهای خارجی (External Event Counting)
- زمانبندی سیستم عاملهای بلادرنگ (RTOS Tick)
اجزای اصلی یک تایمر/کانتر
هر تایمر/کانتر در AVR از چندین جزء کلیدی تشکیل شده است:
1. منبع کلاک (Clock Source): تایمر برای شمارش به یک منبع کلاک نیاز دارد. این منبع میتواند کلاک سیستم (CPU Clock) باشد که از طریق یک پیشتقسیمکننده (Prescaler) عبور میکند، یا یک منبع کلاک خارجی که به پایه Tnx متصل میشود.
2. پیشتقسیمکننده (Prescaler): این ماژول فرکانس کلاک ورودی را به نسبتهای مشخصی (مثلاً 1، 8، 64، 256، 1024) تقسیم میکند. این کار باعث میشود تایمر بتواند دورههای زمانی طولانیتری را شمارش کند.
3. رجیستر شمارنده (TCNTn): این رجیستر قلب تایمر است. با هر پالس کلاک، مقدار آن افزایش مییابد. تایمرهای AVR معمولاً 8 بیتی (TCNT0, TCNT2) یا 16 بیتی (TCNT1) هستند.
4. رجیستر مقایسه خروجی (OCRnx): این رجیستر برای حالتهای خاصی مانند CTC و PWM استفاده میشود. وقتی مقدار TCNTn با OCRnx برابر شود، یک رویداد (مانند تولید وقفه یا تغییر وضعیت پین خروجی) رخ میدهد.
حالتهای عملکرد اصلی تایمر/کانترها
تایمر/کانترهای AVR میتوانند در چندین حالت مختلف کار کنند. در اینجا به دو حالت پرکاربرد میپردازیم:
1. حالت عادی (Normal Mode):
* در این حالت، TCNTn به طور پیوسته از 0 تا حداکثر مقدار خود (0xFF برای 8 بیتی و 0xFFFF برای 16 بیتی) شمارش میکند.
* پس از رسیدن به حداکثر مقدار، سرریز (Overflow) رخ داده و TCNTn به 0 بازمیگردد و شمارش را از سر میگیرد.
* یک پرچم وقفه سرریز (TOVn) تنظیم میشود که میتواند باعث ایجاد وقفه شود.
* این حالت برای تولید تاخیرهای زمانی یا شمارش رویدادها استفاده میشود.
2. حالت CTC (Clear Timer on Compare Match):
* در این حالت، TCNTn از 0 شروع به شمارش میکند و تا زمانی که مقدار آن با رجیستر مقایسه خروجی (OCRnx) برابر شود، ادامه میدهد.
* هنگامی که TCNTn == OCRnx میشود، TCNTn به 0 ریست شده و شمارش را از سر میگیرد.
* یک پرچم وقفه مقایسه خروجی (OCFnx) تنظیم میشود که میتواند باعث ایجاد وقفه شود.
* این حالت برای تولید تاخیرهای دقیق و تولید فرکانسهای مشخص بسیار مفید است، زیرا میتوان دوره تناوب را با تنظیم OCRnx به دقت کنترل کرد.
رجیسترهای کلیدی برای پیکربندی تایمر
برای پیکربندی تایمرها، باید رجیسترهای کنترلی مربوطه را تنظیم کنید. برای مثال، برای Timer/Counter0 در ATmega328P:
- TCCR0A و TCCR0B (Timer/Counter Control Register): این رجیسترها برای انتخاب حالت عملکرد (Normal, CTC, PWM) و تنظیم پیشتقسیمکننده استفاده میشوند.
- TCNT0 (Timer/Counter Register): رجیستر شمارنده 8 بیتی.
- OCR0A و OCR0B (Output Compare Register): رجیسترهای مقایسه 8 بیتی.
- TIMSK0 (Timer/Counter Interrupt Mask Register): برای فعالسازی وقفههای سرریز (TOIE0) و مقایسه (OCIE0A, OCIE0B).
- TIFR0 (Timer/Counter Interrupt Flag Register): شامل پرچمهای وقفه (TOV0, OCF0A, OCF0B) که پس از وقوع رویداد تنظیم میشوند و باید به صورت نرمافزاری پاک شوند (با نوشتن 1 در بیت مربوطه).
مثال: تنظیم Timer0 در حالت CTC برای تولید وقفه هر 1 میلیثانیه
فرض کنید کلاک سیستم 16MHz است و میخواهیم هر 1 میلیثانیه یک وقفه داشته باشیم.
1. انتخاب پیشتقسیمکننده:
* فرکانس کلاک سیستم: 16,000,000 Hz
* دوره تناوب مورد نظر: 1 ms = 0.001 s
* تعداد تیکهای مورد نیاز:
(16,000,000 Hz / Prescaler) * 0.001 s* اگر Prescaler را 64 انتخاب کنیم:
(16,000,000 / 64) * 0.001 = 250* این مقدار (250) در محدوده 8 بیتی (0-255) قرار میگیرد. پس OCR0A را 249 تنظیم میکنیم (چون از 0 تا 249 شمارش میکند که 250 تیک است).
2. کد نمونه (با استفاده از C و avr-gcc):
C:
محتوای بلوک کدها در دسترس شما نیست. برای مشاهده بلوک کدها، وارد انجمن شوید یاثبت نام کنید
نکات مهم:
- انتخاب تایمر: AVRها معمولاً چندین تایمر دارند (Timer0, Timer1, Timer2). Timer0 و Timer2 8 بیتی هستند و Timer1 16 بیتی است که برای زمانبندیهای دقیقتر و طولانیتر مناسبتر است.
- رجیسترهای مشترک: برخی رجیسترها مانند SREG (Status Register) که شامل بیت I (Global Interrupt Enable) است، برای همه وقفهها مشترک هستند.
- پاک کردن پرچم وقفه: در بسیاری از AVRها، پرچمهای وقفه (مانند TOVn, OCFnx) به صورت خودکار با ورود به ISR پاک میشوند. اما در برخی موارد (مانند حالتهای خاص PWM) یا برای اطمینان بیشتر، ممکن است نیاز باشد به صورت نرمافزاری (با نوشتن 1 در بیت مربوطه) آنها را پاک کنید.
با درک این مفاهیم پایه، میتوانید از تایمر/کانترهای AVR برای پیادهسازی طیف وسیعی از عملکردهای زمانبندی شده در پروژههای خود استفاده کنید.