در دو قسمت قبل به صورت مفصل در مورد تایمر کانتر 0 و همچنین تایمر کانتر 1 صحبت کردیم. نحوه عملکرد این دو تایمر کانتر، مدهای کاری و چگونگی خروجی گرفتن از آنها را به صورت کامل همراه با مثال توضیح دادیم. همینطور تفاوتهای این دو تایمر کانتر با یکدیگر و مزیتهای هر کدام گفته شد. اما امروز در آخرین بخش از آموزش تایمر کانترها به چگونگی عملکرد تایمر کانتر 2 به خصوص در حالت RTC خواهیم پرداخت. همراه با رزدینو باشید.
نکته: چون تمرکز ما بیشتر بر روی حالت RTC تایمر کانتر 2 است و از طرف دیگر، عملکرد مدها و نحوه خروجی گرفتن این تایمر بسیار شبیه تایمر کانتر 0 است، قبل از مطالعه این قسمت، حتما بخش تایمر کانتر 0 را مطالعه کنید.
تذکر: اگر برایتان سوال پیش آمده که چرا بجای « تایمر کانتر 2 » از « تایمر 2 » استفاده میکنیم، علت این است که این تایمر فاقد پایه ورودی بوده و نمیتوان از یک کلاک خارجی به عنوان پالس استفاده کرد. به همین خاطر خاصیت Counter (کانتر یا شمارنده) را ندارد.
بررسی مختصر تایمر 2
اگر دو قسمت قبل را مطالعه کرده باشید، گفتیم که تایمر کانتر 0 یک تایمر 8 بیتی و تایمر کانتر 1 یک تایمر 16 بیتی است. تایمر کانتر 2 هم 8 بیتی بوده و شباهت بسیار زیادی با تایمر 0 دارد. اما دارای یک خصوصیت منحصر به فرد است که به آن حالت RTC یا Real Time Clock گویند. به طور کل تایمر 2 دارای خصوصیات زیر است.
- این تایمر یک تایمر 8 بیتی است. پس رجیسترهای آن تک بیتی هستند.
- دارای 4 مد عملکرد است که عبارتاند از Fast PWM ،CTC ،Normal و Correct PWM که کاملا مشابه مدهای تایمر کانتر 0 میباشد.
- خروجی این تایمر بر روی پایه OC2 اعمال شده و دقیقا عملکردی مشابه تایمر کانتر 0 دارد.
- بر خلاف تایمر کانتر 0 حالت Counter ندارد.
- مزیت تایمر 2 وجود حالت RTC برای ساخت یک زمانسنج واقعی است.
شکل زیر پایههایی که مربوط به سخت افزار تایمر 2 هستند را نشان میدهد.

در شکل فوق پایه OC2 عملکردی مشابه OC0 در تایمر کانتر 0 دارد. اما دو پایه TOSC1 و TOSC2 مربوط به حالت RTC هستند که کمی جلوتر در مورد آن صحبت میکنیم.
رجیسترها و مدهای عملکرد
مدهای عملکرد تایمر 2 مشابه تایمر کانتر 0 بوده و در 4 مد میتواند عمل کند.
- مد Normal: در این مد شمارش تایمر 2 (منظور رجیستر TCNT2) از 0 تا 255 است.
- مد CTC: در این مد شمارش TCNT2 از 0 تا رجیستر OCR2 است.
- مد Fast PWM: این مد جهت تولید سیگنال PWM بر روی پایه OC2 خواهد بود.
- مد Correct PWM: این مد هم بر روی پایه OC2 سیگنال PWM ایجاد میکند اما دقت بیشتری نسبت به مد Fast PWM دارد.
تذکر: عملکرد، نمودارها و جزئیات کامل تمام 4 مد بالا کاملا مشابه تایمر کانتر 0 است و میتوانید از این لینک آنها را مطالعه کنید.
از بحث مدها خارج شویم. تایمر 2 همانند دو تایمر قبلی از دو رجیستر مشترک به نامهای TIMSK و TIFR استفاده میکند که مربوط به وقفههای تایمر هستند. اما تایمر 2 دارای رجیسترهای منحصر به فرد TCCR2 ،OCR2 ،TCNT2 و یک رجیستر اضافی به نام ASSR است.
رجیستر Timer Interrupt Mask) TIMSK)
وقفههای هر سه تایمر 0، 1 و 2 توسط این رجیستر فعال میشوند. برای تایمر 2 درون این رجیستر دو بیت تعبیه شده که با 1 کردن هر کدام از آنها وقفه مربوطه فعال خواهد شد. البته فراموش نشود که بیت وقفه عمومی هم باید 1 گردد تا مجوز صدور وقفه در میکروکنترلر داده شود.

دو بیت آخر این رجیستر TOIE2 و OCIE2 هستند که :
- با 1 کردن TOIE2 در صورتی که سرریز یا overflow رخ دهد، میتوان ایجاد وقفه کرد.
- با 1 کردن OCIE2 در صورتی که کپچر رخ دهد، میتوان باعث رخ دادن وقفه شد.
مفهوم overflow و کپچر کمی جلوتر گفته میشوند؛ از این بابت نگران نباشید.
تذکر: اگر با وقفهها آشنایی ندارید قسمت هشتم آموزش مقدماتی avr را مطالعه کنید.
رجیستر Timer Interrupt Flag Register) TIFR)
اگر وقفهها در رجیستر TIMSK فعال شده باشند و بیت وقفه عمومی هم یک شده باشد، در صورت وقوع وقفه بیت متناظر با آن وقفه در این رجیستر 1 میشود. در این صورت CPU متوجه وقوع وقفه شده و به اجرای دستورات وقفه خواهد پرداخت. پس از اتمام انجام دستورات، بیت 1 شدهی این رجیستر به صورت اتوماتیک 0 میشود.

به عنوان مثال اگر وقفه سرریز یعنی TOIE2 در TIMSK یک شده باشد، در صورت وقوع وقفه بیت TOV2 در این رجیستر 1 شده و CPU به سرویس روتین مربوطه پرش میکند. سپس دستورات را انجام داده و به مکان قبلی باز میگردد. در آخر هم بیت TOV2 به صورت اتوماتیک 0 میشود.
نکته: چون 0 و 1 شدن بیتهای این رجیستر اکثرا توسط سختافزار انجام میشود، ما به عنوان برنامهنویس کاری با این رجیستر نداریم. اما چون به صورت پیشفرض بیتهای این رجیستر 1 است، اگر هر کدام از وقفهها را در TIMSK فعال کنیم، بلافاصله یک وقفه رخ میدهد. به همین خاطر میتوان با نوشتن 1 بر روی هر کدام از بیتهای این رجیستر، مقدار آن بیت را 0 کرد.
رجیستر Timer Counter Register 2) TCNT2)
این رجیستر قلب تایمر 2 است و وقتی میگوییم تایمر 2 شروع به شمارش میکند یعنی این رجیستر عمل شمارش را انجام میدهد.

مشخص است که این رجیستر 8 بیتی بوده و محدوده شمارش آن بین 0 تا 255 (0xFF) خواهد بود. یعنی در صورت روشن کردن تایمر و اعمال پالس به این رجیستر، مقدار آن با هر پالس یک واحد افزایش مییابد. اگر به عنوان مثال تایمر از 0 به ازای هر کلاک شمارش کند و به مقدار 255 برسد، در این صورت اگر یک کلاک دیگر اعمال شود تایمر دوباره 0 شده و به این حالت سرریز یا overflow گویند.
رجیستر Output Compare Register 2) OCR2)
این رجیستر به صورت سخت افزاری و به طور دائم با مقدار TCNT2 مقایسه میشود و در صورت برابری مقدار این دو رجیستر، کپچر رخ میدهد. به عبارتی اگر مثلا ما مقدار 165 را درون OCR2 بریزیم و مقدار TCNT2 هم به 165 برسد، در این صورت کپچر رخ میدهد.

وقتی کچر رخ میدهد دو اتفاق مهم را میتوان فعال کرد.
- اگر وقفه کپچر فعال باشد، با برابر شدن این دو رجیستر میتوان وقفه تولید کرد.
- اگر تایمر در یکی از مدهای PWM باشد، میتوان وضعیت پایه خروجی (OC2) را هنگام کپچر تغییر داد.
رجیستر Timer Counter Control Register 2) TCCR2)
توسط این رجیستر میتوان نوع مد، نحوه عملکرد و گرفتن خروجی از تایمر 2 را کنترل کرد. در واقع این رجیستر برای تعیین مشخصات و وضعیت تایمر 2 به کار میرود (مثل TCCR0 و TCCR1).

توضیح عملکرد بیتهای COM ،WGM و FOC مشابه تایمر کانتر 0 است و تنها تفاوت در بیتهای CS بوده که زیاد هم متفاوت نیست و تنها حالت Counter تایمر حذف شده است. به همین خاطر به جای آنها دو مورد Clk/32 و Clk/128 اضافه شده است.
در حالت پیشفرض مقدار این سه بیت “000” است و به تایمر (منظور TCNT2) هیچ کلاکی داده نمیشود و خاموش است. با انتخاب موارد غیر “000” کلاک ورودی تایمر 2 یا ClkT2S تقسیم بر یکی از ضرایب 1، 8، 32، 64، 128، 256 یا 1024 خواهد شد.
رجیستر Asynchronous Status Register) ASSR)
گفتیم چیزی که تایمر 2 را از تایمرهای 0 و 1 متمایز میکند، وجود حالت RTC است که برای زمانسنجی دقیق استفاده میشود.
تایمر 2 دارای دو منبع کلاک است که انتخاب هر کدام از آنها توسط بیت AS2 این رجیستر مشخص میشود. به شکل زیر دقت کنید.
با توجه به مقدار بیت AS2 :
- اگر این بیت 0 شود، کلاک ClkI/O که همان کلاک میکروکنترلر است وارد تقسیم کننده میشود.
- اگر این بیت 1 شود، کلاک اعمال شده به پایه TOSC1 وارد تقسیم کننده میشود.
اگر بیت AS2 را 1 کرده و به دو پایه TOSC1 و TOSC2 یک کریستال ساعت با فرکانس 32768Hz متصل کنیم، میتوانیم از قابلیت زمانسنجی دقیق بهره مند شویم.
سوال: اتصال کریستال 32768Hz چه فایدهای دارد؟
جواب: اگر بیتهای CS در وضعیت “101” تنظیم شوند یعنی ضریب تقسیم 128 اعمال شود، در این صورت کلاک نهایی تایمر 256 هرتز (256 = 32768/128) خواهد شد. از آن جایی که یک دور کامل شمارش TCNT2 به 256 کلاک احتیاج دارد، در این صورت با گذشت هر یک ثانیه، یکبار تایمر 2 سرریز میشود که اگر وقفه سرریز فعال شده باشد، هر یک ثاینه یکبار وقفه سرریز رخ خواهد داد.
دیگر بیتهای این رجیستر کاربرد خاصی ندارند و بیت مهم همان AS2 است.
ساخت ساعت دقیق با ATmega16
میخواهیم برنامهای بنویسیم که ساعت، دقیقه و ثانیه را بر روی lcd کاراکتری نشان دهد.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 |
#include <mega16.h> #include <stdio.h> #include <alcd.h> unsigned char Buffer[17]; unsigned char second = 20; unsigned char minute = 20; unsigned char hour = 20; void time_write(){ sprintf(Buffer,"%02d:%02d:%02d",hour,minute,second); lcd_gotoxy(4,0); lcd_puts(Buffer); } void main(void){ ///////////////////block 1 lcd_init(16); lcd_clear(); ///////////////////block 2 TIMSK = 0x40; TIFR = 0x40; #asm ("sei") ///////////////////block 3 ASSR = 0x08; TCNT2 = 0x00; TCCR2 = 0x05; ///////////////////block 4 time_write(); lcd_gotoxy(3,1); lcd_putsf("Rasdino.ir"); while(1); } interrupt[5]void Tik_Tik(void){ second++; if(second==60){ second = 0; minute++; if(minute==60){ minute = 0; hour++; if(hour==24) hour = 0; } } time_write(); } |
توضیح برنامه
خطوط 1 تا 3 هدر فایلهای مورد استفاده هستند که اولی مربوط به mega16، دومی برای استفاده از تابع sprintf و سومی مربوط به توابع کار با lcd کاراکتری است.
خط 5 یک آرایه از نوع unsigned char با نام Buffer تعریف کردیم که بعدا یک رشته درون آن جهت نمایش قرار میدهیم.
خطوط 6 تا 8 به ترتیب متغیرهای مربوط به ثانیه، دقیقه و ساعت تعریف شدهاند.
خطوط 10 تا 14 یک تابع به نام time_write تعریف شده است که با استفاده از دستور sprintf سه متغیر minute ،second و hour را در فرمت مخصوصی در درون آرایه Buffer قرار میدهد و سپس این آرایه در وسط خط اول lcd نشان داده میشود.
خط 16 تابع main را نوشتیم و در واقع نقطه آغاز برنامه از اینجاست.
بلاک 1
با دستور (lcd_init(16 ابتدا تنظیمات اتصال lcd به میکروکنترلر انجام شده و سپس با دستور ()lcd_clear تمام lcd پاک میشود.
بلاک 2
با مقداردهی TIMSK برابر با 0x40، وقفه سرریز تایمر 2 فعال خواهد شد. همچنین به دلایلی که گفتیم مقدار TIFR را هم 0x40 میدهیم. در آخر هم برای اینکه وقفه اجازه صدور داشته باشند، بیت وقفه عمومی را با دستور (“asm (“sei# فعال میکنیم.
بلاک 3
گفته شد برای اینکه کلاک تایمر 2 از پایههای TOSC تامین شود باید بیت AS2 را 1 کنیم. این بیت در رجیستر ASSR قرار دارد که با مقداردهی 0x08 برابر 1 میشود. سپس مقدار TCNT2 را جهت اطمینان 0 کرده و TCCR2 را هم 0x05 قرار میدهیم. با اینکار ضریب تقسیم کلاک 128 خواهد شد.
بلاک 4
تابع time_write را صدا زده تا در خط اول lcd ساعت نشان داده شود. در نهایت هم عبارت ثابت Rasdino.ir بر روی خط دوم چاپ شده و CPU وارد حلقه بینهایت while میشود.
سرویس روتین وقفه
چون قرار است هر یک ثانیه یکبار تایمر 2 سرریز شود، دستوراتی را که میخواهیم با هر بار وقوع وقفه اجرا شوند داخل سرویس روتین میگذاریم. در این صورت کلمه کلیدی interrupt را نوشته و شماره Vector مربوط به سرریز تایمر 2 را داخل [ ] مینویسیم. این شماره مشخص میکند که این دستورات مربوط به کدام وقفه است. شماره Vector سرریز تایمر 2 برابر 5 است.
دستورات داخل سرویس روتین ساده هستند. در هر بار اجرا متغیر second را 1 واحد زیاد میکنیم. اگر برابر 60 شد، 0 شده و یک واحد به minute اضافه میکنیم. همینطور اگر minute مساوی 60 شد، مقدارش را 0 کرده و یک واحد به hour اضافه میکنیم و در آخر اگر hour برابر 24 شد، مقدار آن را 0 خواهیم کرد.
پس از اتمام مراحل بالا، برای بروزرسانی lcd تابع time_write را صدا زده تا خط اول lcd اصلاح شود.
نتیجهگیری
به غیر ار مواردی مثل زمانگیری و تولید شکل موج PWM که بر روی پایه OC2 ظاهر میشود، خاصیت دیگر تایمر 2 حالت RTC است که با اتصال کریستال ساعت به پایه TOSC میکرو میتوان از آن استفاده کرد. البته حالت RTC زمانی کاربردی است که میکروکنترلر خاموش نشود. چون در این حالت دیگر عمل شمارش انجام نشده و ساعت عقب خواهد افتاد.
برای داشتن یک ساعت Real Time که با قطع برق به کار خود ادامه دهد، باید از آیسیهای مخصوص اینکار مثل DS1307 استفاده کرد که با اتصال یک باتری پشتیبان 3.3 ولت عمل زمانسنجی را انجام میدهد. سپس با اتصال سریال بین میکروکنترلر و این آیسی که در جلسات آینده در مورد آن صحبت میکنیم، اطلاعات ساعت و تاریخ را به راحتی مدیریت کرد.
در این قسمت از آموزش، سعی بر این بود که به مفاهیم تکراری تولید موج و زمانگیری نپردازیم و بیشتر تمرکز را بر حالت RTC تایمر 2 بگذاریم. اگر سوالی باقی مانده است، آخر همین پست کامنت کنید.
14 پاسخ
عاااااااااااااالی.چقد خوب و مسلط گفتین .دستتون واقعا درد نکنه
عالی توضیح دادید. دست مریزاد
مچکرم. ممنون از انرژی خوبتون.
ممنون عالی بود
سپاس فراوان بابت انرژی که صرف تهیه این مطالب می کنید
خواهش میکنم؛ انجام وظیفه میکنیم.
سلام در این برنامه میشه از کریستال ۸ مگ توی واقعیت استفاده کرد یا حتما نیازه که 32 کیلو هرتز استفاده کرد؟
بسیار عالی..
خداقوت مهندس ممنون از زحماتتون ، عالی بود
ببخشید فکر میکنم اشتباه بجای comparematch از capture استفاده کردید چون این تعریف اشتباهه و قابلیت capture برای تایمر ۱ هستش فقط
با عرض ادب و احترام؛
آیا میشه دو تایمر کانتر (مثلاً تایمر کانتر های 1و 2) رو بصورت همزمان راه اندازی کرد و هر کدوم برای مقاصد متفاوت استفاده کرد؟
با تشکر
بله امکان پذیر است هر تایمر بصورت مجزا فعالیت میکند
با عرض سلام و خسته نباشید،
میحواستم بدونم که این پروژه تون با اتمگا32 هم انجام دادین ؟
یا کد دستوری یا توضیح راجبش میتونید بدید؟
سلام
من این کد رو وارد کردم
اما بعد از compiler خط ۲۶ رو error میزنه .
مشکل از کجاست؟