پاسخ : آموزش کامپایلر CCS از صفر
سلام
از درسام خسته شدم اومدم یه پست بذارم
در قسمت قبلی با تایمر 0 در مد خارجی کار کردیم
در ادامه میخوام وقفه تایمر رو بگم و کارای مختلفی رو با تایمر 0 انجام بدیم
وقفه تایمر:
قبلا وقفه رو گفتیم چیه. و با وقفه خارجی هم کار کردیم.
هر کدوم از تایمرها هم برای خودشون یه وقفه دارن. که زمانی اتفاق میافته که تایمر سرریز (overflow) بشه برای همین به این وقفه، وقفه سرریز تایمر هم میگن. مثلا یه تایمر 8 بیتی رو فرض کنید که میتونه از 0 تا 255 رو بشمره و مثلا مقدار فعلی تایمر روی 255 هستش. حالا اگه تایمر فقط یک بار دیگه شمارش کنه چون پر شده و بیشتر 255 رو نمیتونه بشمره سرریز میشه و مقدارش 0 میشه. حالا همزمان با این سرریز یه وقفه هم توی برنامه میتونه اتفاق بیافته که شما باید اون رو فعال کرده باشین
هر کجا از برنامه که میخواید وقفه تایمر فعال بشه باید عبارت زیر رو بنویسید:
[code=c]enable_interrupts(int_timerx);[/code]
که بجای x در عبارت بالا باید شماره تایمر رو قرار بدید. مثلا برای فعال کردن وقفه تایمر 0 از عبارت زیر استفاده میکنیم :
[code=c]enable_interrupts(int_timer0);[/code]
یادتون باشه که وقفه global رو هم فعال کرده باشید.
حالا وقتی وقفه تایمر اتفاق میافته برنامه به تابع نوشته شده در پایین عبارت زیر میره:
[code=c]#INT_TIMERx[/code]
باز هم در عبارت بالا به جای x شماره تایمر باید نوشته بشه
مثلا میخوایم با میکروی 18f452 یه برنامه بنویسیم که با هربار سرریز تایمر مقدار یه متغیر 1 واحد زیاد بشه. کد زیر رو ببینید:
[code=c,15]#Include <18f452.h>
#fuses NOWDT,HS
#use delay(xtal=20mhz)
int16 overflow;
#INT_TIMER0
void count_overflow()
{
overflow++;
}
void main()
{
Setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
enable_interrupts(int_timer0);
enable_interrupts(global);
while(true);
}[/code]
به خط 15 که هایلایت شده دقت کنید. شما در پست قبلی با این دستور کار کرده بودید فقط بجای عبارت RTCC_INTERNAL از عبارت RTCC_EXT_L_TO_H استفاده کردید. دلیلش واضحه که چرا اینجا اینطوری نوشته شده. چون میخواستیم تایمر به صورت داخلی فعال بشه و از کلاک خود میکرو شمارش رو انجام بده. همچنین عبارت RTCC_DIV_1 در تابع setup_timer0 مشخص کننده prescale تایمر هستش (یعنی به ازای هر کلاک یک واحد به تایمر اضافه بشه)
حالا با توجه به برنامه بالا فکر میکنید چقدر وقت یکبار به متغیر overflow یک واحد اضافه میشه؟
برای اینکه زمان سرریز تایمر رو مشخص کنیم قبلش باید چندتا چیز رو مشخص کنیم:
1- حجم تایمر 0 در میکروی 18f452 چقدره؟ که مطابق دیتاشیت 16 بیتی هستش پس تا عدد 65535 رو میتونه شمارش کنه
2- فاصله زمانی بین 2 کلاکی که به تایمر داده میشه چقدره؟ با توجه به این که کلاک در میکروهای 8 بیتی pic 1 به 4 است (یعنی 1/4 کل کلاک به cpu و واحدهای دیگه میرسه) پس با توجه به فرکانس 20 مگاهرتزی که ما مشخص کرده ایم فرکانس 5 مگاهرتز به تایمر میرسد (20 تقسیم بر 4 مساوی 5)
حالا از رابطه f=1/t میشه فاصله زمانی بین هر دو کلاک رو مشخص کرد که 1/5000000=0.2us پس فاصله زمانی بین دو کلاک برابر 0.2 میکروثانیه هستش.
3- بعد از چه مدت زمانی یک واحد به مقدار تایمر اضافه میشه؟ با توجه به این که prescale رو روی 1 تنظیم کردیم پس با هر کلاک یک واحد تایمر زیاد میشه پس زیاد شدن یک واحدی تایمر هم 0.2 میکروثانیه طول میکشه. این در حالیه که اگه prescale رو روی 2 تنظیم میکردیم افزایش هر واحد تایمر پس از 0.4 میکرو ثانیه رخ میداد
حالا با اطلاعات بالا میشه فهمید وقفه تایمر پس از چه مدتی رخ میده:
حجم تایمر 65536 واحد. هر واحد 0.2 طول میکشه پس کلا 65536*0.2=13107.2us طول میکشه تا وقفه اتفاق بیافته (حدود 13 میلی ثانیه)
برنامه بالا برای این بود که با نحوه محاسبه زمان و دستورات تایمر و وقفه اون بهتر آشنا بشید.
از برنامه بالا میتونید موقعی استفاده کنید که مثلا میخواید هر 13 میلی ثانیه داخل برنامتون یه اتفاقی بیافته (مثلا از adc یه نمونه برداری کنید)
یا میتونه موقعی مورد استفاده قرار بگیره که میخواید زمان های بیشتر از 13 میلی ثانیه رو اندازه گیری کنید. به این شکل که هر واحد متغیر overflow نشان دهنده یک سرریز هست و مقدار خود تایمر هم که موجوده پس با فرمول زیر میشه زمان های بزرگتری رو هم اندازه گیری کرد:
[code=c]time=(overflow*65536)+get_timer0();[/code]
در پست بعدی با چگونگی تولید فرکانس پایین با این تایمر ها آشنا میشید
سلام
از درسام خسته شدم اومدم یه پست بذارم

در قسمت قبلی با تایمر 0 در مد خارجی کار کردیم
در ادامه میخوام وقفه تایمر رو بگم و کارای مختلفی رو با تایمر 0 انجام بدیم
وقفه تایمر:
قبلا وقفه رو گفتیم چیه. و با وقفه خارجی هم کار کردیم.
هر کدوم از تایمرها هم برای خودشون یه وقفه دارن. که زمانی اتفاق میافته که تایمر سرریز (overflow) بشه برای همین به این وقفه، وقفه سرریز تایمر هم میگن. مثلا یه تایمر 8 بیتی رو فرض کنید که میتونه از 0 تا 255 رو بشمره و مثلا مقدار فعلی تایمر روی 255 هستش. حالا اگه تایمر فقط یک بار دیگه شمارش کنه چون پر شده و بیشتر 255 رو نمیتونه بشمره سرریز میشه و مقدارش 0 میشه. حالا همزمان با این سرریز یه وقفه هم توی برنامه میتونه اتفاق بیافته که شما باید اون رو فعال کرده باشین
هر کجا از برنامه که میخواید وقفه تایمر فعال بشه باید عبارت زیر رو بنویسید:
[code=c]enable_interrupts(int_timerx);[/code]
که بجای x در عبارت بالا باید شماره تایمر رو قرار بدید. مثلا برای فعال کردن وقفه تایمر 0 از عبارت زیر استفاده میکنیم :
[code=c]enable_interrupts(int_timer0);[/code]
یادتون باشه که وقفه global رو هم فعال کرده باشید.
حالا وقتی وقفه تایمر اتفاق میافته برنامه به تابع نوشته شده در پایین عبارت زیر میره:
[code=c]#INT_TIMERx[/code]
باز هم در عبارت بالا به جای x شماره تایمر باید نوشته بشه
مثلا میخوایم با میکروی 18f452 یه برنامه بنویسیم که با هربار سرریز تایمر مقدار یه متغیر 1 واحد زیاد بشه. کد زیر رو ببینید:
[code=c,15]#Include <18f452.h>
#fuses NOWDT,HS
#use delay(xtal=20mhz)
int16 overflow;
#INT_TIMER0
void count_overflow()
{
overflow++;
}
void main()
{
Setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
enable_interrupts(int_timer0);
enable_interrupts(global);
while(true);
}[/code]
به خط 15 که هایلایت شده دقت کنید. شما در پست قبلی با این دستور کار کرده بودید فقط بجای عبارت RTCC_INTERNAL از عبارت RTCC_EXT_L_TO_H استفاده کردید. دلیلش واضحه که چرا اینجا اینطوری نوشته شده. چون میخواستیم تایمر به صورت داخلی فعال بشه و از کلاک خود میکرو شمارش رو انجام بده. همچنین عبارت RTCC_DIV_1 در تابع setup_timer0 مشخص کننده prescale تایمر هستش (یعنی به ازای هر کلاک یک واحد به تایمر اضافه بشه)
حالا با توجه به برنامه بالا فکر میکنید چقدر وقت یکبار به متغیر overflow یک واحد اضافه میشه؟
برای اینکه زمان سرریز تایمر رو مشخص کنیم قبلش باید چندتا چیز رو مشخص کنیم:
1- حجم تایمر 0 در میکروی 18f452 چقدره؟ که مطابق دیتاشیت 16 بیتی هستش پس تا عدد 65535 رو میتونه شمارش کنه
2- فاصله زمانی بین 2 کلاکی که به تایمر داده میشه چقدره؟ با توجه به این که کلاک در میکروهای 8 بیتی pic 1 به 4 است (یعنی 1/4 کل کلاک به cpu و واحدهای دیگه میرسه) پس با توجه به فرکانس 20 مگاهرتزی که ما مشخص کرده ایم فرکانس 5 مگاهرتز به تایمر میرسد (20 تقسیم بر 4 مساوی 5)
حالا از رابطه f=1/t میشه فاصله زمانی بین هر دو کلاک رو مشخص کرد که 1/5000000=0.2us پس فاصله زمانی بین دو کلاک برابر 0.2 میکروثانیه هستش.
3- بعد از چه مدت زمانی یک واحد به مقدار تایمر اضافه میشه؟ با توجه به این که prescale رو روی 1 تنظیم کردیم پس با هر کلاک یک واحد تایمر زیاد میشه پس زیاد شدن یک واحدی تایمر هم 0.2 میکروثانیه طول میکشه. این در حالیه که اگه prescale رو روی 2 تنظیم میکردیم افزایش هر واحد تایمر پس از 0.4 میکرو ثانیه رخ میداد
حالا با اطلاعات بالا میشه فهمید وقفه تایمر پس از چه مدتی رخ میده:
حجم تایمر 65536 واحد. هر واحد 0.2 طول میکشه پس کلا 65536*0.2=13107.2us طول میکشه تا وقفه اتفاق بیافته (حدود 13 میلی ثانیه)
برنامه بالا برای این بود که با نحوه محاسبه زمان و دستورات تایمر و وقفه اون بهتر آشنا بشید.
از برنامه بالا میتونید موقعی استفاده کنید که مثلا میخواید هر 13 میلی ثانیه داخل برنامتون یه اتفاقی بیافته (مثلا از adc یه نمونه برداری کنید)
یا میتونه موقعی مورد استفاده قرار بگیره که میخواید زمان های بیشتر از 13 میلی ثانیه رو اندازه گیری کنید. به این شکل که هر واحد متغیر overflow نشان دهنده یک سرریز هست و مقدار خود تایمر هم که موجوده پس با فرمول زیر میشه زمان های بزرگتری رو هم اندازه گیری کرد:
[code=c]time=(overflow*65536)+get_timer0();[/code]
در پست بعدی با چگونگی تولید فرکانس پایین با این تایمر ها آشنا میشید
دیدگاه