שְׁאֵלָה:
מה יקרה כשאשתמש במספר PIN לא חוקי?
Anonymous Penguin
2014-02-17 21:26:30 UTC
view on stackexchange narkive permalink

קשור ל: מה קורה אם יש שגיאת זמן ריצה?

שאלה זו דומה לשאלה שלמעלה, אולם זו חלופה מצב:

  int pin = 999; pinMode (pin, OUTPUT); digitalWrite (pin, HIGH);  

מה יקרה במקרה זה? המהדר אולי יתפוס אותו אבל אם השתמשת במספר אקראי IDE יתפוס אותו?

שתיים תשובות:
#1
+9
asheeshr
2014-02-17 22:48:05 UTC
view on stackexchange narkive permalink

המהדר לא יזהה שום שגיאה והקוד ידורש ויבוצע. לפיכך, כדי לראות מה קורה עלינו לחקור את הקסם שמאחורי הקלעים. לסיכום, דלג עד הסוף.


השורה השנייה בקוד שלך היא המקום שבו הקסם יקרה ושם אנחנו צריכים להתמקד.

  pinMode (pin, OUTPUT);  

החלק של pinMode הרלוונטי לדיון זה הוא:

  בטל pinMode (פין uint8_t, מצב uint8_t) {uint8_t bit = digitalPinToBitMask (pin); // המופע הראשון שבו משתמשים בסיכה uint8_t port = digitalPinToPort (pin); if (port == NOT_A_PIN) return; // Do something}  

(היישום המלא ניתן למצוא ב- wiring_digital.c)

אז, כאן, נראה כי digitalPinToBitMask משתמש ב pin כדי לחשב ביט ביניים. לחקור עוד, digitalPinToBitMask הוא מאקרו המוגדר ב- Arduino.h שהגדרתו היא קו אחד זה:

  #define digitalPinToBitMask (P) (pgm_read_byte (digital_pin_to_bit_mask_PGM + (P)))  

אניה אחת למראה מוזר זה עושה משימה מאוד פשוטה. הוא מוסיף לאינדקס את האלמנט P th במערך digital_pin_to_bit_mask_PGM ומחזיר אותו. מערך זה digital_pin_to_bit_mask_PGM מוגדר ב- pins_arduino.h או במפת הסיכה עבור הלוח הספציפי שנמצא בשימוש.

  const uint8_t PROGMEM digital_pin_to_bit_mask_PGM [] = {_BV (0), / * 0, port D * / _BV (1), _BV (2), _BV (3), _BV (4), _BV (5), _BV (6 ), _BV (7), ...};  

מערך זה כולל 20 אלמנטים בסך הכל, כך שאין לנו מזל. 999 יוסיף אינדקס מיקום זיכרון בזיכרון הבזק מחוץ למערך זה, ובכך יוביל להתנהגות בלתי צפויה. או שיהיה?

עדיין יש לנו קו הגנה נוסף נגד אנרכיה בזמן ריצה. זו השורה הבאה של הפונקציה pinMode:

  uint8_t port = digitalPinToPort (pin);  

digitalPinToPort לוקח אותנו בדרך דומה. הוא מוגדר כמקרו יחד עם digitalPinToBitMask . ההגדרה שלה היא:

  #define digitalPinToPort (P) (pgm_read_byte (digital_pin_to_port_PGM + (P)))  

כעת, אנו מוסיפים את אינדקס ה- P האלמנט ה sup> של digital_pin_to_port_PGM שהוא מערך המוגדר במפת הסיכה:

  const uint8_t PROGMEM digital_pin_to_port_PGM [] = {PD, / * 0 * / PD, .... PC, PC,};  

מערך זה מכיל 20 אלמנטים, כך ש- 999 שוב מחוץ לטווח. שוב, פקודה זו קוראת ומחזירה ערך מזיכרון ההבזק שערכו איננו יכולים להיות בטוחים. זה שוב יוביל להתנהגות בלתי צפויה מכאן והלאה.

יש עדיין קו הגנה אחרון. זה הסימון if ב- pinMode בערך ההחזרה של digitalPinToPort:

  if (port == NOT_A_PIN) return;  

NOT_A_PIN מוגדר כ- 0 ב Arduino.h . לכן, אם במקרה שבית המוחזר מ- digitalPinToPort אפס, אז pinMode ייכשל בשקט ויחזור.

בכל מקרה, pinMode לא יכול להציל אותנו מאנרכיה. 999 נועד לגרום לאבדון.


TL; DR, הקוד יבוצע והתוצאה של זה לא תהיה צפויה. סביר להניח שלא ייקבע סיכה. ל OUTPUT ו- digitalWrite ייכשלו. אם במקרה יש לך מזל רע במיוחד, סיכה אקראית עשויה להיות מוגדרת ל OUTPUT , ו- digitalWrite עשוי להגדיר אותו ל HIGH .

מעניין שאין בדיקת גבולות. digitalWrite בכל מקרה כל כך איטי ומגושם, שלא יהיה מביך להכניס זמן הידור או בדיקות זמן.
אם כל הפינים של הארדואינו נמצאים בטווח רציף, הם לא יכלו להחליף את היציאה == לא בדיקת סיכה בעזרת סיכה> BOARD_MAX_PIN, כאשר נקודת סיכה מקסימלית של הלוח מוגדרת בקובץ כותרת כלשהו על סמך איזו ifdef שמזהה את הלוח?
אתה שוכח שלא ניתן לייצג את 999 ב- 'uint8_t' ולכן תחילה יומר ל- 231 על ידי הקוד המכונה 'pinMode'. התוצאה הסופית היא זהה: ל- "pinMode" ול- "digitalWrite" תהיה התנהגות בלתי צפויה ועלולה לסתום חלקים אקראיים בזיכרון אם תקראו אליהם בטיעון סיכה רע.
#2
+4
TheDoctor
2014-02-17 21:50:12 UTC
view on stackexchange narkive permalink

בספריות הסטנדרטיות יש פקודות מאקרו המיועדות להמרת פינים ליציאות המשמשות בהרכבה. הנה הם עבור ה- Uno מארדואינו 1.0.5:

  #define digitalPinToPCICR (p) (((p) > = 0 && (p) < = 21)? (&PCC (uint8_t *) 0)) # הגדר digitalPinToPCICRbit (p) (((p) < = 7)? 2: ((p) < = 13)? 0: 1)) # הגדר digitalPinToPCMSK (p) (((p < = 7)? (&PCMSK2): (((p) < = 13)? (&PCMSK0): (((p) < = 21)? (&PCMSK1): (u)) digitalPinToPCMSKbit (p) (((p) < = 7)? (p): (((p) < = 13)? ((p) - 8): ((p) - 14)))  

יש עוד, אבל אני לא אראה אותם כאן.

אני מאמין שהתוכנית שלך תגרע 14 מ- 999, וזה עדיין יהיה גדול מדי לברוגרמה. לאחר מכן הוא ינסה להצביע על האלמנט 985 של digital_pn_to_bit_mask_PGM מערך, שמכיל רק 20 אלמנטים. זה בסופו של דבר בסופו של דבר יבריג את הארדואינו על ידי הצבעה על נקודה אקראית בתוכנית.



שאלה ותשובה זו תורגמה אוטומטית מהשפה האנגלית.התוכן המקורי זמין ב- stackexchange, ואנו מודים לו על רישיון cc by-sa 3.0 עליו הוא מופץ.
Loading...