שְׁאֵלָה:
שולח uint16_t מעל I2C
Cerin
2016-09-20 09:45:16 UTC
view on stackexchange narkive permalink

איך אתה משדר וקורא uint16_t מעל I2C?

אני מנסה לקרוא שני ערכי uint16_t ממכשיר עבדים ואני רואה קריאות שטויות.

זה הקוד על העבד שלי Arduino Uno:

  #include <Wire.h>void send_wire_int (uint16_t num) {// שלח בתים נמוכים Wire.write ((uint8_t) num); // שלח בתים גבוהים מספר >> = 8; Wire.write ((uint8_t) num);} // זה נקרא ממארח ​​I2C. הימנע I2C_Send () {// send_wire_int (acount_abs); // שלח מקודד ספירה. // send_wire_int (bcount_abs); // שלח ספירת מקודד B. send_wire_int (0); send_wire_int (0);} הגדרת חלל () {Wire.begin (30); // אתחל את ספריית I²C והגדר את כתובת העבדים Wire.onRequest (I2C_Send); // להגדיר עבד I²C להעביר ISR Wire.flush (); Wire.setTimeout (1000L);} loop loop () {// stuff}  

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

זהו הקוד ב- Arduino Uno המאסטר שלי:

  #include <Wire.h>uint16_t receive_wire_int () {while (Wire.available () < 1) {} // קרא בתים נמוכים לתוך rxnum uint16_t rxnum = Wire .לקרוא(); while (Wire.available () < 1) {} // קרא בתים גבוהים לתוך rxnum rxnum + = Wire.read () << 8; החזר rxnum;} הגדרת חלל () {Wire.begin (); // הצטרף לאוטובוס i2c (כתובת אופציונלית עבור מאסטר) Wire.setTimeout (1000L); Serial.begin (9600); // התחל סדרתי עבור פלט} loop void () {Serial.println ("בקשת נתונים ..."); Serial.flush (); Wire.requestFrom (30, 4); uint16_t acount = receive_wire_int (); uint16_t bcount = receive_wire_int ();
Serial.println (String ("acount:") + String (acount) + String ("bcount:") + String (bcount)); עיכוב (500);}  

כפי שאתה יכול לראות, הוא פשוט מבקש את שני ערכי uint16_t בארבעה בתים, ולאחר מכן מדפיס אותם לסדרה (מסוף המחשב הנייד שלי).

הפלט שאני רואה הוא:

  acount: 65280 bcount: 65535  

מתי הייתי מצפה:

  acount: 0 bcount: 0  

מה אני עושה לא בסדר?

מהו קצב השעון I2C במאסטר? הגדרת אותו על העבד אך לא על מכשיר המאסטר.
נראה כאילו כל השיחות אל 'Wire.read ()', שמור לראשונה, החזר '-1', שהופך ל'0 xffff 'כאשר יצוק ל' uint16_t '. האם אתה יכול לבדוק אם יש מצב זה?
האם שני הארדואינו חולקים בסיס משותף?
@Andrew, מהירויות השעון הן ברירת המחדל / תקן 100k.
@EdgarBonet, אתה צודק ש- [read ()] (https://github.com/esp8266/Arduino/blob/master/libraries/Wire/Wire.cpp#L183) מחזיר -1 אם שום דבר לא מתקבל, אבל למה שזה קורה רק בשני מתוך 4 הבתים?
@Matt, כן, חיבור I2C כולל את סיכות SCL / SDA וכן Vcc / GND.
@Cerin - הייתי צריך לבדוק אני מניח שיש לך גם נגדים. אני חושב שפונקציית הקריאה תחזיר -1 אם אין נתונים. וזה מוזר מכיוון שהפונקציה הזמינה אומרת שיש 4 בתים של נתונים. מה קורה אם פג הזמן הקצוב של 1 ms? האם אתה יכול להגדיל את פסק הזמן באופן טיפשי? אתה מקבל -1 עבור 3 בתים ולא 2. הבית השני (חשבון MSB הוא גם -1). האם צריכה להתקיים 'Wire.available ()' בפונקציית הקריאה שלך כדי לחכות שהבית השני יהיה זמין?
@Matt, כן, נראה שאולי רק בית אחד מסיים את זה, והשאר קריאות () קוראות חוזרות -1. ניסיתי לשנות את פסק הזמן ל 1000 ms, אבל זה לא השפיע. שיניתי גם את הקריאות בכדי להמתין לכל בייט בנפרד, אך גם לכך לא הייתה כל השפעה.
@Cerin - האם בדקת את פונקציית הכתיבה באותו אופן? האם הוספת הצהרת עיכוב בין כתיבת העזרה תועיל? האם Write.write () מחזיר ערך, האם ייתכן שאתה כותב רק בת נתונים אחד?
שתיים תשובות:
KIIV
2016-09-20 21:27:03 UTC
view on stackexchange narkive permalink

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

לדוגמה זה עובד (AVR הם מעט אנדיאניים):

  #include <Wire.h> // זה נקרא ממארח ​​I2C.void I2C_Send () {uint16_t uints [2] = {0xDEAD, 0xBEEF}; Wire.write ((uint8_t *) uints, 4);} הגדרת חלל () {Wire.begin (30); // אתחל את ספריית I²C והגדר את כתובת העבדים Wire.onRequest (I2C_Send); // להגדיר עבד I²C להעביר ISR Wire.flush (); Wire.setTimeout (1000L);} loop loop () {// stuff}  

ומקלט עם הדפסים HEX :

  #include <Wire.h>uint16_t receive_wire_int () {while (Wire.available () < 1) {} // קרא בתים נמוכים ל- rxnum uint16_t rxnum = Wire.read (); while (Wire.available () < 1) {} // קרא בתים גבוהים ל- rxnum rxnum + = Wire.read () << 8; החזר rxnum;} הגדרת חלל () {Wire.begin (); // הצטרף לאוטובוס i2c (כתובת אופציונלית עבור מאסטר) Wire.setTimeout (1000L); Serial.begin (9600); // התחל סדרתי עבור פלט} loop void () {Serial.println ("בקשת נתונים ..."); Serial.flush (); Wire.requestFrom (30, 4); uint16_t acount = receive_wire_int (); uint16_t bcount = receive_wire_int (); Serial.print ("acount: 0x"); Serial.print (acount, HEX); Serial.print ("bcount: 0x"); Serial.println (bcount, HEX); עיכוב (500);}  
Cerin
2016-09-21 05:54:56 UTC
view on stackexchange narkive permalink

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

זה עובד אם אכתוב מחדש את העבדים שלי ל:

  בטל I2C_Send () { בתים myArray [4]; myArray [0] = 0; myArray [1] = 0; myArray [2] = 0; myArray [3] = 0; Wire.write (myArray, 4);}  


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