- מדוע טיימר כשיש לנו עיכוב ()?
- טיימרים למיקרו-בקר PIC:
- הסבר על תכנות ועבודה:
- תרשים מעגלים וסימולציית פרוטאוס:
זו תהיה ההדרכה החמישית בסדרת ההדרכות PIC שלנו, שתעזור לך ללמוד ולהשתמש בטיימרים ב- PIC16F877A. בהדרכות הקודמות שלנו, התחלנו עם מבוא ל- PIC ו- MPLABX IDE, ואז כתבנו את תוכנית ה- PIC הראשונה שלנו כדי להבהב את ה- LED באמצעות PIC ואז עשינו רצף מהבהב של LED באמצעות פונקציית עיכוב במיקרו-בקר PIC. עכשיו נשתמש באותו רצף LED מהבהב בו השתמשנו בחומרת ההדרכה הקודמת ועם זה נלמד כיצד להשתמש בטיימרים ב- PIC MCU שלנו. הרגע הוספנו כפתור אחד נוסף בלוח LED להדרכה זו. עברו על המדריך למידע נוסף.
טיימרים הם אחד מסוסי העבודה החשובים עבור מתכנת משובץ. כל יישום שאנו מעצבים יכלול איכשהו יישום תזמון, כמו להפעיל או לכבות משהו לאחר פרק זמן מוגדר. אוקיי, אבל למה אנחנו צריכים טיימרים כשיש לנו כבר פקודות מאקרו (עיכוב_ms ()) שעושות את אותו הדבר !!
מדוע טיימר כשיש לנו עיכוב ()?
מאקרו של עיכוב נקרא עיכוב "dump". מכיוון שבמהלך ביצוע פונקציית Delay ה- MCU יושב על ידי יצירת עיכוב בלבד. במהלך תהליך זה ה- MCU אינו יכול להקשיב לערכי ה- ADC שלו או לקרוא דבר מהרישומים שלו. לפיכך לא מומלץ להשתמש בפונקציות עיכוב למעט יישומים כמו LED מהבהב כאשר עיכוב הזמן אינו צריך להיות מדויק או ארוך.
המקרו העיכוב יש גם את בואם הקצר הבא,
- ערך העיכוב חייב להיות קבוע עבור פקודות מאקרו; לא ניתן לשנות את זה במהלך ביצוע התוכנית. לפיכך נותר מוגדר מתכנת.
- העיכוב לא יהיה מדויק בהשוואה לשימוש בטיימרים.
- לא ניתן ליצור ערכים גדולים יותר של עיכובים באמצעות פקודות מאקרו, לדוגמא אי אפשר ליצור עיכוב של חצי שעה על ידי פקודות מאקרו. העיכוב המרבי שניתן להשתמש בו מבוסס על מתנד קריסטל המשמש.
טיימרים למיקרו-בקר PIC:
מבחינה פיזית, טיימר הוא רישום שערכו עולה כל הזמן ל 255, ואז הוא מתחיל מחדש: 0, 1, 2, 3, 4… 255…. 0, 1, 2, 3……וכו.
ל- PIC16F877A PIC MCU יש שלושה מודולי טיימר. הם שמות כ- Timer0, Timer1 ו- Timer2. טיימר 0 וטיימר 2 הם טיימרים של 8 ביט וטיימר 1 הוא טיימר של 16 ביט. במדריך זה נשתמש בטיימר 0 ליישום שלנו. ברגע שנבין את טיימר 0 יהיה קל לעבוד גם על טיימר 1 וטיימר 2.
הטיימר / מונה למודול Timer0 כולל את התכונות הבאות:
- טיימר / דלפק 8 סיביות
- קריא וכתוב
- Prescaler לתכנות 8 סיביות
- בחר שעון פנימי או חיצוני
- הפסק על הצפה מ FFh ל 00h
- בחר קצה לשעון חיצוני
כדי להתחיל להשתמש בטיימר, עלינו להבין כמה מהמונחים המהודרים כמו טיימר 8 סיביות / 16 סיביות, Prescaler, Timer interrupts ו- Focs. עכשיו, בואו נראה מה באמת כל אחד מתכוון. כפי שנאמר קודם, ישנם שני טיימרים של 8 סיביות ו -16 סיביות ב- PIC MCU שלנו, ההבדל העיקרי ביניהם הוא שלטיימר של 16 סיביות יש רזולוציה טובה בהרבה מזו של 8 סיביות.
Prescaler הוא שם לחלק של מיקרו-בקר המחלק את שעון המתנד לפני שהוא יגיע להיגיון המגביר את מצב הטיימר. הטווח של מזהה prescaler הוא בין 1 ל 256 וניתן להגדיר את הערך של Prescaler באמצעות OPTION Register (זהה בו השתמשנו לנגדי משיכה). לדוגמא, אם הערך של prescaler הוא 64, אז עבור כל 64 th דופק טיימר יגדלו על ידי 1.
ככל שהטיימר מתגבר וכאשר הוא מגיע לערכו המרבי של 255, הוא יפעיל הפרעה ויתחל את עצמו ל -0 בחזרה. הפרעה זו נקראת בשם הפסקת טיימר. הפרעה זו מודיעה ל- MCU כי הזמן המסוים הזה חלף.
ה- Fosc מייצג תדר של המתנד, זהו תדר הקריסטל המשמש. הזמן שנדרש לרישום הטיימר תלוי בערך של Prescaler ובערך ה- Fosc.
הסבר על תכנות ועבודה:
במדריך זה נגדיר שני כפתורים כשני כניסות ו- 8 נוריות כ- 8 יציאות. הלחצן הראשון ישמש להגדרת עיכוב הזמן (500ms לכל לחיצה) והלחצן השני ישמש להפעלת רצף הטיימר המהבהב. לדוגמא, אם לוחצים על הכפתור הראשון שלוש פעמים (500 * 3 = 1500ms) העיכוב יוגדר ל -1.5 שניות וכאשר לוחצים על כפתור שני כל נורית תידלק ונכבה עם עיכוב הזמן שהוגדר מראש. בדוק את סרטון ההדגמה בסוף הדרכה זו.
עכשיו, עם היסודות האלה בחשבון, הבה נבחן את התוכנית שלנו שניתנה בסוף בסעיף הקוד.
זה בסדר אם לא קיבלת את התוכנית, אבל אם כן !! תן לעצמך עוגיה וזרוק את התוכנית כדי ליהנות מהתפוקה שלך. לאחרים אפרוק את התוכנית לחלקים משמעותיים ואסביר לך מה קורה בכל בלוק.
כמו תמיד השורות הראשונות של הקוד הן הגדרות התצורה וקבצי הכותרת, אני לא מתכוון להסביר זאת מכיוון שכבר עשיתי זאת במדריכים הקודמים שלי.
לאחר מכן, בואו נדלג על כל השורות ונקפוץ היישר לפונקציה הראשית הריקנית, שבתוכה יש לנו את תצורת ה- PORT עבור ה- Timer0.
void main () {/ ***** תצורת יציאה לטיימר ****** / OPTION_REG = 0b00000101; // Timer0 עם freq חיצוני ו- 64 כ prescalar // מאפשר גם PULL UPs TMR0 = 100; // טען את ערך הזמן עבור 0.0019968 שניות; delayValue יכול להיות בין 0-256 בלבד TMR0IE = 1; // אפשר סיבית הפסקת טיימר ברישום PIE1 GIE = 1; // אפשר הפרעה גלובלית PEIE = 1; // אפשר את ההפרעה ההיקפית / *********** ______ *********** /
כדי להבין זאת עלינו להסתכל במרשם ה- OPTION בגליון הנתונים של ה- PIC שלנו.
כפי שנדון במדריך הקודם, נעשה שימוש בסיבית 7 כדי לאפשר נגד התנגדות חלש עבור ה- PORTB. תסתכל על האיור לעיל, הסיבית 3 נעשתה 0 כדי להנחות את ה- MCU כי יש להשתמש במגוון המחוון הבא שמוגדר עבור הטיימר ולא עבור ה- WatchDogTimer (WDT). מצב טיימר נבחר על ידי ניקוי ביט 5 T0CS
(OPTION_REG <5>)
כעת, ה- bits2-0 משמש לקביעת ערך prescaler עבור הטיימר. כפי שמוצג בטבלה שלמעלה כדי להגדיר ערך prescaler של 64, יש להגדיר את הביטים כ -101.
לאחר מכן, הבה נבדוק את הרישומים המשויכים ל- Timer0
הטיימר יתחיל להתגבר ברגע שהוגדר ויעלה על גדותיו לאחר שהגיע לערך 256, כדי לאפשר את הפרעת הטיימר במהלך נקודה זו יש להגדיר את הרישום TMR0IE גבוה. מכיוון שטיימר 0 עצמו הוא ציוד היקפי עלינו לאפשר את ההפרעה ההיקפית על ידי הפיכת PEIE = 1. לבסוף עלינו לאפשר את ה- Global Interrupt כך שה- MCU יקבל הודעה על ה- Interrupt במהלך כל פעולה, זה נעשה על ידי הפיכת GIE = 1.
עיכוב = ((256-REG_val) * (Prescal * 4)) / Fosc
הנוסחה שלעיל משמשת לחישוב הערך של עיכוב.
איפה
REG_val = 100;
פרסקאל = 64
Fosc = 20000000
זה בחישוב נותן, עיכוב = 0.0019968 שניות
קבוצת השורות הבאה היא הגדרת יציאות ה- I / O.
/ ***** תצורת יציאה עבור I / O ****** / TRISB0 = 1; // הנחו את ה- MCU כי סיכה PORTB 0 משמשת כקלט לכפתור 1. TRISB1 = 1; // הנחו את ה- MCU כי סיכה PORTB 1 משמשת כקלט לכפתור 1. TRISD = 0x00; // הורה ל- MCU שכל הפינים ב- PORT D יופלטו PORTD = 0x00; // אתחל את כל הסיכות ל- 0 / *********** ______ *********** /
זה זהה לזה של המדריך הקודם שלנו מכיוון שאנחנו משתמשים באותה חומרה. אלא שהוספנו כפתור נוסף כקלט. זה נעשה על ידי קו TRISB1 = 1.
בשלב הבא, אינסוף תוך כדי לולאה יש לנו שני גושי קוד. האחד משמש לקבלת קלט הטיימר מהמשתמש והשני לביצוע רצף העיכוב על נוריות הנורות. הסברתי אותם באמצעות הערות כנגד כל שורה.
ואילו (1) {count = 0; // אל תפעיל טיימר בזמן הלולאה הראשית // ******* קבל את עיכוב המספר מהמשתמש **** ////// אם (RB0 == 0 && דגל == 0) // מתי קלט שניתן {get_scnds + = 1; // get_scnds = get_scnds + http: // דגל משתנה מגדיל = 1; } אם (RB0 == 1) // כדי למנוע דגל תוספת רציף = 0; / *********** ______ *********** /
משתנה הנקרא get_scnds מצטבר בכל פעם שהמשתמש לוחץ על כפתור 1. משתמשים במשתנה דגל (מוגדר בתוכנה) כדי להחזיק את תהליך התוספת עד שהמשתמש מסיר את אצבעו מהכפתור.
// ******* בצע רצף בעיכוב **** ////// תוך (RB1 == 0) {PORTD = 0b00000001 <
הבלוק הבא נכנס לפעולה אם לוחצים על כפתור שני. מכיוון שהמשתמש כבר הגדיר את עיכוב הזמן הנדרש באמצעות כפתור אחד והוא נשמר במשתנה get_scnds. אנו משתמשים במשתנה הנקרא hscnd, משתנה זה נשלט על ידי ה- ISR (שגרת שירות להפסיק).
שגרת שירות הפסיקה מהווה פסיקה כי תיקרא בכל פעם Timer0 הוא גולש. בואו נראה כיצד הוא נשלט על ידי ה- ISR בבלוק הבא, כמו שאנחנו רוצים להגדיל את עיכוב הזמן בחצי שנייה (0.5s) בכל לחיצה על כפתור ואז עלינו להגדיל את המשתנה hscnd לכל חצי שנייה. כפי שתכננו את הטיימר שלנו לזרום יתר עבור כל 0.0019968 שניות (~ 2ms), כך לספור משתנה של חצי שנייה של ספירה צריך להיות 250 כי 250 * 2ms = 0.5 שניה. אז כאשר הספירה מגיעה ל -250 (250 * 2ms = 0.5 שניה), המשמעות היא שהייתה חצי שנייה ולכן אנו מגדילים את hscnd ב -1 ומתחילים את הספירה לאפס.
חלל הפסקת זמן timer_isr () {אם (TMR0IF == 1) // דגל הטיימר הופעל עקב הצפת טיימר {TMR0 = 100; // טען את הטיימר ערך TMR0IF = 0; // נקה טיימר להפסיק ספירת דגלים ++; } אם (ספירה == 250) {hscnd + = 1; // hscnd יקבל תוספת עבור כל ספירה של חצי שנייה = 0; }}
לכן אנו משתמשים בערך זה ומשווים אותו ל- hscnd שלנו ומעבירים את ה- LED שלנו על בסיס הזמן שהוגדר על ידי המשתמש. זה גם מאוד דומה להדרכה האחרונה.
זהו זה שהבנתנו את התוכנית שלנו ועובדת.
תרשים מעגלים וסימולציית פרוטאוס:
כרגיל מאפשר לאמת את הפלט באמצעות Proteus תחילה, קישרתי כאן את הקבצים הסכימטיים של Proteus.
הוסף כפתור ללוח LED הקודם שלנו והחומרה שלנו מוכנה לשימוש. זה צריך להיראות בערך כך:
לאחר סיום החיבור, העלה את הקוד וודא את הפלט. אם יש לך בעיה, אנא השתמש בסעיף ההערות. בדוק גם את הסרטון למטה כדי להבין את כל התהליך.