Pergunta

estou a tentar copiar os membros de uma estrutura que contém uma mistura de ints, carvão animal de matrizes e de caracteres em uma matriz de bytes para enviar para uma linha serial. Até agora eu tenho

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 eu obter esse código, eu não totalmente compreender como ele funciona. Eu posso ver que a memcpy leva cada elemento da estrutura e torna-lo em um fluxo de série indexada pela variável 'i', mas eu não sei como a função USARTWrite packetises isso em uma corda, ou como carregar a matriz com meu struct inicialização.

Infelizmente este post é um pouco longo, mas eu estou apenas começando esta cotovia programação, e tentando colocar minha cabeça em torno deste conceito.

Graças Dave

EDIT:

wow, muitas boas respostas rapidamente -. Obrigado rapazes

slaz: Isso parece lógico para mim, eu realmente não tinha pensado sobre essa abordagem como eu realmente não tenho a minha cabeça em torno de ponteiros ainda, mas estou começando a ver que eles são uma parte essencial de C, então eu devidamente terá um olhar.

  • Esta linha de código envia os dados para o meu UART, o que eu substituir a matriz que contém o conteúdo da mensagem com? Parece que eu estou em falta um passo lógico aqui onde eu tenho uma variável a dizer-me onde meus estrutura começa e quão grande ele é, mas nenhuma matriz para enviar

    USART_SendData(USART1, message_on_contents[array_count]);
    

Harper Shelby: Obrigado por essa descrição, torna-se muito mais clara em minha mente

.

rgds

Dave

Foi útil?

Solução

Desculpe, eu não vi o seu comentário até agora. O código a seguir compila em Linux muito bem, então eu espero que ele funciona para você.
printf () está imprimindo em hexadecimal, você vai ter 2 caracteres para 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 isso ajude.

~
~

Outras dicas

Você não tem que realmente copiar a estrutura em uma matriz de bytes. Você pode, opcionalmente, faça o seguinte:

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

O poder de ponteiros! :)

Se quer para tratar uma estrutura como uma matriz de bytes que tipicamente utilizam uma união para a estrutura combinada com uma matriz de bytes. Por exemplo:

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

Seu struct aqui é apenas matriz de bytes, não contém indicações que ponto fora dele.

Membro-a-membro cópia é provavelmente realizada para lidar com o alinhamento, como (char*) &address provavelmente vai ser maior do que ((char*) &descriptor_msg) + 5.

USARTWrite envia códigos HEX dos bytes de sua estrutura para stdout, mas devoluções alinhamento. Compilar esse código com diferentes estratégias de alinhamento vai levar a diferentes saídas.

Coloque sua declaração de estrutura em #pragma pack(push, n) e #pragma pack(pop) ao alinhamento força, e apenas copiar a estrutura do byte-a-byte.

É bastante simples: 1. ArrayBuild leva um ponteiro para uma estrutura msg_on_send, e para cada um dos membros em ali, usos memcpy para copiar os bytes em uma matriz de char que foi passado em modo como -

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 é apenas dada uma matriz de caracteres e um tamanho - que agarra cada caractere por sua vez, e imprime-a no ecrã como um valor hexadecimal com printf ()

.

A 'magia' está na ArrayBuild - memcpy faz uma cópia literal de bytes da origem para o destino, sem tradução. Assumindo ints de 4 bytes, a matriz construída pela função será parecido com isso:

                     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)

Eu supor que na aplicação 'real', a chamada printf () seria substituída por uma chamada para uma gravação de porta serial.

exemplo completo completa. Funciona perfeitamente. Testado sob X-CÓDIGO 9 Objectivo-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
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top