אנחנו ממשיכים את סדרת הפוסטים הפופולרית (נניח) על תכנות בסיסי של מיקרו-בקר MSP430G2553 הוותיק של TI עם סביבת הפיתוח Code Composer Studio, והפעם ניצור משהו דמוי פונקציית millis של ארדואינו, בהתבסס על טיימר ועל פסיקה שלו.
למי שלא זוכר – בכל זאת, הפוסט הקודם בסדרה היה לפני קצת יותר משנה – אני מציג כאן הפעלה של מודולים בסיסיים במיקרו-בקר הזה, שהיה פופולרי מאוד לפני עשר שנים: Texas Instruments מכרה אז לוחות פיתוח שלו, שהיו באיכות גבוהה, ובמחירים נמוכים אפילו יותר מארדואינו סיניים (כולל משלוח מהיר עד הבית). לרוע המזל, כפי שקורה לעתים קרובות כל כך ובמיוחד בחברות טכנולוגיה גדולות, TI לא הבינה ולא התנהלה נכון בשוק החדש של המייקרים. הלוחות האלה התבזבזו עליו, לא צברו תנופה, ובסופו של דבר נשכחו לגמרי. אף על פי כן, לפיתוח רציני, משפחת המיקרו-בקרים 16-ביט MSP430 היא עדיין אופציה לגיטימית לגמרי.
הפעם נממש פונקציה שימושית במיוחד: ספירה מדויקת של אלפיות שנייה. ל-MSP430G2553 יש שני טיימרים, מסוג שנקרא "TIMER_A" (לא שזה ממש משנה לנו, במיוחד כשהסוג "TIMER_B" שקיים בכמה דגמים אחרים דומה לו מאוד). אלה הם טיימרים 16-ביט, מה שאומר שכדי לזהות אלפיות שנייה, אם שעון המערכת שלנו הוא 16MHz, צריך רק לגרום לאחד מהטיימרים לספור שוב ושוב מ-0 עד 16,000 ולעורר פסיקה. לצורך העניין בחרתי את הטיימר הראשון מבין השניים, שנקרא Timer0.
כמו בכל מיקרו-בקר, צריך להגדיר לטיימר מאיזה שעון הוא ניזון. ברירת המחדל, שמוגדרת בביטים TASSELx של הרגיסטר TA0CTL, היא אות שעון חיצוני שיתחבר לפין P1.0 (כן, אותו אחד ששולט, בלוח הפיתוח, בלד האדום). לא רלוונטי לנו – אנחנו רוצים את שעון המערכת, ושיהיה נטו, בלי חלוקה. אם צריך, מגדירים את החלוקה הנוספת בביטים IDx של אותו רגיסטר. הביטים MCx קובעים את אופן הפעולה של הטיימר: מה שיהיה לנו הכי נוח עכשיו נקרא Up mode – ספירה חוזרת מ-0 עד הערך שברגיסטר TA0CCR0. לקינוח, נכתוב 1 לביט TA0IE שמאפשר את הפסיקה של הטיימר הזה. לא לשכוח להפעיל אחר כך באופן גלובלי את הפסיקות, עם הפקודה __enable_interrupt() .
הפסיקה הדרושה של הטיימר, כפי שגיליתי אחרי חיפוש מתיש, נקראת TIMER0_A1_VECTOR. יש אחת נוספת, לא רלוונטית כרגע, שנקראת TIMER0_A0_VECTOR, ומה שעוד יותר מעצבן, הפסיקה שלנו (A1) יכולה להתעורר גם במצבים אחרים, כלומר היא משותפת עם פעולות אחרות של הטיימר. זו הסיבה שצריך – מה שגיליתי אחרי דיבוג עוד יותר מתיש – לאפס את דגל הפסיקה הספציפי בקוד שבתוך פונקציית הפסיקה, אחרת היא תתעורר שוב ושוב ותתקע לנו את הקוד הראשי. זה בניגוד לפסיקות שראינו בפוסטים הקודמים, אלה של ה-WDT ושל ה-UART, שטיפלו בדגל הפסיקה שלהן לבד.
הלולאה הראשית שלי ביצעה toggle, שינוי מצב הפלט של P1.0, בכל אלפית שנייה, מה שאמור להפיק גל ריבועי בתדר 500Hz, אבל הסקופ הראה דווקא 490Hz. כפי שהראיתי בפוסט הראשון בסדרה, אפשר לשקף את שעון המערכת הראשי באחד מהפינים של המיקרו-בקר, ואכן התדר שהופיע שם היה נמוך יותר מ-16MHz הצפויים – סביבות 15.6MHz, אף על פי שזכרתי להשתמש ברגיסטרים הייעודיים לכיול. כמו תמיד, אם רוצים דיוק טוב יותר, אין ברירה אלא להשתמש בגביש/אות שעון חיצוני או לכייל את הקוד במיקרו-בקר הספציפי באופן ידני.
הקוד שלי נעזר, לצורך ספירת אלפיות השנייה, במשתנה גלובלי שמתעדכן בקוד הפסיקה ונקרא מחוץ לו. המשתנה הזה הוא גם 32 ביט, שאי אפשר לקרוא בפעולת אסמבלי יחידה כיוון שארכיטקטורת המיקרו-בקר היא 16 ביט. לכן חשוב לזכור להגדיר את המשתנה הזה בתור volatile, ולנטרל את הפסיקות בזמן הקריאה שלו, כדי שפסיקה לא תשנה את הערך באמצע הקריאה.
הקוד המלא לפוסט הזה נמצא כאן.