سؤال

أحاول نسخ أعضاء بنية تحتوي على مزيج من ints وchar's ومصفوفات الأحرف في مصفوفة بايت لإرسالها إلى سطر تسلسلي.حتى الآن لدي

struct msg_on_send
{
    char descriptor_msg[5];
    int  address;
    char space;
    char cmdmsg[5];
    char CR;
    char LF;
};

void switch_output_on()
{
    int member;
    struct msg_on_send SendMsg_on[sizeof member] =
     {

    };
    unsigned char buffer [ sizeof SendMsg_on[0] ];
    showbytes(buffer, serialize(buffer, SendMsg_on));
}

/*************************************************************************** 
*   Function:   ArrayBuild                                                 *
*   Purpose:    Uses memcopy to transfer the struct members sequentially   *
*               into an array of char                                      *
*   Arguments:                                                             *
*   Returns:    size_t i = a count of the number of bytes in the array     *
***************************************************************************/    

size_t ArrayBuild(unsigned char *dst, const struct msg_on_send *object)
{
    size_t i = 0;

    memcpy(&dst[i], &object->descriptor_msg, sizeof object->descriptor_msg);
    i += sizeof object->descriptor_msg;

    memcpy(&dst[i], &object->address, sizeof object->address);
    i += sizeof object->address;

    memcpy(&dst[i], &object->space, sizeof object->space);
    i += sizeof object->space;

    memcpy(&dst[i], &object->cmdmsg, sizeof object->cmdmsg);
    i += sizeof object->cmdmsg;

    memcpy(&dst[i], &object->CR, sizeof object->CR);
    i += sizeof object->CR;

    memcpy(&dst[i], &object->LF, sizeof object->LF);
    i += sizeof object->LF;

    return i;
}

/*********************************************************************** 
*   Function:   USARTWrite                                             *
*   Purpose:    Writes the array data to the USART data register       *
*   Arguments:  void *object = struct member                           *
*               size_t size =  size of array remaining                 *
*   Returns:    None                                                   *
***********************************************************************/

void USARTWrite(const void *object, size_t size)        
{
    const unsigned char *byte;
    for ( byte = object; size--; ++byte )
    {
        printf("%02X", *byte);
    }
    putchar('\n');
}

وبما أنني حصلت على هذا الرمز، لا أفهم تمامًا كيف يعمل.أستطيع أن أرى أن memcpy يأخذ كل عنصر من عناصر البنية ويحوله إلى دفق تسلسلي مفهرس بواسطة المتغير 'i'، لكنني لا أعرف كيف تقوم وظيفة USARTWrite بتجميع ذلك في سلسلة، أو كيفية تحميل المصفوفة باستخدام تهيئة الهيكل الخاص بي.

آسف لأن هذا المنشور طويل بعض الشيء، لكنني بدأت للتو هذه اللعبة البرمجية، وأحاول أن أفهم هذا المفهوم.

شكرا ديف

يحرر:

واو، العديد من الإجابات الجيدة بسرعة - شكرًا يا شباب.

سلاز:يبدو هذا منطقيًا بالنسبة لي، لم أفكر حقًا في هذا النهج لأنني لم أستوعب المؤشرات بعد، لكنني بدأت أرى أنها جزء أساسي من لغة C، لذلك سألقي نظرة على النحو الواجب .

  • يرسل سطر التعليمات البرمجية هذا البيانات إلى UART الخاص بي، فما الذي يمكنني استبدال المصفوفة التي تحتوي على محتويات الرسالة بها؟يبدو أنني أفتقد خطوة منطقية هنا حيث لدي متغير يخبرني أين يبدأ الهيكل الخاص بي وما هو حجمه، ولكن لا توجد مصفوفة لإرسالها

    USART_SendData(USART1, message_on_contents[array_count]);
    

هاربر شيلبي:أشكرك على هذا الوصف، فهو يجعل الأمر أكثر وضوحًا في ذهني.

rgds

ديف

هل كانت مفيدة؟

المحلول

عذرا لم أرى تعليقك إلا الآن.يتم تجميع الكود أدناه على Linux بشكل جيد، لذلك آمل أن يكون مناسبًا لك.
تتم طباعة printf() بالنظام السداسي، وستحصل على حرفين لكل بايت.

#include <stdio.h>

struct msg_on_send
{
char descriptor_msg[5];
int  address;
char space;
char cmdmsg[5];
char CR; 
char LF; 
};

void USARTWrite(const void *object, size_t size)    
{
    const unsigned char *byte;
      for ( byte = object; size--; ++byte )                                     
      {   
          printf("%02X", *byte);
      }   
      putchar('\n');
}

int main (int argc, char**argv)
{
    struct msg_on_send myMsg;
    unsigned char* ptr= (unsigned char*)&myMsg;

    USARTWrite(ptr, sizeof(myMsg));

    return 0;
}

آمل أن يساعد هذا.

~
~

نصائح أخرى

ليس عليك نسخ البنية فعليًا إلى مجموعة من البايتات.يمكنك القيام بذلك اختياريًا:

struct msg_on_send myMessage;

// code to set myMessage to whatever values...

// get a byte pointer that points to the beginning of the struct    
uint8_t *bytePtr = (uint8_t*)&myMessage;

// pass that into the write function, and it will write the amount of bytes passed in
USARTWrite(bytePtr, sizeof(myMessage));

قوة المؤشرات!:)

إذا كنت أرغب في التعامل مع البنية كمصفوفة من البايتات، فعادةً ما أستخدم اتحادًا لدمج البنية مع مصفوفة البايتات.على سبيل المثال:

typedef union
{
    struct
    { 
        char descriptor_msg[5]; 
        int  address; 
        char space; 
        char cmdmsg[5]; 
        char CR; 
        char LF; 
    };
    BYTE bytes[];
} msg_on_send;

لك struct هذه مجرد مجموعة من البايتات، ولا تحتوي على مؤشرات تشير إلى خارجها.

من المرجح أن يتم إجراء النسخ من عضو إلى عضو للتعامل مع المحاذاة، مثل (char*) &address من المرجح أن يكون أكبر من ((char*) &descriptor_msg) + 5.

USARTWrite يرسل HEX رموز بايت من البنية الخاصة بك ل stdout, ، لكنه يتجاهل المحاذاة.سيؤدي تجميع هذا الرمز باستخدام استراتيجيات محاذاة مختلفة إلى مخرجات مختلفة.

أرفق إعلان الهيكل الخاص بك في #pragma pack(push, n) و #pragma pack(pop) لفرض المحاذاة، وقم فقط بنسخ البنية الخاصة بك بايت إلى بايت.

الأمر بسيط إلى حد ما:1.يأخذ ArrayBuild مؤشرًا إلى بنية msg_on_send، ولكل عضو هناك، يستخدم memcpy لنسخ البايتات إلى مصفوفة char التي تم تمريرها بهذه الطريقة -

char byteArray[17]; // This assumes 4-byte ints
                    // be careful though, the length *must* be long enough, or 
                    // Bad Things will happen
size_t msgSize; // Holds the size of the message built by ArrayBuild,
                // passed to USARTWrite
struct msg_on_send myMessage;
// Code to fill up myMessage appropriately

msgSize = ArrayBuild(byteArray, &myMessage); // need the & to pass a pointer as required

USARTWrite(myMessage, msgSize);

يتم إعطاء USARTWrite فقط مصفوفة char وحجمًا - فهو يلتقط كل حرف بدوره ويطبعه على الشاشة كقيمة سداسية عشرية باستخدام printf().

"السحر" موجود في ArrayBuild - يقوم memcpy بعمل نسخة حرفية من البايتات من المصدر إلى الوجهة، بدون ترجمة.بافتراض أن عدد ints ذو 4 بايت، فإن المصفوفة التي أنشأتها الدالة ستبدو كما يلي:

                     1 1 1 1 1 1 1 
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6
|   A     |   B   |C|    D    |E|F|

A = descriptor_msg (char[5])
B = address (int)
C = space (char)
D = cmdmsg (char[5])
E = CR (char)
F = LF (char)

أفترض أنه في التطبيق "الحقيقي"، سيتم استبدال استدعاء printf() بمكالمة لكتابة المنفذ التسلسلي.

مثال كامل كامل.يعمل بشكل مثالي.تم اختباره بموجب X-CODE 9 Objective-C

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

struct Person
{
    char name[20];
    int age;
};

int main()
{
    //structure variable declaratio with initialisation
    struct Person person={"Deniss Ritchie", 60};
    //declare character buffer (byte array)
    unsigned char *buffer=(char*)malloc(sizeof(person));
    int i;

    //copying....
    memcpy(buffer,(const unsigned char*)&person,sizeof(person));

    //printing..
    printf("Copied byte array is:\n");
    for(i=0;i<sizeof(person);i++)
        printf("%02X ",buffer[i]);
    printf("\n");

    //freeing memory..
    free(buffer);
    return 0;
}

انتاج:

Copied byte array is:
44 65 6E 69 73 73 20 52 69 74 63 68 69 65 00 00 00 00 00 00 3C 00 00 00
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top