مود های تایمر / کانتر در میکروکنترلر AVR
محتویات
- مد های مختلف Timer / Counter در میکروکنترلر AVR
- انواع مود های تایمر کانتر در AVR
- Normal Mode = مود معمولی چیست؟
- CTC Mode = مود CTC چیست ؟
- رجیستر در تایمر کانتر 0 میکروکنترلر AVR
- رجیستر در تایمر کانتر 1 میکروکنترلر AVR
- رجیستر در تایمر کانتر 2 میکروکنترلر AVR
- آموزش کار با مود CTC در تایمر کانتر 1
- مثال اول برای فهمیدن مد CTC در تایمر کانتر یک
- مثال دوم برای فهمیدن مود CTC در تایمر کانتر 1
- آموزش کامل سخت افزار CTC
سلام. آموزش مود های مختلف تایمر کانتر (مد CTC) در میکروکنترلر های AVR را آماده کردیم.
مد های مختلف Timer / Counter در میکروکنترلر AVR
در این قسمت از سری آموزش های AVR ما به طور کامل با مد های مختلف تایمر / کانتر در میکروکنترلر های AVR آشنا میشویم. مهم ترین مد برای ما مود CTC خواهد بود.
حتما حتما حتما قبل از خواندن این قسمت از آموزش AVR ، قسمت قبلی را بخوانید :
خب تا اینجا ما به طور کامل متوجه شدیم که تایمر کانتر چیست و چه میکند. از این به بعد مبحث timer / counter ها را حرفه ای تر ادامه میدهیم. برای استفاده بهتر و بهینه تر از تایمر و کانتر ها شرکت اتمل مد های متفاوتی را تعریف کرده است.
انواع مود های تایمر کانتر در AVR
- Normal Mode = مود معمولی
- CTC Mode = مود CTC
- Fast PWM Mode = مود PWM سریع
- Phase Correct PWM Mode = مود PWM فاز صحیح
- Phase And Frequency Correct PWM Mode > فقط در بعضی از میکروکنترلر های AVR
در ابتدا نگاهی گذرا به حالت Normal میاندازیم. اما در این آموزش بیشتر با مود CTC آشنا میشویم.
Normal Mode = مود معمولی چیست؟
این مود همان مدی است که تا کنون با ان کار کرده ایم. در مود معمولی تایمر کانتر از صفر شروع میکند و تا مقدار ماکزیموم خود میشمارد و سپس 0 میشود و تکرار این داستان. از این مود تایمر کانتر برای عملیات های ساده استفاده میشود.
CTC Mode = مود CTC چیست ؟
CTC مخفیف Clear Timer On Compare Match میباشد که به معنی “پاک کردن تایمر در هنگام مچ شدن عمل مقایسه” است. یعنی هر وقت مقدار تایمر (TCNT0) با یک مقدار دیگر (OCR0) برابر شد، مقدار تایمر/کانتر 0 میشود. به عبارت دیگر، مقدار ماکزیمم ما در اینجا FF نیست. بلکه مقدار ماکزیمم مثل شکل زیر OCR0 میباشد.
در قسمتهای قبلی آموزش،عمل مقایسه رو بصورت نرم افزاری انجام میدادیم. یعنی با فرمول، مقدار TimerCount را حساب میکردیم و در برنامه شرط میگذاشتیم که هر وقت مقدار رجیستر TCNTx برابر با مقدار TimerCount شد، یک کاری انجام شود.
اما استفاده از اینگونه شروطی که دائما CPU را درگیر خود میکند برای همیشه مناسب نیست. با استفاده از مود CTC، عمل مقایسه بصورت سخت افزاری انجام میشود و در نتیجه احتمال خطا کمتر میشود و بار مقایسه نرم افزاری از روی دوش CPU برداشته میشود.
تصویر زیر را ببینید :
در اینجا هم میبینید که مقدار ماکزیمم ، هر مقداری میتواند باشد و در سیکلهای متفاوت مقدارهای متفاوتی را اختیار میکند. حالا به تصویر زیر دقت کنید.
این تصویر مربوط به تایمر کانتر 0 است. ببینید در ردیف شکل ردیف اول یک موج دندان اره ای داریم که از 0 شروع میشود و تا 255 میشمارد. بعد از آن مجددا صفر میشود و تکرار داستان.
یک خط چین افقی وجود دارد که همان مقدار مقایسه ای ما است یعنی OCR0A که برای مثال مقدار آن 250 در نظر گرفته شده است. توجه داشته باشید که نمودار اول، توسط میکروکنترلر ساخته نمیشود و کاملا نمایشی است برای درک مسئله ! تایمر شروع به شمردن از 0 میکند و به مقدار OCR0 میرسد.
هنگامی که تایمر به OCR0 برسد یعنی همان مقدار ماکزیمم ، Microcontroller مطلع میشود که مقادیر با هم برابر شده اند. در شکل بالا که یک مثال است ، با برابر ششدن مقدار دو رجیستر TCNT0 و OCR0،پایه OC0 میکرو فعال / غیر فعال میشود. اما ما میتوانیم حالتهای مختلفی برای پایه OCx انتخاب کنیم.
رجیستر در تایمر کانتر 0 میکروکنترلر AVR
در اینجا رجیستر های مربوط به timer counter صفر را بررسی میکنیم.
بررسی رجیستر OCR0 : Output Compare Register
مقدار ماکزیمم مورد نظر خود را در این رجیستر قرار میدهیم. دقت داشته باشید که تایمر کانتر صفر ، یک تایمر کانتر 8 بیت است تنها میتواند مقداری بین 0 تا 255 را استفاده کنیم.
بررسی رجیستر TCCR0 : Timer/Counter Control Register
بیت های 3 و 6 ؛ Bit 6 , 3 – Wave Generation Mode Bits : با استفاده از این 2 بیت و جدول پایین میتوانیم مود کاری تایمر کانتر 0 را مشخص کنیم.
که در اینجا ردیف سوم جدول بالا مد نظر ماست و مقدار WGM0:1 برابر با 10 در نظر گرفته خواهد شد.
بیت های 4 و 5 ؛ Bit 5 , 4 – Compare Match Output Mode :
مشخصا در میکروکنترلر ATmega32 پایه ای داریم به نام OC0 . به جدول زیر نگاه کنید :
این جدول میگوید با برابر شدن مقدار تایمر / کانتر 0 با مقدار رجیستر OCR0 ، در پایه OC0 میکروکنترلر فعالیتی انجام شود.
- حالت 00 : غیر فعال بودن OC0 یعنی پایه OC0 در حالت عادی به کار خود ادامه خواهد داد.
- حالت 01 : به محض برابر شدن، وضعیت پایه OC0 میکروکنترلر Toggle خواهد شد یعنی اگر 1 منطقی روی پایه هست 0 میشود و اگه 0 هست 1 میشود !
- حالت 10 : به محض برابر شدن، وضعیت پایه OC0 میکرو Clear خواهد شد. یعنی وقتی برابری اتفاق بیافتد وضعیت پایه OC0 صفر خواهد شد.
- حالت 11 : به محض برابر شدن، وضعیت پایه OC0 میکرو Set خواهد شد یعنی وقتی برابریاتفاق افتاد وضعیت پایه OC0 یک خواهد شد.
بررسی رجیستر TIMSK : Timer/Counter Interrupt Mask Register
بیت 1 ؛ Bit 1 – OCIE0: Timer/Counter0 Output Compare Match Interrupt Enable :
با یک کردن این بیت، میتوانید وقفه برابری مقدار تایمر/کانتر صفر و مقدار رجیستر OCR0 را فعال کنید.
بررسی رجیستر TIFR : Timer/Counter Interrupt Flag Register – TIFR
بیت 1 ؛ Bit 1 – OCF0: Output Compare Flag 0 :
هنگامی که مقدار تایمر / کانتر 0 و رجیستر OCR0 با همدیگر برابر شود این فلگ 1 میشود. OCF0 پس از انجام وقفه و اجرا شدن دستور زیر روال وقفه به صورت سخت افزاری و اتوماتیک 0 خواهد شد.
همچنین با نوشتن 1 بر روی این فلگ، میتوانیم به صورت دستی آن را 0 کنیم. دقت داشته باشید که با فعال بودن بیت وقفه سراسری (I) از رجیستر SREG ( با دستور اسمبلی “sei” در محیط کدویژن ) و همچنین بیت OCIE0 از رجیستر TIMSK و فعال شدن همین بیت، وقفه اجرا خواهد شد.
رجیستر در تایمر کانتر 1 میکروکنترلر AVR
در اینجا رجیستر های مربوط به timer counter یک را بررسی میکنیم.
رجیسترهای OCR1A , OCR1B :
Output Compare Register 1 A – OCR1AH and OCR1AL و Output Compare Register 1 B – OCR1BH and OCR1BL
این دو رجیستر از نوع 16 بیتی هستند و میتوانند عددی بین 0-65535 را در خود قرار دهند. گفتیم که این مقایسه به صورت سخت افزاری انجام میشود. اگر یادتان باشد عددی بدست آوردیم که مقدارش 24999 بود. حالا این عدد را در یکی از این دو رجیستر قرار میدهیم. در واقع کمپانی اتمل برای این بخش 2 تا Compare Register تعریف کرده است تا قادر باشیم مقدار تایمر/کانتر یک را همزمان با دو مقدار (OCR1A , OCR1B) مقایسه کنیم. این دو رجیستر تفاوتی با هم ندارند.
رجیستر TCCR1A : Timer/Counter1 Control Register A – TCCR1A
بیت های 0 و 1؛ Bit 1:0 – Wave Generation Mode Bits :
با این دو بیت و بیتهای WGM12:13 از رجیستر TCCR1B میتوانیم مد کاری Timer / Counter 1 را مشخص کنیم.
بیت های 4 و 5 و 6 و 7 ؛ Bit 4:7 – Wave Generation Mode Bits :
برای تایمر / کانتر یک هم مشخصا پایه هایی با نام های OC1A و OC1B وجود دارد. جدول زیر را ببینید :
بررسی رجیستر TCCR1B : Timer/Counter1 Control Register B – TCCR1B
بیت های 3 و 4؛ Bit 4:3 – Wave Generation Mode Bits :
از این رجیستر هم با دو بیت WGM12,WGM13 سر و کار داریم. این چهار بیت (WGM10,WGM11,WGM12,WGM13) از دو رجیستر TCCR1A و TCCR1B در کنار هم میتوانند مود کاری تایمر/کانتر را تعیین کنند.
مود شماره 4 و 12 جدول بالا مدنظر ماست. ما مود 4 رو انتخاب میکنیم که مقدار متناظر آن برای 4 فلگ WGM10:13 برابر 0100 خواهد بود.
رجیستر TIMSK : Timer/Counter Interrupt Mask Register
بیت 3 و 4 ؛ Bit 3:4 – OCIE1A:B: Timer/Counter1, Output Compare A:B Match Interrupt Enable :
با یک کردن هر یک از دو بیت بالا میشود وقفه های برابری مقدار timer / counter 1 با رجیستر های OCR1A و OCR1B را فعال کرد.
بررسی رجیستر TIFR : Timer/Counter Interrupt Flag Register – TIFR
بیت 3 و 4 : Bit 4:3 – OCF1A:B – Timer/Counter1, Output Compare A/B Match Flag Bit :
هرگاه مقدار رجیستر TCNT1 با مقدار رجستر OCR1A (یا OCR1B) برابر باشد، مقدار فلگ OCF1A (یا OCF1B) یک خواهد شد. این فلگ پس از اجرا شدن روتین وقفه بصورت اتوماتیک 0 خواهد شد. در صورت عدم استفاده از وقفه با نوشتن 1 بر روی این فلگ میتوانید مقدار آن را به 0 برگردانید. فعال بودن فلگ وقفه سراسری از رجیستر SREG و همچنین فعال بودن بیت OCIE1A (یا OCIE1B) و فعال شدن فلگ OCF1A (یا OCF1B) وقفه رخ خواهد داد.
رجیستر در تایمر کانتر 2 میکروکنترلر AVR
در اینجا رجیستر های مربوط به timer counter دو را بررسی میکنیم.
رجیستر OCR2 : Output Compare Register
مقدار مورد نظر برای مقایسه در این رجیستر قرار میگیرد.
رجیستر TCCR2 : Timer/Counter Control Register
بیت های 3 و 6 ؛ Bit 6, 3 – WGM21:0: Waveform Generation Mode :
از این دو بیت برای تعیین مود کاری تایمر/کانتر دو استفاده میشود. جدول زیر را ببینید :
بیت های 4 و 5 ؛ Bit 5:4 – COM21:0: Compare Match Output Mode :
با این بیتها هم میشود مثل قبل وضعیت پایه OC2 را مشخص کرد. طبق جدول زیر :
رجیستر TIMSK : Timer/Counter Interrupt Mask Register
بیت 7 ؛ Bit 7 – OCIE2: Timer/Counter2 Output Compare Match Interrupt Enable :
با یک کردن این بیت،وقفه تایمر/کانتر دو فعال میشود.
رجیستر TIFR : Timer/Counter Interrupt Flag Register – TIFR
بیت 7 ؛ Bit 7 – OCF2: Output Compare Flag 2 :
اگر مقدار تایمر/کانتر دو با مقدار رجیستر OCR2 برابر شود، این بیت 1 میشود.
سلام. آموزش کامل برنامه نویسی تایمر / کانتر یک در مود CTC (آموزش AVR #18) را آماده کردیم.
آموزش کار با مود CTC در تایمر کانتر 1
در این قسمت از سری آموزش های AVR ، به طور کامل با نحوه کار با مود CTC و برنامه نویسی آن در Timer / Counter 1 آشنا میشویم. در قسمت قبلی ، ما با مد های مختلف تایمر / کانتر در میکروکنترلر های AVR آشنا شدیم. حتما قبل از خواندن این قسمت از آموزش ، قسمت قبل را بخوانید.
این آموزش را نیز با تعریف یک مسئله شروع میکنیم.
مثال اول برای فهمیدن مد CTC در تایمر کانتر یک
به طور مثال ما میخواهیم یک فلاشر ال ای دی بسازیم که هر 100 میلی ثانیه چشمک بزند. ما از Timer / Counter 1 و مد CTC استفاده میکنیم. میدانیم که تایمر کانتر یک نهایتا میتواند تا 65535 میتونه بشمارد. با انتخاب ضریب تقسیم 64 ، فرکانس تایمر/کانتر به 250 کیلوهرتز کاهش پیدا میکند و برای ایجاد تاخیر 100 میلی ثانیه ای ، مقدار TimerCount برابر 24999 میشود.
چند تا رجیستر هم داریم که قبلا با اکثرشان آشنا شدید و اینجا با فلگ های جدیدتری از آن ها آشنا میشویم.
ابتدا مثل همیشه کتابخانه میکروکنترلر Atmega 32 را فراخوانی میکنیم.
#include <mega32.h> void timer1_configuration (void){}
تابعی با نام timer1_configuration تعریف میکنیم و تنظیمات مربوط به پیکربندی تایمر/کانتر یک را در آن انجام میدهیم.
#include <mega32.h> void timer1_configuration (void){ TCCR1A = 0x00; //WGM10 = 0 , WGM11 = 0 TCCR1B = (1 << WGM12)|(1 << CS11)|(1 << CS10); TCNT1 = 0; OCR1A = 24999; }
مقدار ضریب تقسیم 64 در نظر گرفته شده و مقادیر فلگ های CS10 و CS11 از رجیستر TCCR1B جهت استفاده در مد CTC و با توجه به جدول زیر یک شده اند.
تا اینجای کار تایمر/کانتر در مود CTC برنامه ریزی شد. مقدار رجیستر OCR1A هم با توجه به محاسبات انجام شده در ابتدای پست 24999 تعیین شد.
تابع اصلی یعنی تابع main :
void main(){
DDRC |=(1 << 0);
timer1_configuration();
while(1){
if (TIFR & (1 << OCF1A)){
PORTC ^=(1 << 0);
}
TIFR |=(1 << OCF1A);
}
}
پین 0 از پورت C بعنوان خروجی در نظر گرفته میشود و به LED مربوطه وصل میشود. در خط بعدی تابع timer1_configuration فراخوانی میشود که حاوی تنظیمات تایمر/کانتر شماره یک است. پس از آن یه حلقه بی نهایت داریم که در آن یک شرط مینویسیم.
یک شرط گذاشتیم که هر وقت فلگ OCF1A از رجیستر TIFR یک شود، پین 0 از پورت C فعال / غیرفعال شود.
فلگ OCF1A وظیفه اش این بود که هروقت مقدار تایمر/کانتر یک، با مقدار مشخص شده در رجیستر OCR1A برابر شد یک شود. و از یک شدن این فلگ متوجه میشیم که سرریز رخ داده و عمل برابر شدن اتفاق افتاده است.
پس از اینکه فلگ OCF1A یک شد،باید بصورت دستی آن را 0 کنیم.
مثال دوم برای فهمیدن مود CTC در تایمر کانتر 1
میتوانیم همین برنامه را حرفه ای بنویسیم در آن از اینتراپت (وقفه) استفاده کنیم.
اول از همه شروع میکنیم به پیکربندی تایمر/کانتر یک با استفاده از ویژگی وقفه !
بار دیگر تابع timer1_configuration را بازنویسی میکنیم و تغییرات مورد نیاز را اعمال میکنیم.
void timer1_configuration (void){
TCCR1A = 0x00; //WGM10 = 0 , WGM11 = 0
TCCR1B = (1 << WGM12)|(1 << CS11)|(1 << CS10); //Mode = CTC , Prescaler = 64
TCNT1 = 0; //initialize timer/counter 1
OCR1A = 24999; //initialize compare value
TIMSK |=(1<<OCIE1A); //Enable Compare Interrupt
#asm("sei") //Enable Global Interrupt
}
فلگ OCIE1A از رجیستر TIMSK را یک میکنیم تا وقفه مقایسه ای تایمر/کانتر یک فعال بشود. در انتها هم فلگ I از رجیستر SREG را فعال میکنیم.
حالا نوبت به نوشتن زیرروال وقفه میرسد :
interrupt [8] void compare_interrupt (void){ PORTC ^=(1 << 0); }
تابع اینتراپت را نوشتیم با Vector Number معادل 8 که همان بردار Timer/Counter1 Compare Match A است. یک اسم هم گذاشتیم برای تابع وقفه ؛ compare_interrupt که ورودی هم نداره (void). در زیرروال وقفه هم دستور Toggle شدن PORTC.0 میکروکنترلر را نوشتیم.
نوبت میرسه به تابع main :
void main (void){ DDRC |= (1<<0); timer1_configuration (); while(1){} }
ابتدا پایه 0 از پورت C را بعنوان خروجی تعریف میکنیم. در خط بعدی تابع timer1_configuration را فراخوانی میکنیم تا تایمر/کانتر یک تنظیم بشود. و در انتها یه حلقه بینهایت تعریف کردیم که داخلش هم هیچی ننوشتیم چون نیازی نیست.
تمام کاری که میخوایم انجام بدیم داخل زیرروال وقفه انجام میشود. بنابراین تنها دلیل ما برای نوشتن این حلقه بینهایت اینه که برنامه تمام نشود و از داخل تابع main بیرون نیاید و برنامه به کار خودش ادامه بدهد.
آموزش کامل سخت افزار CTC
به تصویر زیر که دیتاشیت میکروکنترلر ات مگا 32 است دقت کنید.
4 تا از پایه ها یعنی PB3 , PD4 , PD5 , PD7 داخل پرانتزهاشون به ترتیب نوشته شده است : OC0 , OC1B , OC1A , OC2
این پایه ها به پایه های مقایسه گر خروجی یا Output Compare Pins معروف هستند که به تایمر/کانتر 0 ، 1 و 2 مربوط میشوند.
رجیستری داشتیم به نام TCCR1A که قبلا معرفیش کردیم :
رجیستر TCCR1A : Timer/Counter1 Control Register A – TCCR1A
بیت های 6 و 7 ؛ COM1A1 و COM1A0 :
این بیت ها وظیفه کنترل پایه های OC را بر عهده دارند.
بطور کلی این بیتها برای مود های کاری مختلف، بصورت جداگانه بحث میشوند که در اینجا مد CTC مدنظر ماست. جدول زیر را ببینید :
در اینجا چون خاموش/روشن کردن LED مدنظر ماست از ردیف دوم جدول بالا یعنی حالت 01 استفاده میکنیم. البته دقت داشته باشید که ما اینجا از تایمر/کانتر یک داریم استفاده میکنیم و به همین دلیل هم رفتیم سراغ رجیستر TCCR1A. و اگر میخواستیم از تایمر/کانتر صفر یا دو استفاده کنیم قطعا باید به رجیستر های مربوط به خودشون مراجعه میکردیم.
کد کامل :
#include <mega32.h> void timer1_configuration (void){ TCCR1A = (1<<COM1A0); //WGM10 = 0 , WGM11 = 0 , Set OC1A In CTC Toggle Mode TCCR1B = (1 << WGM12)|(1 << CS11)|(1 << CS10); //Mode = CTC , Prescaler = 64 TCNT1 = 0; //initialize timer/counter 1 OCR1A = 24999; //initialize compare value } void main (void) { DDRC |=(1<<0); timer1_configuration (); while(1) { } }
مقدار COM1A0 را 1 کردیم و در نتیجه حالت روشن / خاموش شدن را برای پایهی OC1A فعال کردیم.
یعنی هربار که تایمر/کانتر 1 سرریز شود، با توجه به تنظیماتی که ما برایش انجام دادیم، مقدار پایهی PD5 شروع به روشن و خاموش شدن میکند.
این قسمت آموزش AVR هم تمام شد. در قسمت بعدی به طور کامل با برنامه نویسی ال سی دی کاراکتری در میروکنترلر AVR در محیط کدویژن آشنا میشویم.
قسمت بعد : توابع برنامه نویسی ال سی دی کاراکتری در کدویژن
سلام واقعا خوب بود! دمتون گرم!!
سلام عزیز
خوشحالم که براتون مفید واقع شده
سلام، ببخشید آقای رحیمی میشه بفرماید کتاب مرجع این سری از آموزش ها اسمش چیه؟
سلام جناب. سری آموزش های AVR کتابی نداره از سایت ها جمع آوری شده.