در کل سه تایمر/کانتر به نامهای "تایمرصفر ، تایمریک و تیامردو " داریم که صفر و یک هشت بیتی هستند و تایمریک ۱۶ بیتی.
رجیسترهایی که باید بشناسید
TCNTn: Timer / Counter Register
این رجیستر با هر بار کلاک یک عدد به مقدارش اضافه میشه درکل کار شمارنده رو انجام میده. مقدار اولیه اش صفره و قابلیت نوشتن و خوندن ازش رو داریم.
TOVn: Timer Overflow Flag
هر تایمر فلگ سرریز داره که وقتی تایمر سرریز میکنه ،یا وقتی شمارنده به تهش میرسه ، این فلگ ست میشه.
TCCRn : Timer Counter Control Register
این رجیستر برای تنظیم حالت های تایمر/کانتر استفاده میشه.
OCRn : Output Compare Register
مقدار داخل این رجیستر با شمارنده مقایسه میشه وقتی برابر باشند فلگ OCFn ست میشه.
در ادامه تایمر صفر رو بررسی میکنیم. اول باید رجیستر های اساسی تایمر صفر رو درک کنیم.
TCNT0: Timer / Counter Register 0
یک رجیستر هشت بیتی که با هرپالس یکی بهش اضافه میشه.که بهش شمارنده میگیم.
TCCR0: Timer / Counter Control register 0
یک رجیستر هشت بیتی برای تنظیم حالت و منبع کلاک
Bit 7- FOC0: Force compare match
بیت هفتم ، تنها بیتی که هنگام تولید موج استفاده میشود، را مینویسد. نوشتن یک در این بیت باعث میشود که تولید کننده موج مانند زمانی عمل کند که مقایسه انجام شده.
Bit 6, 3 - WGM00, WGM01: Waveform Generation Mode
حالتهای عملکرد تایمر با بیت سوم و ششم این رجیستر طبق جدول بالا مشخص میشوند.
Bit 5:4 - COM01:00: Compare Output Mode
این دو بیت تعیین کننده حالت تولیدکننده شکلموج هستند.
Bit 2:0 - CS02:CS00: Clock Source Select
این سه بیت برای انتخاب منبع کلاک استفاده میشوند. وقتی مقدار سه بیت صفر باشد تایمر متوقف میشود.
ولی بعد از ست کردن مقدار بین ۲ تا ۵ باینری با pre-scaler شروع به تولید کلاک میکنه و شمارنده عددش رو اضافه میکنه در هر سیکل.
خب تصویر بالا نیاز به توضیح نداره از مقدار ۲ باینری تا ۵ باینری کلاک رو تقسیم بر عدد سمت راستش میکنه.
TIFR: Timer Counter Interrupt Flag register
رجیستر فلگ وقفه تایمر/کانتر
Bit 0 - TOV0: Timer0 Overflow flag
بیت صفر فلگ سرریز تایمر صفر. صفر بودن این بیت یعنی سرریز نشده و یک بودن یعنی سرریز شده.
Bit 1 - OCF0: Timer0 Output Compare flag
فلگ خروجی مقایسه : وقتی مقدار شمارنده و مقایسه شونده برابر شوند این بیت یک در غیر اینصورت صفر میشود.
بقیه بیت ها هم به صورت زیر هستند.
Bit 2 - TOV1: Timer1 Overflow flag
Bit 3 - OCF1B: Timer1 Output Compare B match flag
Bit 4 - OCF1A: Timer1 Output Compare A match flag
Bit 5 - ICF1: Input Capture flag
Bit 6 - TOV2: Timer2 Overflow flag
Bit 7 - OCF2: Timer2 Output Compare match flag
درحالت نرمال : وقتی شمارنده سرریز میشود، یعنی مثلا از صفر به ۲۵۵ میرود، فلگ TOV0 ست میشود.توجه کنید که مقدار شمارنده بصورت خودکار صفر نمیشود و باید بصورت دستی این کار را انجام دهیم.
ساخت تاخیر با اسفاده از تایمر صفر
مراحل برنامه نویسی :
برنامهی وقته با تایمر
#include <avr/io.h> void T0delay(); int main(void){ DDRB = 0xFF; /* PORTB as output*/ while(1){ /* Repeat forever*/ PORTB=0x55; T0delay(); /* Give some delay */ PORTB=0xAA; T0delay(); } } void T0delay() { TCNT0 = 0x25; /* Load TCNT0*/ TCCR0 = 0x01; /* Timer0, normal mode, no pre-scalar */ while((TIFR&0x01)==0); /* Wait for TOV0 to roll over */ TCCR0 = 0; TIFR = 0x1; /* Clear TOV0 flag*/ }
مثال
یک شکل موج مربعی با طول ۱۰ میلی ثانیه بالا و ۱۰ میلی ثانیه پایین تولید کنیم.
اول باید یک وقفه ۱۰ میلی ثانیهای با تایمر صفر تولید کنیم.
فرض که میکرو رو روی فرکانس ۸ مگاهرتز تنظیم کردیم.
با استفاده از pre-scaler اه ۱۰۲۴ ، فرکانس منبع کلاک میشود :
8 MHz / 1024 = 7812.5 Hz
زمان هر سیکل :
1 / 7812.5 = 128 μs
بنابراین برای وقفه ۱۰ میلیثانیهای تعداد سیکلهای مورد نیاز تقریبا 78 میشه
10 ms / 128 μs = 78
پس ما به ۷۸ سیکل نیاز داریم تا وقفه ۱۰ میلیثانیهای بسازیم. پس مقداری که باید توی TCNT0 بزاریم میشه 178 :
TCNT0 = 256 – 78
یعنی شمارنده از ۱۷۸ شروع میکنه به شمردن و ۷۸ تا سیکل میشماره تا سرریز کنه.
پس ما اگه مقدار 0xB2 رو داخل رجیستر TCNT0 بزاریم ، تایمر بعد از ۱۰ میلی ثانیه سرریز میکنه.
برنامه وقفه ۱۰ میلیثانیهای با تایمر صفر
#include <avr/io.h> void T0delay(); int main(void) { DDRB = 0xFF; /* PORTB as output */ PORTB=0; while(1) /* Repeat forever */ { PORTB= ~ PORTB; T0delay(); } } void T0delay() { TCCR0 = (1<<CS02) | (1<<CS00); /* Timer0, normal mode, /1024 prescalar */ TCNT0 = 0xB2; /* Load TCNT0, count for 10ms */ while((TIFR&0x01)==0); /* Wait for TOV0 to roll over */ TCCR0 = 0; TIFR = 0x1; /* Clear TOV0 flag */ }
وقفه تایمر
TIMSK: Timer / Counter Interrupt Mask Register
ما باید بیت TOIE0 (Timer0 Overflow Interrupt Enable) رو در رجیستر TIMSK ست کنیم تا وققهی تایمر صفر فعال بشه. بعد از فعال شدن ، به محض سرریز تایمرصفر ، کنترلر به روتین وقفه تایمر صفر پرش میکنه.
برنامه وقفه یک میلیثانیهای با تایمر صفر
#include <avr/io.h> #include <avr/interrupt.h> /* timer0 overflow interrupt */ ISR(TIMER0_OVF_vect) { PORTB=~PORTB; /* Toggle PORTB */ TCNT0 = 0xB2; } int main( void ) { DDRB=0xFF; /* Make port B as output */ sei(); TIMSK=(1<<TOIE0); /* Enable Timer0 overflow interrupts */ TCNT0 = 0xB2; /* Load TCNT0, count for 10ms*/ TCCR0 = (1<<CS02) | (1<<CS00); /* Start timer0 with /1024 prescaler*/ while(1); }
منبع :