Question

J'essaie de copier les membres d'une structure contenant un mélange d'ints, de caractères et de tableaux de caractères dans un tableau d'octets à envoyer à une ligne série. Jusqu'ici j'ai

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

Après avoir obtenu ce code, je ne comprends pas très bien comment cela fonctionne. Je peux voir que le memcpy prend chaque élément de la structure et en fait un flux série indexé par la variable 'i', mais je ne sais pas comment la fonction USARTWrite en paquets la dans une chaîne, ni comment charger le tableau avec mon initialisation de la structure.

Désolé, ce billet est un peu long, mais je commence tout juste cette programmation, et j'essaie de comprendre ce concept.

Merci Dave

EDIT:

wow, beaucoup de bonnes réponses rapidement - merci les gars.

slaz: Cela me semble logique, je n’avais pas vraiment réfléchi à cette approche car je ne connaissais pas encore très bien les indicateurs, mais je commence à voir qu’ils sont une partie essentielle de C, alors je dûment jeté un coup d'oeil.

  • Cette ligne de code envoie les données à mon UART. Avec quoi pourrais-je remplacer le tableau contenant le contenu du message? Il semble que je manque une étape logique ici où j'ai une variable qui me dit où commence ma structure et quelle est sa taille, mais pas de tableau à envoyer

    USART_SendData(USART1, message_on_contents[array_count]);
    

Harper Shelby: Merci pour cette description, cela rend les choses beaucoup plus claires dans mon esprit.

rgds

Dave

Était-ce utile?

La solution

Désolé, je n'ai pas vu votre commentaire jusqu'à maintenant. Le code ci-dessous est parfaitement compilé sous Linux. J'espère que cela fonctionnera pour vous.
printf () imprime en hexadécimal, vous obtiendrez 2 caractères pour chaque octet.

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

J'espère que cela vous aidera.

~
~

Autres conseils

Il n'est pas nécessaire de copier la structure dans un tableau d'octets. Vous pouvez éventuellement faire ceci:

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

Le pouvoir des pointeurs! :)

Si je veux traiter une structure comme un tableau d'octets, j'utilise généralement une union pour combiner la structure avec un tableau d'octets. Par exemple:

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

Votre struct ici est juste un tableau d'octets, il ne contient aucun pointeur qui le pointe.

La copie d'un membre à l'autre est généralement effectuée pour faire face à l'alignement, car (char*) &address sera probablement supérieur à ((char*) &descriptor_msg) + 5.

USARTWrite envoie HEX les codes des octets de votre structure à stdout, mais ignore l'alignement. La compilation de ce code avec différentes stratégies d’alignement mènera à différents résultats.

Placez votre déclaration de structure entre #pragma pack(push, n) et #pragma pack(pop) pour forcer l'alignement. Copiez simplement votre structure, octet par octet.

C'est assez simple: 1. ArrayBuild prend un pointeur sur une structure msg_on_send et, pour chaque membre de celui-ci, utilise memcpy pour copier les octets dans un tableau de caractères qui a été transmis comme suit -

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 reçoit juste un tableau de caractères et une taille - il saisit chaque caractère à tour de rôle et l’affiche à l’écran sous forme de valeur hexadécimale avec printf ().

La "magie" est dans ArrayBuild - memcpy effectue une copie littérale d'octets de la source à la destination, sans traduction. En supposant des ints de 4 octets, le tableau construit par la fonction ressemblera à ceci:

                     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)

Je suppose que dans l'application "réelle", l'appel printf () serait remplacé par un appel à une écriture sur port série.

Exemple complet complet. Fonctionne parfaitement. Testé sous 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;
}

Sortie:

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
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top