כשהמחשבות האישיות שלי על סטרוקטס הן הדרך היעילה ביותר לשלוח משתנים רבים ושונים, בניתי ספרייה כדי להקל על שליחת מבנים ומשתנים על סדרתי. קוד מקור
בספריה זו הוא מאפשר לשלוח באמצעות סדרתי בקלות. השתמשתי עם חומרה ותוכנה סדרתית. בדרך כלל משתמשים בזה בשילוב עם xbee כך שאוכל לשלוח את הנתונים באופן אלחוטי לרובוט וממנו.
בעת שליחת נתונים זה הופך אותו לפשוט כיוון שהוא מאפשר לשלוח משתנה או מבנה (זה לא לא אכפת).
הנה דוגמה לשליחת תו פשוט על הסידורי:
// שלח את המשתנה charVariable מעל סדרתי .// כדי לשלוח את המשתנה עליך להעביר מופע של הסידרה לשימוש, // הפניה למשתנה שיש לשלוח ולגודל המשתנה שנשלח .// אם תרצה תוכל לציין 2 נוספים בסוף ארגומנטים המשנים את // קידומת ברירת המחדל ותו הסיומת המשמשים בעת ניסיון לשחזר את המשתנה // בקצה המקבל. אם מצוינים קידומת ותו סיומת הם יצטרכו // להתאים בקצה המקבל אחרת נתונים לא יישלחו כראוי acrosschar charVariable = 'c'; // הגדר את המשתנה שיש לשלוח דרך serialStreamSend :: sendObject (Serial, &charVariable, sizeof (charVariable)); // ציין קידומת ותו סיומת StreamSend :: sendObject (Serial, &charVariable, sizeof (charVariable), 'a', 'z');
דוגמה לשליחת אינט פשוט דרך הסדרה:
int intVariable = 13496; // הגדר את ה- int שיישלח דרך serialStreamSend :: sendObject (xbeeSerial, &intVariable, sizeof (intVariable)); // ציין קידומת ותו סיומת StreamSend :: sendObject (xbeeSerial, &intVariable, sizeof (intVariable), 'p');
דוגמה למשלוח מבנה על סדרתי:
// הגדר את המבנה שיש לשלוח המבנה הסדרתי SIMPLE_STRUCT {
char char משתנה; int int-variable [7]; boolean boolVariable;}; SIMPLE_STRUCT simpleStruct; simpleStruct.charVariable = 'z'; // הגדר את charVariable במבנה ל- z // מלא את מערך intVariable במבנה עם מספרים 0 עד 6for (int i = 0; i<7; i ++) {simpleStruct.intVariable [i] = i;} // שלח את struct לאובייקט xbeeSerial שהוא סדרת תוכנה שהוגדרה //. במקום להשתמש ב- xbeeSerial תוכלו להשתמש בסידורי אשר ירמז על // סדרת החומרה, ובמגה תוכלו לציין Serial, Serial1, Serial2, Serial3.StreamSend :: sendObject (xbeeSerial, &simpleStruct, sizeof (simpleStruct)); // Send זהה לעיל עם קידומת וסיומת שונה מערכי ברירת המחדל // שהוגדרו ב- StreamSend. כאשר מציינים מתי קידומת ותו סיומת לשלוח // עליכם לוודא שבקצה המקבל הם תואמים אחרת הנתונים // לא יוכלו להיקרא בקצה השני. StreamSend :: sendObject (xbeeSerial, &simpleStruct, sizeof (simpleStruct), '3', 'u');
דוגמאות קבלה:
קבלת תו שהיה שלח באמצעות Streamsend:
char charVariable; // הגדר את המשתנה לאן יונחו הנתונים // קרא את הנתונים מהאובייקט הסידורי ושמור אותם ל- charVariable פעם אחת // הנתונים התקבלו byte packetResults = StreamSend :: receiveObject (Serial, &charVariable, sizeof (charVariable)) ; // בנה מחדש את התו המגיע מהסידרה ל charVariable שיש לו סיומת מותאמת אישית // וקידומת של packet zbyteResults = StreamSend :: receiveObject (Serial, &charVariable, sizeof (charVariable), 'a', 'z') ;
קבלת int שנשלח באמצעות StreamSend:
int intVariable; // הגדר את המשתנה היכן יונחו הנתונים // בנה מחדש את int מ- xbeeSerial למשתנה intVariablebyte packetResults = StreamSend :: receiveObject (xbeeSerial, &intVariable, sizeof (intVariable));
// בנה מחדש את הנתונים ל- intVariable שנשלחו עם קידומת מותאמת אישית // של j וסיומת של pbyte packetResults = StreamSend :: receiveObject (xbeeSerial, &intVariable, sizeof (intVariable), 'j', 'p'); קוד>
קבלת מבנה שנשלח באמצעות StreamSend:
// הגדר את המבנה שהנתונים יועברו למבנה SIMPLE_STRUCT {char charVariable ; int int-variable [7]; boolean boolVariable;}; SIMPLE_STRUCT simpleStruct; // צור מבנה לאחסון הנתונים ב // שחזר את הנתונים מ- xbeeSerial לאובייקט simpleStructbyte packetResults = StreamSend :: receiveObject (xbeeSerial, &simpleStruct, sizeof (simpleStruct)); // שחזר את הנתונים מ- xbeeSerial לאובייקט פשוט יותר יש // קידומת של 3 וסיומת של packetResults = StreamSend :: receiveObject (xbeeSerial, &simpleStruct, sizeof (simpleStruct), '3', 'p');
ברגע שאתה קרא את הנתונים באמצעות StreamSend :: receiveObject ()
אתה צריך לדעת אם הנתונים היו טובים, לא נמצאו או רעים.
טוב = מוצלח
לא נמצא = לא נמצא תו קידומת בזרם שצוין
רע = איכשהו נמצא תו קידומת, אך הנתונים אינם שלמים. בדרך כלל זה אומר שלא נמצאה תו סיומות או שהנתונים לא היו בגודל הנכון.
בדיקת תוקף הנתונים:
// ברגע שאתה מתקשר ל- StreamSend :: receiveObject () הוא מחזיר בית של הסטטוס // איך הדברים התנהלו. אם אתה מפעיל את זה למרות שחלק מפונקציות הבדיקה זה // יידע אותך כיצד התנהלה העסקה (StreamSend :: isPacketGood (packetResults)) {// החבילה הייתה טובה} אחרת {// החבילה הייתה גרועה} אם StreamSend :: isPacketCorrupt (packetResults)) {// החבילה הייתה מושחתת} אחר {// החבילה לא נמצאה או שהיא הייתה טובה} אם (StreamSend :: isPacketNotFound (packetResults)) {// החבילה לא נמצאה לאחר מקסימום מספר נסיונות} עוד {
// החבילה נמצאה, אך יכולה להיות מושחתת}
SteamSend Class:
#include "Arduino.h" #ifndef STREAMSEND_H # הגדר STREAMSEND_H # הגדר PACKET_NOT_FOUND 0 # הגדר BAD_PACKET 1 # הגדר GOOD_PACKET 2 // הגדר את הגודל המקסימלי של המאגר הסידורי או את כמות הנתונים שברצונך לשלוח + 2 // עליך להוסיף 2 כדי לאפשר את הקידומת וסיומת מרחב תווים לשליחה. # הגדר MAX_SIZE 64 קלאס StreamSend {פרטי: static int getWrapperSize () {return sizeof (char) * 2; } בתים סטטיים קבלת אובייקט (זרם &ostream, void * ptr, unsigned int objSize, unsigned int loopSize); בתים סטטיים קבלת אובייקט (זרם &ostream, void * ptr, לא חתום obj objize, int חתום int loopSize, char קידומת Char, סיומת char char); char charly_prefixChar; // ערך ברירת המחדל הוא תו סטטי _suffixChar; // ערך ברירת המחדל הוא e static int _maxLoopsToWait; public: static void sendObject (Stream &ostream, void * ptr, unsigned int objSize); static void sendObject (זרם &ostream, void * ptr, un חתום int objSize, char קידומת Char, סיומת char Char); בתים סטטיים קבלת אובייקט (זרם &ostream, ריק * ptr, לא חתום obj objize); בתים סטטיים קבלת אובייקט (זרם &ostream, חלל * ptr, int objSize לא חתום, char קידומת Char, סיומת char Char); סטטי בוליאני isPacketNotFound (const byte packetStatus); סטטי בוליאני isPacketCorrupt (const byte packetStatus); סטטי בוליאני isPacketGood (const byte packetStatus); סטטי ריק ריק setPrefixChar (ערך char const) {_prefixChar = value; } ריק ריק סטטי SuffixChar (const char value) {_suffixChar = value; } סטטי ריק ריק setMaxLoopsToWait (ערך const int) {_maxLoopsToWait = value; } char const char getPrefixChar () {return _prefixChar; } char const char getSuffixChar () {return _suffixChar; } const int int getMaxLoopsToWait () {return _maxLoopsToWait; }}; // קבוע מראש כמה משתני ברירת מחדל // ניתן לשנות כשרואים לנכון
char StreamSend :: _ prefixChar = 's'; // התחלת תו לפני שליחת נתונים על פני Serialchar StreamSend :: _ suffixChar = 'e'; // תו מסתיים לאחר שנשלח כל הנתונים StreamSend :: _ maxLoopsToWait = -1; // מוגדר כ -1 עבור גודל האובייקט והעטיפה הנוכחיים / ** * sendObject * * ממיר את האובייקט לבתים ושולח אותו לזרם * * @param זרם כדי לשלוח נתונים אל * @param ptr למבנה למילוי * @ גודל param של struct * @param תו שיש לשלוח לפני זרם הנתונים (אופציונלי) * @ param תו לשליחה אחרי זרם הנתונים (אופציונלי) * / void StreamSend :: sendObject (Stream &ostream, void * ptr, לא חתום int objSize) { sendObject (ostream, ptr, objSize, _prefixChar, _suffixChar);} void StreamSend :: sendObject (Stream &ostream, void * ptr, unsigned int objSize, char prefixChar, char suffixChar) {if (MAX_SIZE > = objSize) // וודא שהאובייקט לא גדול מדי בתים * b = (בתים *) ptr; // צור מערך ptr של הבתים לשליחת ostream.write ((byte) prefixChar); // כתוב את תו הסיומת כדי לסמן את תחילתו של זרם // עקוב אחר כל הבייטים הנשלחים וכתוב אותם לזרם עבור (unsigned int i = 0; i<objSize; i ++) {ostream.write (b [i]) ; // כתוב כל בייט לזרם} ostream.write ((בתים) סיומת Char); // כתוב את תו הקידומת כדי לסמן את סוף הזרם}} / ** * קבל אובייקט * * מקבל את הנתונים מהזרם ושומר לאובייקט שסופק * * @param זרם לקרוא נתונים מ * @param ptr למבנה למילוי * @param גודל המבנה * @param תו שיש לשלוח לפני זרם הנתונים (אופציונלי) * @param תו לשליחה אחרי זרם הנתונים (אופציונלי) * / בתים StreamSend :: receiveObject (זרם &ostream, ריק * ptr, לא חתום obj objize ) {return receiveObject (ostream, ptr, objSize, _prefixChar, _suffixChar);}
בתים StreamSend :: receiveObject (זרם &ostream, חלל * ptr, לא חתום int objSize, char קידומת Char, סיומת char) {return קבלObject (ostream, ptr, objSize, 0, קידומת Char, סיומת Char);} בתים StreamSend :: קבל אובייקט (Stream & void * ptr, int objSize לא חתום, int loopSize לא חתום, prefixChar char, char סיומת char) {int maxLoops = (_maxLoopsToWait == -1)? (objSize + getWrapperSize ()): _maxLoopsToWait; if (loopSize > = maxLoops) {return PACKET_NOT_FOUND; } אם (ostream.available () > = (objSize + getWrapperSize ())) {// חבילה עומדת בדרישת גודל מינימאלית אם (ostream.read ()! = (byte) prefixChar) {// תו הקידומת לא נמצא // דרוך שוב בקוד וקרא את החזרת char הבאה, קבלObject (ostream, ptr, objSize, loopSize + 1, prefixChar, suffixChar); } נתוני char [objSize]; // צור מערך char tmp של הנתונים מ- Stream ostream.readBytes (data, objSize); // קרא את מספר הבתים memcpy (ptr, data, objSize); // העתק את הבתים למבנה אם (ostream.read ()! = (בתים) סיומת צ'אר) {// תו הסיומת לא נמצא החזר BAD_PACKET; } להחזיר GOOD_PACKET; } להחזיר PACKET_NOT_FOUND; // תו הקידומת לא נמצא ולכן לא זוהתה מנות} StreamSend בוליאני :: isPacketNotFound (const byte packetStatus) {return (packetStatus == PACKET_NOT_FOUND);} StreamSend בוליאני :: isPacketCorrupt (const byte packetStatus) {return (packetStatus == BAD_ );} StreamSend בוליאני :: isPacketGood (const byte packetStatus) {return (packetStatus == GOOD_PACKET);} # endif