۰۲۱-۷۷۶۰۵۵۳۸

پنج شنبه, 20 -2669 ساعت 00:00

برنامه نویسی تایمر کانتر در میکروکنترلر AVR بخش 1

نوشته شده توسط 
این مورد را ارزیابی کنید
(1 رای)

برنامه نویسی تایمر کانتر در میکروکنترلر AVR بخش 1

 

 

کارگاه عملی با تشریح برنامه نویسی تایمر/کانتر یک آماده شده است.

این جلسه،فقط میخوایم در مورد کدنویسیش صحبت کنیم.

ایندفعه میخوایم از وقفه هم که تا حالا تو کدنویسی هامون ازش استفاده نکردیم،استفاده کنیم.

کد نویسی به زبان سی در محیط کامپایلر کدویژن :

فرکانس کاری میکروکنترلر 16 مگاهرتز خارجی تعریف شده.

#include<mega32.h>

در ابتدای کار،طبق معمول فایل سرآیند مربوط به میکروکنترلر مورد نظرمون که اینجا ATmega32 هست رو اضافه میکنیم.

#include<mega32.h>

void timer1_configuration (){}

تابعی تعریف کردیم با نام : timer1_configuration ، که تنظیمات اولیه و پیکربندی تایمر/کانتر یک رو در اون انجام میدیم.

#include<mega32.h>

void timer1_configuration (){

TCCR1B |=(1<<CS11);// Prescaler=8
TIMSK |=(1<<TOIE1);// Enable Timer1 Overflow

TCNT1=0;// Initialize Timer/Counter1

#asm ("sei"); // Enable Global Interrupts

}

تموم اون حرفایی که قبلا زدیم رو داریم میاریم رو کامپایلر !

توضیحات رو بصورت کامنت روبروی هر عبارت براتون نوشتم.فکر نکنم مسئله خاصی باشه.

بریم سراغ تابع main :

void main(){

DDRB.0=1;// Config B.0 As Output Pin
timer1_configuration ();// Load Timer1 Configurationwhile(1){}// Loop Forever

}

پین B.0 همون پایه ای هست که میخوایم بهش LED رو وصل کنیم.پس خروجی تعریف میشه !

در خط بعدی،تابع timer1_configuration رو فراخوانی میکنیم،تا تایمر/کانتر شماره یک پیکربندی بشه.

و در پایان،یه حلقه بینهایت تعریف شده که یجورایی برنامه تو این حلقه گیر میکنه و از داخل اون در نمیاد !

یه متغیری تعریف میکنیم از جنس int ، با نام مثلا : overflow

وظیفه این متغیر،شمارش تعداد سرریز های رخ داده است !

یادتونه گفتم طبق فرضیات باید 61 بار سرریز رخ بده تا 2 ثانیه طی بشه ؟!

پس این متغیر میخواد ببینه که، کِی تعداد سرریز ها 61 عدد میشه ؟

#include<mega32.h>

int overflow=0;

این هم از تعریف متغیر از نوع integer با نام overflow و همچنین مقدار اولیه 0.

بریم سراغ اصل کار؛

تعریف زیرروال مربوط به وقفه :

 در مورد وقفه قبلا جداگانه بحث کردیم :

اما درباره برنامه نویسیش نه !

فکر کنم که دیگه الان وقتش باشه.

برای تعریف وقفه از تابع کلیشه ای زیر استفاده میکنیم :

interrupt[VectorNumber]voidint_expression(void){

برنامهسرویسوقفه

}

به جای عبارت int_expression ، یه نام دلخواه برای تابع وقفه انتخاب میکنیم.

به جای [Vector Number]،عدد وکتور مورد نظر رو از روی دیتاشیت انتخاب میکنیم.

در مورد Vector Number هم از روی دیتاشیت نگاه میکنیم و عدد مورد نظر رو انتخاب میکنیم و از اون استفاده میکنیم !

نکته : در داخل براکت،به جای عدد،میتوان از عبارت متناظر در ستون Source جدول بالا نیز استفاده کرد.

interrupt [10]void timer1_int (){}

 اینجا هم اومدیم و برای Vector Number عدد 10 رو انتخاب کردیم که مربوط به وقفه Timer/Counter1 Overflow میشه.

اسمش رو هم گذاشتیم : timer1_int

interrupt [10]void timer1_int (){

overflow++;// Increase The Number Of Overflow 

// Check If 2 Sec Passed

if(overflow>=61){ 

PORTB^=(1<<0);// Toggle B.0
overflow=0;// Reset The number Of Overflow

}}

با هر بار سر ریز شدن،یک واحد به متغیر overflow اضافه میشه.

هنگامیکه تعداد سرریزها 61 (یا احیانا بیشتر از 61) بشه،پین B.0 شروع به Toggle شدن میکنه !

یعنی اگه خاموشه،روشن میشه و اگه روشنه خاموش.

در انتها مقدار متغیر overflow رو مجددا صفر میکنیم تا تایمر/کانتر یک،مجددا اقدام به محاسبه زمان مورد نظر ما کنه.

و در انتها کل کد :

#include<mega32.h>

int overflow=0;

void timer1_configuration (){

TCCR1B |=(1<<CS11);// Prescaler=8
TIMSK |=(1<<TOIE1);// Enable Timer1 Overflow

TCNT1=0;// Initialize Timer/Counter1

#asm ("sei"); // Enable Global Interrupts

}

interrupt [10]void timer1_int (){

overflow++;// Increase The Number Of Overflow 

// Check If 2 Sec Passed

if(overflow>=61){ 

PORTB^=(1<<0);// Toggle B.0
overflow=0;// Reset The number Of Overflow

}}

void main(){
DDRB.0=1;// Config B.0 As Output Pin 
timer1_configuration ();// Load Timer1 Configuration while(1){}// Loop Forever}

چون دفعه اول بود که از وقفه ها استفاده میکردیم جا داره که یه بار بصورت مختصر بگم چه کارایی دقیقا انجام دادیم :

هدف این بود که تاخیری به میزان 2 ثانیه بسازیم.

با محاسباتی که انجام دادیم به این نتیجه رسیدیم که باید حدودا 61 بار سرریز در تایمر/کانتر یک رخ بده تا مدت زمان 2 ثانیه بدست بیاد.

با ایجاد یک تابع با نام timer1_configuration ، پیکربندی تایمر/کانتر یک رو انجام دادیم.

در تابع اصلی main هم،پین B.0 رو خروجی تعریف کردیم و تابع timer1_configuration رو فراخوانی کردیم.

چون در واقع ما کاری نمیخوایم انجام بدیم و کار اصلی رو تایمر داره برای ما انجام میده و فعالیت تایمر/کانتر هم مستقله،یه حلقه بینهایت میسازیم و برنامه رو گیرش میدیم داخل حلقه !!!

منتظر میمونیم تا 2 ثانیه طی بشه !

حالا کِی 2 ثانیه طی میشه ؟! هر وقت تعداد سرریزها 61 تا شد !

پس تایمر/کانتر تا سرریز کرد،چون براش وقفه سرریز رو فعال کردیم،سریع میپره به برنامه زیرروال خودش (timer1_int).

برنامه زیرروال رو انجام میده و پس از اینکه انجام داد،مجددا برمیگرده به محل قبلی(حلقه بینهایت).

دائما طی سیکلهای زمانی مشخص،سرریز انجام میپذیره و برنامه زیرروال مربوطه انجام میشه.

 

به تایمر/کانتر میگه آقا هروقت سرریز کردی،یه دونه به مقدار متغیر overflow که خودمون تعریفش کردیم و مقدار اولیش رو صفر تعیین کردیم،اضافه کن.

همونطور که گفتم؛دائما سرریز تایمر/کانتر یک انجام میشه و یکی یکی به مقدار متغیر overflow اضافه میشه.

میایم یه شرط هم تعریف میکنیم داخل زیر روال؛هر وقت تعداد این سرریزها 61 یا بیشتر شد(2 ثانیه گذشت !!!)؛پین B.0 رو Toggle کن.

بازدید 392413 بار آخرین ویرایش در یکشنبه, 09 آذر 1393 ساعت 12:38
+