Domanda

Sto tentando di copiare i membri di uno struct contenente una combinazione di ints, char e array di caratteri in un array di byte da inviare a una linea seriale. Finora ho

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');
}

Quando ho ottenuto questo codice, non capisco completamente come funziona. Vedo che memcpy prende ogni elemento della struttura e lo trasforma in un flusso seriale indicizzato dalla variabile 'i', ma non so come la funzione USARTWrite lo comprime in una stringa o come caricare l'array con la mia inizializzazione strutt.

Mi dispiace che questo post sia un po 'lungo, ma sto solo cominciando questo scherzo di programmazione, e sto cercando di farmi un'idea di questo concetto.

Grazie Dave

EDIT:

wow, molte buone risposte rapidamente - grazie ragazzi.

slaz: Mi sembra logico, non avevo davvero pensato a quell'approccio dato che non ho ancora avuto la testa intorno ai puntatori, ma sto cominciando a vedere che sono una parte essenziale di C, quindi io dovremo dare un'occhiata.

  • Questa riga di codice invia i dati al mio UART, con cosa sostituirei l'array contenente il contenuto del messaggio? Sembra che qui manchi un passaggio logico in cui ho una variabile che mi dice dove inizia la mia struttura e quanto è grande, ma nessun array da inviare

    USART_SendData(USART1, message_on_contents[array_count]);
    

Harper Shelby: Grazie per quella descrizione, mi rende molto più chiaro nella mia mente.

rgds

Dave

È stato utile?

Soluzione

Mi dispiace, non ho visto il tuo commento fino ad ora. Il codice seguente si compila su Linux bene, quindi spero che funzioni per te.
printf () sta stampando in esadecimale, otterrai 2 caratteri per ogni byte.

#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;
}

Spero che questo aiuti.

~
~

Altri suggerimenti

Non è necessario copiare la struttura in una matrice di byte. Opzionalmente puoi farlo:

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));

Il potere dei puntatori! :)

Se voglio trattare una struttura come una matrice di byte, in genere uso un'unione per combinare la struttura con una matrice di byte. Ad esempio:

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

Il tuo struct qui è solo un array di byte, non contiene puntatori che lo indicano.

La copia da membro a membro viene probabilmente eseguita per far fronte all'allineamento, poiché (char*) &address sarà probabilmente maggiore di ((char*) &descriptor_msg) + 5.

USARTWrite invia HEX codici dei byte della struttura a stdout, ma scarta l'allineamento. Compilare questo codice con diverse strategie di allineamento porterà a risultati diversi.

Racchiudi la tua dichiarazione di struttura in #pragma pack(push, n) e #pragma pack(pop) per forzare l'allineamento e copia semplicemente la tua struttura byte-to-byte.

È abbastanza semplice: 1. ArrayBuild prende un puntatore a una struttura msg_on_send e, per ogni membro presente, usa memcpy per copiare i byte in un array di caratteri che è stato passato in questo modo -

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 ha appena ricevuto un array di caratteri e una dimensione: prende ogni carattere a sua volta e lo stampa sullo schermo come valore esadecimale con printf ().

La 'magia' è in ArrayBuild - memcpy esegue una copia letterale di byte dall'origine alla destinazione, senza traduzione. Supponendo che 4 byte, l'array creato dalla funzione sarà simile al seguente:

                     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)

Suppongo che nell'applicazione 'reale', la chiamata printf () sarebbe sostituita da una chiamata a una scrittura su porta seriale.

Esempio completo completo. Funziona perfettamente. Testato sotto 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;
}

Output:

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
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top