הפעלת ה-ADC במיקרו-בקר ATmega4809

במסגרת הלמידה של המיקרו-בקר החדש והמדובר של Microchip, נתעכב הפעם על מודול ה-ADC, שמתרגם מתחים חשמליים למספרים שהתוכנה יכולה לעבד, ויודע לבצע עוד כמה דברים קצת יותר חכמים.

ל-ATmega4809 יש מודול ADC יחיד עם רזולוציה של 10 ביט. מודול זה מסוגל לקבל קלט מאחד מ-16 פינים, ממודול DAC פנימי או מחיישן טמפרטורה מובנה, ולמדוד אותו ביחס למתח האספקה של הרכיב, למתח חיצוני או לאחד מכמה ערכי מתח פנימיים קבועים. עד כאן, פרט לעניין ה-DAC, אין כאן בשורה מיוחדת ביחס למיקרו-בקרים מהדור הקודם. גם מצב ה-Free running (שבו המרות ה-ADC מתבצעות כל הזמן, ברצף) ואופציית הפסיקה בסיום ההמרה הם אלמנטים מוכרים.

לעומת זאת, ה-4809 מציע גם כמה חידושים מעניינים ביחס לקודמיו. ראשית, פונקציית "השוואת חלון" (Window compare) מאפשרת לנו להגדיר פסיקה שתתעורר רק כשתוצאת המדידה של ה-ADC נמצאת בתוך או מחוץ לטווח ערכים שאנחנו מגדירים. כך אנחנו יכולים, למשל, לנטר מתח של סוללה, או את הטמפרטורה של המיקרו-בקר, ולזהות חריגות מהותיות בלי לבזבז משאבי עיבוד וזמן בתוכנה.

שנית, אפשר לומר למודול ה-ADC לצבור מספר מדידות (2,4,8,16,32 או 64) לתוך רגיסטר התוצאה ולהתייחס לסכום כתוצאה יחידה, ובנוסף הוא מסוגל לשנות מעט את התזמון של כל אחת מהמדידות כדי למנוע סינכרון מקרי ולא רצוי עם תנודות מחזוריות בקלט. ביט מסוים באחד מרגיסטרי הבקרה מאפשר לנו אפילו לבחור את הקיבולת (Capacitance) של מנגנון הדגימה. אלו הם פרמטרים מתקדמים שביישומים "רגילים" אין בהם צורך, אבל במקרים נדירים יכול להיות להם ערך עצום.

בגדול, ביצוע מדידות על ידי ה-ADC נעשה בארבעה שלבים: 1. הגדרת הפרמטרים הרצויים, כולל מקור המתח הנמדד ומקור המתח לייחוס 2. הפעלת מודול ה-ADC עצמו, 3. מתן טריגר למודול להתחלת המדידה (בפקודה ישירה בקוד או על ידי קישור למודול אחר), ו-4. המתנה לסיום המדידה (שמזוהה באמצעות ביט "דגל" או על ידי פסיקה) וקריאת התוצאה מהרגיסטר המתאים.

לשמחתנו, ה-Datasheet של משפחת megaAVR 0-Series קריא וברור יחסית, והתיאור של מודול ה-ADC ושל הרגיסטרים שלו עוזר לכתוב את ארבעת השלבים בלי להסתבך. פרט אחד קטן שקל לפספס הוא שאם קוראים מתח מפין קלט, צריך לנטרל את "באפר הקלט הדיגיטלי" (Digital Input Buffer) של אותו פין כדי למנוע הפרעות פוטנציאליות למדידה. הניטרול הזה נעשה דרך רגיסטר PINxCTRL של אותו פין. לדוגמה, כהכנה לקריאת מתח מפין PD0, שהוא פין 0 של פורט D, ננטרל את הבאפר שלו כך:

PORTD_PIN0CTRL = 0x04;

הערך 0x04 נלקח מהטבלה הבאה, שבעזרתה אנחנו יכולים להגדיר, לחלופין, את אופי הפסיקה שתפעל על אותו פין:

הגדרות פסיקה ובאפר קלט לפין ב-ATmega4809 ודומיו
הגדרות פסיקה ובאפר קלט לפין ב-ATmega4809 ודומיו

ל-ATmega4809 יש כאמור מודול ADC יחיד שנקרא ADC0. למודול זה יש חמישה רגיסטרים שונים להגדרת הפרמטרים השונים של המדידה, והם נקראים ADC0_CTRLA עד ADC0_CTRLE. אין טעם להעתיק לפה את כל מה שכתוב ב-Datasheet; בתור דוגמה בלבד, הנה הפקודה להפעלת המודול, שבעצם כותבת "1" לביט 0 של הרגיסטר ADC0_CTRLA בלי לשנות את הביטים האחרים שאולי הגדרנו קודם. כפרקטיקה מומלצת, ניעזר בקבועים שהוגדרו מראש על ידי היצרן, במקום במספרים סתם:

 ADC0_CTRLA |= ADC_ENABLE_bm;

אפרופו, ביט 2 באותו רגיסטר מאפשר לנו לבחור בין מדידה ברזולוציה של 10 ביטים (ברירת המחדל) למדידה ב-8 ביטים, למי שממהר והדיוק קצת פחות חשוב לו.

כדי לבחור את הפין PD0 בתור מקור הקלט, נכתוב את הערך המתאים לרגיסטר הבחירה:

 ADC0_MUXPOS = 0x00;

מאיפה אני יודע ש-0x00 הוא הערך המתאים? שוב, הכול כתוב ב-Datasheet, צריך רק להסתכל. כך נוכל לדעת גם שכדי לבחור את Vdd, מתח ההפעלה של המערכת, בתור המתח לייחוס צריך לכתוב 0x01 לצמד הביטים 4-5 של הרגיסטר ADC0_CTRLC.

לסיום, בהנחה שהגדרנו את כל הפרמטרים כמו שצריך, הנה קוד בסיסי לביצוע של המרת ADC יחידה וקריאת התוצאה לתוך משתנה שנקרא לו v (שצריך להיות מטיפוס uint16_t ומעלה):

// Trigger an ADC conversion
ADC0_COMMAND |= ADC_STCONV_bm;

// Wait for it to finish
while (ADC0_COMMAND & ADC_STCONV_bm) {
}

// Read result
v = ADC0_RES;
להרשמה
הודע לי על
0 תגובות
Inline Feedbacks
הראה את כל התגובות