التايمر باستخدام pic16f877a

 بسم الله الرحمن الرحيم

بعد ان  قمنا في الدروس السابقة بشرح العديد من المواضيع المهمة
واعطينا مقدمة كافية للتعريف بمتحكمات pic والتي يمكن الإطلاع عليها من هنا  
وتحدثنا في الدرس الذي يليه عن المنافذ الرقمية التي يحتويها متحكم pic16f877a وللإطلاع عليه من هنا 
وقمنا بعمل العديد من التجارب لتوضيح هذه الدروس السابقة والتي يمكن الإطلاع عليه من هنا 
وقمنا ايضا بشرح المقاطعات وفكرة عملها وللإطلاع عليها من هنا 


 لكن في هذا المقال سنتطرق لشرح مكون داخلي يسمي المؤقتات timers 
وهي مكون الكتروني وظيفته انها تقوم ببدء العد عند بدء عمل المتحكم وتصل الي قيمة معينة ثم تقوم بالعد مره اخري
دعنا نوضح اكثر في البداية يجب عيلنا التطرق الي مكون الكتروني يسمي flip flop ودوائر counter التتابعية
اولا مكون flip flop هو مكون رقمي له القدرة علي تخزين 1 بت اما 0 او 1 ويتم اخراج هذه القيمة في صورة طاقة  
حيث يتم تحديد القيمة التي يتم اخراجها تبعا للإشارة الداخلة علي منفذ clk وهذا تبعا لنوع flip flop
اشارة clk لها احتمالين فقط falling edge , rising edge 
falling edge هي عندما تكون الإشارة قيمتها 0
rising edge هي عندما تكون الإشارة قيمتها 1
 ففي حالة timers الموجودة في المتحكم تكون ال flip flops تقوم بتغيير حالتها اذا كان اشارة المؤقت 1 او بمعني عندما تكون موجة المؤقت في rising edge
حيث يحتوي flip flop علي مجموعة من الترانزيستورات التي تشكل بعض البوابات المنطقية التي تقوم بالإحتفاظ بالإشارة 
يوجد العديد من الأنواع من flip flops اشهرها 
SR FLIP FLOP
JK FLIP FLOP
حيث النوع الأول هو النوع الأبسط من ال FLIP FLOPS
 والنوع الثاني هو اكثر الأنواع شهرة وهو المستخدم في متحكم PIC16F877A
لتوضيح فكرة عمل القلابات بشكل اسرع سنناقش 
الحالات التي يتم تحديد قيمة الخرج Q عليها  ودور CLK في تحديد قيمة الخرج Q و ايضا دائرة COUNTER كيف تعمل 

يتكون JK FLIP FLOP من 5 منافذ منفذ J , K  وهم يتم تعيين بهم اشارة الخرج او Q 

منفذ CLK وهو موجود بين منفذين J , K ويتم ادخال عليه الإشارة CLOCK 

و منفذ Q وهو الخرج و منفذ الأخر Q وعليه شرطة في الأعلي وهو عكس الخرج فلو كان الخرج 1 يكون المنفذ الثاني الخرج عليه 0

يتم  اتباع الجدول التالي في قيمة الخرج علي  Q

 

حيث نلاحظ في حالة كانت الإشارة علي منفذين J , K تكون Q ثابته لا تتغير 

واذا كانت J 0 و K 1 يتم عمل RESET لإشارة Q وجعلها تساوي 0

واذا كانت قيمة J 1 و قيمة K 0 يتم جعل اشارة Q تساوي 1

وفي حالة كانت الإشارة 1 علي كل من المنفذين K , J فيتم عكس اشارة Q   

حسنا هذه الإشارة التي يتم اخراجها تبعا ل J K  ما علاقة منفذ CLK بهذه الإشارة 

يتم توضيح هذا الأمر في المخطط التالي


عندما تكون اشارة CLK في RISING EDGE في الثانية الأولي
نلاحظ ان قيمة اشارة J 1 و قيمة K 0 في بداية RISING EDGE  فتبعا للجدول 
تكون قيمة الخرج Q تساوي 1 وهذا ما نراه في المخطط الخاص ب Q 
وحتي بعد ان اصبحت اشارة K 1 مادام لم تتغير اشارة CLK فلم تتغير ابدا اشارة Q 
وبالنظر الي اشارة CLK نلاحظ انها بعد ان اصبحت الإِشارة تساوي 0 ثم ارتفعت الإشارة مره اخري لتصبح 1 
فعند الإرتفاع الثاني كانت اشارة K 1 و اشارة J 0 
فتبعا للجدول تكون قيمة Q هي 0 وحيث حدث REST لقيمة Q
ومع كل التغير في الإشارة CLK يتم قراءة الإشارات القادمة علي J , K ونلاحظ من الثانية الثانية الي بداية الثانية الثالثة لا يحدث تغير في اشارة Q بسبب ثبات اشارة J  K 
ومع بداية الثانية 3 تم تغير اشارة حتي اصبحت J 1 , K 1 
وتبعا للجدول يتم عمل تبديل لقيمة Q ونري كيف تتغير قيمة Q من بداية الثانية الثالثه 
وهذا هو مبدا عمل FLIP FLOP 
ننتقل للموضع التالي وهو دائرة COUNTER يتم تحديد 
اقصي عدد يمكن ان تصل اليه الدارة من العلاقة 
2^n-1
2 مرفوعه لاس n والذي يمثل عدد flip fops مطروح منه واحد
في حالة flip flop 1 
2^1-1 = 2-1 =1
حيث بمعني flip flop 1 يمكن ان يعد الي رقم 1 فقط 
وهذا طبيعي انه يحتمل احتمالين فقط اما 0 او 1 
و مثال اخر 2 flip flop
2^2-1 = 4-1 = 3
وبمعني اقصي عدد يمكن ان يصل 2 flip flop مربوطين مع بعضهما هو رقم 3 
نتطرق لدائرة counter وكيفية بناءها
حيث يوجد مثل هذه الدوائر في كل timer module داخل متحكم pic16f877a
 
حيث لربط اكثر من flip flop مع بضعهما يتم اتباع الآتي 
توصيل كل من j , k الي منفذ اشارة واحد وهو 1 
وهذا يعني انه مع كل تغير في البلصات القادمة من الإِشارة يتم تبديل قيمة Q ونري انه يتم تفريع الخرج من كل FLIP FLOP الي طرفين طرف يذهب الي CLOCK الخاص ب FLIP FLOP الذي يليه 
وطرف تكون عليه الإِشارة وعند تشغيل الدارة نري الآتي


حيث يكون الناتج مع ترتيب كل flip flop من اليمين لليسار
0001
0010
0010
0100 
0101
0110
0111
1000
1001
1010
1011
1100
1101
1110
1111
والتي تعادل الأرقام من 1 الي 15 عند تحويل هذه الأرقام من صيغة binary الي decimal
وهذا تبعا للمعادلة 
2^4-1=16-1=15
وهذا هو الناتج العد الي رقم 15 هذا هو مبدأ عمل counters
ننتقل الأن الي صلب الدرس كل ماسبق كان عبارة عن مقدمة تمهيدية لفهم فكرة عمل XD timer 
 
 في متحكم pic16f877a يوجد اكثر من تايمر به 
سنتعامل مع timer1
 
حيث نلاحظ وجود 3 timers في متحكم الخاص بنا 
حيث يختلف كل timer عن بعضه في بعض الإختلافات مثل اقصي رقم يمكن ان يصل اليه العد والتركيب الإلكتروني 
حيث يتكون timer0 من 16 jk filp flop
حتي يصل اقصي رقم يمكن العد له هو 
2^16-1 = 65535
ولقد قمنا بشرح دائرة العداد في الأعلي
 حيث يوجد اسلوبين للتعامل مع timer في المتحكمات
timer mode
counter mode
الأسلوب الأول : يتم استخدامه عند الرغبة في توليد الزمن بين حدثين 
او مثلا عمل فترة زمنية تفصل بين 2 حدث 
مثال اطفاء وتشغيل ليد بين الإطفاء والتشغيل يكون هناك زمن محدد يتم تحديد هذا الزمن عن طريق timer 
الأسلوب الثاني : يتم استخدامه عند الرغبة في قياس عدد البلصات الخاصة بإشارة  قادمة علي احد منافذ التي هي مهيأة لإستلام البلصات 
حيث يقوم الأسلوب الثاني بحساب عدد البلصات القادمة علي المنافذ مثال السبحة الإلكترونية 

عند بدء التعامل مع timers يتم العد تبعا لعدد البلصات وهذا ما ذكرناه سابقا
عندما تصل دائرة العداد الي اقصي رقم و تصل الي حالة overflow وهي تكون كل 16 بت قيمتها 1 هنا يتم 
كتابة 1 في TMR1IF هذا البت الموجود في المقاطعات التي قمنا بالتحدث عنها في الدرس السابق والذي يمكن الإطلاع عليه من هنا
دعونا نوضح اكثر عند استخدام TIMER يتم العد من 0 الي 65535 وعندما يصل TIMER الي هذه القيمة والتي يكون فيها 16 بت قيمتها 1 يحدث OVERFLOW وفي هذه اللحظة يعود العداد مره اخري للعد من 0 مره اخري 
ويتم تخزين 1 في FLAG BIT الموجودة في REGISTER المقاطعة 
وهذا يعني اننا لكي نتعامل مع المؤقت يجب علينا تشغيل المقاطعة الخاصة بهذا المؤقت
TMR1IE
GIE
PEIE
وهذا لكي يمكننا الوصول لإِشارة الFLAG الخاصه بهذا المؤقت

 
 
متحكم pic16f877a هو متحكم من فئة 8 بت فالسؤال كيف يكون timer1 من 16 بت رغم ان متحكم اقصي register به 8 بت
حيث لكي يتم حل هذه المشكلة تم دمج 2 register مع بعضهما ونلاحظ ذلك في 
TMR1 
حيث تم دمج TMR1H,TMR1L لكي يتكون لنا امكانية تخزين 16 بت
ثم توجد بعد ذلك بوابة AND GATE وهي المسئولة عن تشغيل او اطفاء TMR1 ويتم التحكم بها عن طريق كتابة 1 او 0 في TMR1ON bit 
 
ويوجد ايضا مكون synchronize والذي له دور عند استخدام counter mode ويقوم ايضا بعمل تزامن بين external clock او الإشارات القادمة من خارج المتحكم مع internal clock او الإشارات القادمة من crystal التي نقوم بربطها مع المتحكم ويتم استخدام هذا المكون في counter mode فقط
 
ومكون prescaler وهو يمكن لنا من قسمة التردد علي رقم محدد اما 1 او 2 او 4 او 8 وهذا لتقليل التردد ولكي نحدد الرقم يوجب 2 بت متصلين بهذا المكون هما T1CKPS0 , T1CKPS1 ويتم كتابة الرقم تبعًا للجدول التالي 
11  يكون القسمة علي 8
10 يكون القسمة علي 4
01 يكون القسمة علي 2
00 يكون القسمة علي 1

ثم ياتي مكون اشبه بالسويتش الرقمي وهو منه يمكننا تحديد سنتعامل مع اي mode وهو مرتبط ب  TMR1CS حيث لو كتبنا في هذا البت 1 يتم تفعيل counter mode اي بمعني يتم اخذ الإشارة الخاصة بالبلصات من خارج المتحكم 
ولو كتبنا 0 يتم تفعيل timer mode ويتم اخذ الإشارات من الكريستال التي نقوم بربطها مع المتحكم ونلاحظ في حالة  استخدام counter mode يتم قسمة التردد علي 4 ونلاحظ هذا في كلمة FOSC /4 وهذا يحدث بما يسمي ب instruction cycle وهو ان اي عملية لكي تتم يتم تنفيذها في 4 خطوات وكل خطوة تاخذ ربع التردد الذي تعطيه لنا crystal وهذا الأمر معقد ولن نخوض فيه :)

هذا ما نحتاجه معرفته حول مكونات timer1 
دعنا نخوض في موضوع اخر
كما قلنا سابقا يتم عمل كعداد من timer الي ان يصل timer الي overflow او هي اقصي قيمة يمكن ان يصل لها العداد وهي في لحظتها تكون 16 بت قيمتها 1 
لكي نقوم بحساب الزمن الذي يستغرقه العداد ليصل الي overflow نقوم بحسابها من هذه المعادلة 
حسنا نحتاج الي العديد من المعطيات 
تردد الكريستال والذي سنستخدم كريستاله ترددها = 4 ميغا هرتز
و اقصي عدد يمكن العداد ان يعد له = 65535
ثم قيمة presceler والتي سنستخدم القيمة الإفتراضية  = 1
ثم نعوض في هذه المعادلة 
وعند التعويض يكون الزمن الذي يستغرقه timer1 ليصل الي overflow هو 0.065536 ثانية 
وهذا اقل من الثانية بكثير ولكي نصل الي الثانية نحتاج ان يقوم timer1 بان يصل الي 15 overflow وهذا من المعادلة 
x/0.065536
حيث x يتم كتابة فيها الزمن الذي نريد ان نصل اليه 
ولكي نستطيع الوصول الي 1 ثانية يتم عمل متغير كلما حدث overflow يتم جمع 1 علي المتغير و يتم تكرار هذا الأمر حتي يصل المتغير الي قيمة 15 و في هذه اللحظة تكون قد مرت ثانية
  
نقوم بعمل تجربة سنقوم بعمل وميض لمدة ثانية لليد باستخدام timer1
نقوم بعمل التوصيلة الآتية 
حيث سنربط الليد بمنفذ RB5 
والتوصيلات المعتادة 
ننتقل الي الجزء الأهم وهو الكود#include <pic16f877a.h>
 #include <pic16f877a.h>
#include <xc.h>
#define XTAL_FREG 4000000
unsigned char counter=0;
void main(void) {
    PEIE = 1;
    GIE = 1;
    TMR1IE =1;
    TRISB5 = 0;
    TMR1CS = 0;
    T1CKPS0 = 0;
    T1CKPS1 = 0;
    TMR1ON = 1;
    while(1){}
    return;
}
void interrupt ISR(){
    if(TMR1IF){
        counter++;
        if(counter==15){
            RB5=!RB5;
            counter=0;
        }
        TMR1IF = 0;
    }
}
حيث قمنا بتفعيل اكثر من مكون pie , geie , tmr1on , tmr1ie وكل هذا حتي نتمكن من التعامل مع timer1
ثم قمنا بتعين منفذ B5 كخرج و قمنا بكتابة 
ISR handlers
وفي حالة اذا كان tmr1if تساوي 1 قم بجمع واحد علي متغير العداد لو كان متغير العداد يساوي 15  قم بتغيير حالة الليد 
وقم بتصفير المتغير الذي هو بمثابة العداد وقم بتصفير ال flag الخاصة بمقاطعة ال timer1
وهكذا نقوم بعمل وميض لليد بدون امر delay 
لكن السؤال هنا لماذا كل هذا التعقيد في الكود اذا كان يمكننا كتابة الكود باستخدام طريقة delay وسيكون الأمر ابسط من هذا الامر ؟
امر delay يعتمد علي ايقاف جميع العمليات التي يقوم بها المتحكم اثناء تنفيذه فاذا كنت تقوم بعمليات وشغلت امر delay تتوقف كل هذه العمليات 
علي خلاف timer الذي لا يقوم بإيقاف اي عملية بل تستمر العمليات علي ما هي عليه وهذا الفرق بين كتابة الكود بطريقة delay وكتابة الكود بطريقة ال timer 

وهكذا نكون قد انتهينا من الشرح المفصل للأسلوب الأول وهو timer mode 
ننتقل الي الأسلوب الثاني وهو counter mode 
كما قلنا سابقا يختلف timer mode عن counter mode في مصدر clock القادمة 
حيث counter mode يكون مصدر clocks من خارج المتحكم علي احد المنفذين RC0 , RC1 
ولكن RC1  لكي يحتسب انك قمت بادخال بلصة يجب ان تكون الإنتقال من RISING EDGE TO FALLING EDGE
والعكس في RC0
وهذا المبدأ هو نفسه المطبق في السبحة الإلكترونية 
ولكي نطبق هذا المبدأ نقوم بإيقاف عمل SYNCHRONIZE عن طريق كتابة 0 في T1SYNC
ثم تفعيل T1OSCEN لكي نقوم بإستلام البلصات عن طريق كتابة فيه 1 
وبالتاكيد نقوم بتغيير منفذ CLOCK عن طريق كتابة 1 في TMR1CS بت 
وهكذا نكون قد فعلنا COUNTER MODE 
بالطبع لا يوجد مقاطعة في هذا الأسلوب فتقون انت بكتابة الكود الذي تريده تبعا لهذا في WHILE LOOP 
مثال 
اذا اردنا اخراج قيمة التايمر في صورة ليد
 TMR1 = PORTB 
وهكذا نكون قد اوفينا بالشرح مع التايمرز وشرحنا دوائر العداد و FLIP FLOPS  و كيفية عملهم وكيفية التعامل مع أسلوبين المؤقتات
تصميم وبرمجة : بلال حسان سعدي
 
تعليقات