פסיקות חיצוניות ב-CH32V003

בפוסט קודם קראנו קלט מלחצן באמצעות דגימות (polling) בקוד הראשי. בפוסט הזה נעבור לפתרון חכם יותר – שימוש בפסיקה, שתדאג לזהות שינוי במצב הקלט גם אם הקוד הראשי עסוק במשהו אחר. איך מגדירים את הפסיקה הזו במיקרו-בקר החדש שלנו?

פינצטה מתקרבת ללחצן על לוח הערכה

כאשר משתמש אנושי לוחץ על כפתור, הלחיצה הזו נמשכת זמן רב מאוד במונחים של מיקרו-בקרים. אפילו לחיצה שנראית לנו קצרצרה נמשכת עשרות אלפיות השנייה או יותר, וכל קוד סביר יוכל "לתפוס" אותה בדגימה רגילה. אף על פי כן, לעתים אנחנו זקוקים לזיהוי מיידי יותר. למשל, אם אנחנו בונים מערכת לשיגור טילי יירוט שבה כל שבריר שנייה קריטי, או שהקלט אינו מגיע מלחצן ידני אלא מרכיב אלקטרוני אחר שהסיגנל שלו נמדד באלפיות או מיליוניות השנייה. הפתרון המקובל למצבים כאלה נקרא external Interrupt, פסיקה חיצונית. זה שם קצת מטעה, כי יש עוד פסיקות עם טריגרים חיצוניים (כגון פעילות בקווי תקשורת). אבל זה מה יש ועם זה נסתדר.

פסיקה חיצונית מתקבלת דרך פין קלט דיגיטלי, אז בשלב ראשון נגדיר את הפין הרצוי של המיקרו-בקר. זה יכול להיות פין קלט פשוט ("צף") או עם נגד Pull-up או Pull-down פנימיים. בלוח שלי, הלחצן המובנה לשימוש חופשי מחבר את פין PC3 עם האדמה, אז נגדיר את PC3 כקלט עם Pull-up. לא לשכוח, צריך גם לחבר את פורט C כולו לשעון/חשמל.

// Enable clock for port C RCC->APB2PCENR |= 0x00000010; // PC3 is button input: PU/D mode + input mode GPIOC->CFGLR = 0x44448444; // Set enable Pull-up for PC3 GPIOC->OUTDR = 0x00000008;

הפונקציונליות של פסיקה חיצונית נמצאת תחת המטרייה של "Alternate function" של ה-GPIO, אז כדי שהיא תוכל לפעול, עלינו לתת חשמל גם למודול ה-AFIO:

// Enable AFIO - required for EXTI to work RCC->APB2PCENR |= 0x00000001;

עכשיו, הסבר קצר על שיטת העבודה עם הפסיקות החיצוניות (נקרא להן בקיצור EXTI), כי היא קצת מוזרה. ראשית, כמו שראינו ב-UART, יש פסיקה אחת ויחידה שמשויכת ל-EXTI. השם שלה, שאותו צריך לתת למימוש של פונקציית הפסיקה בקוד, הוא EXTI7_0_IRQHandler. הספרות בשם מרמזות שהיא יכולה להיות רלוונטית לכל פין בפורט, מ-0 ועד 7 כולל. אבל איך היא יודעת באיזה פורט מדובר?

ובכן, יש שמונה ערוצים שונים (0-7) שיכולים לעורר את הפסיקה, אבל עבור כל אחד מהם אנחנו חייבים לבחור פורט אחד ספציפי שממנו הוא יגיע. כלומר, אם בא לי להגדיר EXTI על PC3, אני יכול להוסיף נניח את PA1 או את PD6, אבל לא את PD3 כי ערוץ 3 כבר תפוס. אם בחרתי שערוץ 3 יגיע מפורט C, אז הוא יגיע רק משם. במילים אחרות, אם נתונים לנו פורטים A,C,D, אז לכל שלישיית פינים PAx,PCx,PDx מוקצה ערוץ EXTI אחד בלבד (שמספרו כמובן x). וכמעט מיותר לציין, ברגע שהגענו לתוך פונקציית הפסיקה, עלינו לבדוק "ידנית" מי מהערוצים עורר אותה.

תהליך ההגדרה של ערוצים בקוד הוא כזה: ראשית אנחנו מתירים לערוץ הרצוי להפעיל את פסיקת EXTI. שמונת הביטים הנמוכים (LSB) של הרגיסטר EXTI->INTENR מקבילים לשמונת הערוצים, אז לדוגמה כדי להפעיל את ערוץ 3 נכתוב לרגיסטר הזה 8 עשרוני (ביט שלישי מהסוף, כשהספירה מתחילה מאפס – בבינארי 1000).

// Enable EXT interrupt for channel 3 EXTI->INTENR |= 0x8; // MR3

שנית, צריך להגדיר אם הפסיקה תתעורר כשהמתח יעלה מנמוך לגבוה, יירד מגבוה לנמוך, או בשני המקרים. בשביל האופציה הראשונה יש את הרגיסטר EXTI->RTENR (ה-R הראשונה זה Rising) , ובשביל השנייה יש את EXTI->FTENR (ה-F זה Falling). שוב, נכתוב "1" לביט הרלוונטי בשמינייה הנמוכה של הרגיסטרים האלה, לפי הצורך. אם מעניין אותי לדעת רק מתי הלחצן שמחובר ל-PC3 נלחץ, והפין מוגדר כאמור עם Pull-up, אז התנאי שחשוב לי הוא Falling edge, כלומר:

// Set EXTI falling edge trigger for channel 3 EXTI->FTENR |= 0x00000008;

עד כה טיפלנו בערוץ 3, אבל עוד לא אמרנו לאיזה פורט לשייך אותו. זה נעשה על ידי הרגיסטר AFIO->EXTICR . הסתכלו בתיאור למטה, מתוך ה-Reference Manual: ברגיסטר זה, 16 הביטים הנמוכים מסודרים בזוגות, כל זוג מכוון לערוץ אחר, והערך שניתן לכל זוג קובע לאיזה פורט הוא יפנה, אם בכלל. הביטים של ערוץ 3 (ביטים מס' 6 ו-7 ברגיסטר) נקראים ביחד EXTI3, והערך "10" יפנה את הערוץ לפורט C:

מבנה הרגיסטר AFIO->EXTICR שמחבר ערוצים לפורטים
מבנה הרגיסטר AFIO->EXTICR שמחבר ערוצים לפורטים (לחצו לתמונה גדולה)

ולסיום, עלינו להגיד למערכת הפסיקות שתתחיל להתייחס גם לפסיקת EXTI. המספר הרשמי של הפסיקה הזו ברשימת הפסיקות הוא 20 עשרוני, אז עלינו לכתוב "1" לביט מס' 20 ברגיסטר PFIC->IENR[0]. שתי הפקודות האחרונות שהזכרתי נכתבות כך:

// Configure EXTI channel 3, for port C AFIO->EXTICR |= 0x00000080; // Enable EXTI IRQ PFIC->IENR[0] |= 0x00100000;

מה נשאר? פונקציית הפסיקה עצמה, כמובן. אנחנו יכולים לכתוב בה כל מה שנרצה, אבל חובה להוסיף שם פקודה שתאפס את דגל הפסיקה שהעיר אותה. אם לא נעשה את זה, הוא ימשיך להתריע שקרה משהו, ופונקציית הפסיקה פשוט תרוץ שוב ושוב בלי הפסקה. הדגלים – אחד לכל ערוץ – נמצאים בקצה הנמוך של הרגיסטר EXTI->INTFR, וכדי לאפס דגל צריך דווקא לכתוב לו "1". אז הנה פונקציית פסיקה מתוכנית שלי, וכיוון שהתוכנית הפעילה רק את ערוץ 3, אני מאפס רק את הדגל שלו (בפקודה שבשורה 121) – השאר לא רלוונטיים כאן.

פונקציית פסיקה לדוגמה ל-EXTI, ערוץ 3 בלבד
פונקציית פסיקה לדוגמה ל-EXTI, ערוץ 3 בלבד (לחצו לתמונה גדולה)
להרשמה
הודע לי על
0 תגובות
Inline Feedbacks
הראה את כל התגובות