Pregunta

Estoy intentando copiar a los miembros de una estructura que contiene una mezcla de int, char y matrices de caracteres en una matriz de bytes a enviar a una línea serie.Hasta ahora he

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

Como he obtenido este código, no entiendo bien cómo funciona.Puedo ver que el memcpy toma cada elemento de la estructura y la convierte en una serie de flujo de indexado por el 'yo' de la variable, pero no sé cómo la USARTWrite función packetises este en una cadena, o cómo cargar la matriz con mi estructura de inicialización.

Lo siento, este post es un poco largo, pero me estoy empezando esta programación alondra, y tratando de conseguir mi cabeza alrededor de este concepto.

Gracias Dave

EDITAR:

wow, muchas buenas respuestas rápidamente - gracias chicos.

slaz:Que me parece lógica, yo no había pensado realmente acerca de que el enfoque como yo realmente no tengo mi cabeza en torno a los punteros, pero estoy empezando a ver que ellos son una parte esencial de C, así que debidamente a echar un vistazo.

  • Esta línea de código se envía los datos a mi UART, ¿qué iba a reemplazar la matriz que contiene el contenido del mensaje con el?Parece que me falta un paso lógico aquí donde tengo una variable que me dice donde mi estructura se inicia y lo grande que es, pero no de la matriz a enviar

    USART_SendData(USART1, message_on_contents[array_count]);
    

Harper Shelby:Gracias por la descripción, se hace mucho más clara en mi mente.

rgds

Dave

¿Fue útil?

Solución

Lo siento, no vi tu comentario hasta ahora. El siguiente código se compila en Linux muy bien, así que espero que funcione para usted.
printf () está imprimiendo en hexadecimal, obtendrá 2 caracteres por cada 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;
}

Espero que esto ayude.

~
~

Otros consejos

No tiene que copiar la estructura en una matriz de bytes. Opcionalmente, puede hacer esto:

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

¡El poder de los punteros! :)

Si quiero tratar una estructura como una matriz de bytes, normalmente uso una unión para combinar la estructura con una matriz de bytes. Por ejemplo:

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

Su struct aquí es justo array de bytes, no contiene punteros que señalan de la misma.

Miembro-a-miembro de la copia es más probable que se realiza para hacer frente con la alineación, como (char*) &address probablemente será mayor que ((char*) &descriptor_msg) + 5.

USARTWrite envía HEX los códigos de los bytes de la estructura para stdout, pero descarta la alineación.La elaboración de este código con diferentes estrategias de alineación conducirán a diferentes salidas.

Adjunte a su declaración de estructura en #pragma pack(push, n) y #pragma pack(pop) a fuerza de alineación, y simplemente copiar su estructura byte-a-byte.

Es bastante sencillo: 1. ArrayBuild toma un puntero a una estructura msg_on_send, y para cada miembro allí, usa memcpy para copiar los bytes en una matriz de caracteres que se pasó de esta manera -

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 solo recibe una matriz de caracteres y un tamaño: toma cada carácter por turno y lo imprime en la pantalla como un valor hexadecimal con printf ().

La 'magia' está en ArrayBuild: memcpy realiza una copia literal de bytes desde el origen hasta el destino, sin traducción. Suponiendo entradas de 4 bytes, la matriz construida por la función se verá así:

                     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)

Supongo que en la aplicación 'real', la llamada printf () sería reemplazada por una llamada a una escritura de puerto serie.

Ejemplo completo completo. Funciona perfectamente Probado bajo 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;
}

Salida:

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
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top