Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. International
  3. Italian
  4. Streaming int32_t tramite union struct tra QT e STM32F4
Forum Updated to NodeBB v4.3 + New Features

Streaming int32_t tramite union struct tra QT e STM32F4

Scheduled Pinned Locked Moved Solved Italian
7 Posts 2 Posters 1.6k Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • lagodolioL Offline
    lagodolioL Offline
    lagodolio
    wrote on last edited by lagodolio
    #1

    Ho un problema con l'invio di dati tra QT e un micro STM32.
    Ho creato in QT ( e nel programma che correrà sul micro) una struttura:

    typedef struct
      {
       char start_char[1]; //1
       uint8_t  test;  //1
       int32_t  time_x;  //4
      } csv; 
    
    union assembl
      {
        csv csv_array;
        char buffer_csv[6];
      }
    united_data;
    

    A scopo di debug, ho inserito delle costanti nei campi della struttura che il micro invierà al pc :

    strcpy(united_data.csv_array.start_char,"q");    //only for testing
    united_data.csv_array.test=6;                //only for testing
    united_data.csv_array.time_x =3;             //only for testing
    

    e inviato i dati tramite la USART dell'STM:

    HAL_UART_Transmit(&huart2, (uint8_t*)united_data.buffer_csv, 6, 0xffff);
    
    

    I dati vengono correttamente ricevuti dal PC, ma per quanto riguarda la variabile int32_t non riesco ad avere un'interpretazione corretta.
    Sul fronte del controllore ho:

    Expression---------------------------Type---------Value
    united_data.buffer_csv---------------char[6] 
    united_data.buffer_csv[0]------------char--------113'q'
    united_data.buffer_csv[1]------------char--------6'\006\
    united_data.buffer_csv[2]------------char--------0'\0'
    united_data.buffer_csv[3]------------char--------0'\0'
    united_data.buffer_csv[4]------------char--------3'\003'
    united_data.buffer_csv[5]------------char--------0'\0'
    

    e il tutto viene letto correttamente da QT:

    Expression-------------------------Type	---------------	Value
    united_data.buffer_csv-------------char[6]	
    [0]--------------------------------char---------------'q' 113 0x71
    [1]--------------------------------char--------------- 6 0x06
    [2]--------------------------------char---------------	0'\0'
    [3]--------------------------------char---------------	0'\0'
    [4]--------------------------------char---------------	3'\003'
    [5]--------------------------------char---------------	0'\0'
    

    Il problema è che gli ultimi 32bit (united_data.buffer_csv[2...5] vengono interpretati in modo non corretto (o, meglio, non come vorrei io...):

    Details:"\0\0\003"
    Default:0x2001ffac
    Decimal:537001900
    Hex:0x2001ffac

    QT legge il valore int32_t di csv_array.time_x come "537001900" al posto di "3".
    Il fatto è che non ho ben capito come viene archiviata la variabile int32_t, non mi sembra LittleEndian e nemmeno BigEndian.
    Ho provato a modificare l'ordine ma senza risultato:

    ...
    [2]--------------------------------	char	---------------- 0'\0'
    [3]--------------------------------	char	---------------- 0'\0'
    [4]--------------------------------	char	---------------- 0'\0'
    [5]--------------------------------	char	---------------- 3'\003'
    
    

    Penso sia meglio "riorganizzare" i dati -ammesso che questa sia la strategia giusta - da PC ma forse mi sto perdendo in un bicchiere d'acqua...
    Grazie mille a tutti!

    1 Reply Last reply
    0
    • VRoninV Offline
      VRoninV Offline
      VRonin
      wrote on last edited by
      #2

      molto strano...
      prima cosa, potresti cambiare char buffer_csv[6]; in char buffer_csv[sizeof(csv)]; e poi provare a stampare il valore di united_data.buffer_csv dal lato STM32?

      "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
      ~Napoleon Bonaparte

      On a crusade to banish setIndexWidget() from the holy land of Qt

      1 Reply Last reply
      0
      • lagodolioL Offline
        lagodolioL Offline
        lagodolio
        wrote on last edited by
        #3

        Ciao e grazie per la risposta.
        Inizialmente avevo definito la dimensione del buffer proprio con un sizeof e in QT continuo a seguire questa strada. Il problema con atollic (quindi sul micro) è che non riesco a fargli "digerire" il #pragma pack(), quindi mi ritrovo con un valore per la lunghezza pari a 8byte (contro i 6byte risultanti da due variabili 8 bit e una 32bit->48bit=6byte).
        Leggendo il valore della variabile (fissando la lunghezza del buffer pari a 8 byte-64bit-) avevo -sul micro-:

        Expression---------------------------Type---------Value
        united_data.buffer_csv---------------char[6] 
        united_data.buffer_csv[0]------------char--------113'q'
        united_data.buffer_csv[1]------------char--------6'\006\
        united_data.buffer_csv[2]------------char--------0'\0'
        united_data.buffer_csv[3]------------char--------0'\0'
        united_data.buffer_csv[4]------------char--------3'\003'
        united_data.buffer_csv[5]------------char--------0'\0'
        united_data.buffer_csv[6]------------char--------0'\0'
        united_data.buffer_csv[7]------------char--------0'\0'
        

        Name : united_data.buffer_csv
        Details:"q\006\0\0\003\0\0"
        Default:0x2000024c <united_data>
        Decimal:536871500
        Hex:0x2000024c
        Binary:100000000000000000001001001100
        Octal:04000001114

        mentre ora, con la lunghezza fissata a 6 -48 bit-, ho il risultato (sempre sul micro) troncato al valore [5]:

        Name : united_data.buffer_csv
        Details:"q\006\0\0\003"
        Default:0x2000024c <united_data>
        Decimal:536871500
        Hex:0x2000024c
        Binary:100000000000000000001001001100
        Octal:04000001114

        Non capisco perché i valori siano 3.75 byte in entrambi i casi (30bit)!
        Sinceramente mi sarei aspettato un binario del tipo

        |---113---|----6-----|----------------------3-------------------|
        01110001 00000110 00000000 00000000 00000000 00000011

        ma evidentemente sbaglio io visto che QT legge i primi due dati da 8 bit correttamente.
        Ho come l'impressione che l'allineamento sulla struttura lasci dentro dei "pad " un po' a caso, ma si tratta di un'impressione, appunto. Chissà che lavorando sul #pragma pack() potrei chiarirmi il dubbio ma forse sono su una strada sbagliata...
        Buona giornata a tutti e a presto!

        VRoninV 1 Reply Last reply
        0
        • lagodolioL lagodolio

          Ciao e grazie per la risposta.
          Inizialmente avevo definito la dimensione del buffer proprio con un sizeof e in QT continuo a seguire questa strada. Il problema con atollic (quindi sul micro) è che non riesco a fargli "digerire" il #pragma pack(), quindi mi ritrovo con un valore per la lunghezza pari a 8byte (contro i 6byte risultanti da due variabili 8 bit e una 32bit->48bit=6byte).
          Leggendo il valore della variabile (fissando la lunghezza del buffer pari a 8 byte-64bit-) avevo -sul micro-:

          Expression---------------------------Type---------Value
          united_data.buffer_csv---------------char[6] 
          united_data.buffer_csv[0]------------char--------113'q'
          united_data.buffer_csv[1]------------char--------6'\006\
          united_data.buffer_csv[2]------------char--------0'\0'
          united_data.buffer_csv[3]------------char--------0'\0'
          united_data.buffer_csv[4]------------char--------3'\003'
          united_data.buffer_csv[5]------------char--------0'\0'
          united_data.buffer_csv[6]------------char--------0'\0'
          united_data.buffer_csv[7]------------char--------0'\0'
          

          Name : united_data.buffer_csv
          Details:"q\006\0\0\003\0\0"
          Default:0x2000024c <united_data>
          Decimal:536871500
          Hex:0x2000024c
          Binary:100000000000000000001001001100
          Octal:04000001114

          mentre ora, con la lunghezza fissata a 6 -48 bit-, ho il risultato (sempre sul micro) troncato al valore [5]:

          Name : united_data.buffer_csv
          Details:"q\006\0\0\003"
          Default:0x2000024c <united_data>
          Decimal:536871500
          Hex:0x2000024c
          Binary:100000000000000000001001001100
          Octal:04000001114

          Non capisco perché i valori siano 3.75 byte in entrambi i casi (30bit)!
          Sinceramente mi sarei aspettato un binario del tipo

          |---113---|----6-----|----------------------3-------------------|
          01110001 00000110 00000000 00000000 00000000 00000011

          ma evidentemente sbaglio io visto che QT legge i primi due dati da 8 bit correttamente.
          Ho come l'impressione che l'allineamento sulla struttura lasci dentro dei "pad " un po' a caso, ma si tratta di un'impressione, appunto. Chissà che lavorando sul #pragma pack() potrei chiarirmi il dubbio ma forse sono su una strada sbagliata...
          Buona giornata a tutti e a presto!

          VRoninV Offline
          VRoninV Offline
          VRonin
          wrote on last edited by
          #4

          @lagodolio said in Streaming int32_t tramite union struct tra QT e STM32F4:

          non riesco a fargli "digerire" il #pragma pack(),

          Questo e' il problema. Non e' che modificando la dimensione del buffer l'allineamento si risolva magicamente.

          Rimuovi la union completamente e salva i dati su char[] manualmente:

          typedef struct
            {
             char start_char[1]; //1
             uint8_t  test;  //1
             int32_t  time_x;  //4
            } csv;
          csv data;
          data.start_char[0]='q';
          data.test=6;
          data.time_x =3; 
          uint8_t buffer_csv[6];
          memcpy(buffer_csv,data.start_char,1);
          memcpy(buffer_csv+1,&data.test,1);
          memcpy(buffer_csv+2,&data.time_x,4);
          HAL_UART_Transmit(&huart2, buffer_csv, 6, 0xffff);
          

          Dovresti pero' anche assicurarti che data.time_x sia trasmesso sempre in big endian visto che e' la convenzione usata da quasi tutti i protocolli di comunicazione

          "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
          ~Napoleon Bonaparte

          On a crusade to banish setIndexWidget() from the holy land of Qt

          1 Reply Last reply
          0
          • lagodolioL Offline
            lagodolioL Offline
            lagodolio
            wrote on last edited by
            #5

            Ho provato a modificare il tipo di variabili.
            Premessa, STM32 TrueSTUDIO (Atollic) usa la codifica LittleEndian.
            Ho provato a impostare l'ultima variabile come uint16_t, ho definito il suo valore pari a 30000 (quindi >8bit) e QT non ha fatto una piega, riportando il valore corretto. Idem con int16_t e "-30000".
            Ho poi provato con uint32_t ( e 130000 come valore) e qui sono cominciati i dolori.
            I valori registrati in united_data.buffer_csv[2...5] sono:
            united_data.buffer_csv[2]=0x00
            united_data.buffer_csv[3]=0x00
            united_data.buffer_csv[4]=0xD0
            united_data.buffer_csv[5]=0xFB

            Quindi un valore di 32bit sarà:

            0x0000FBD0 =64464

            dovrei avere,invece

            0x0001FBD0=130000!

            1 Reply Last reply
            0
            • lagodolioL Offline
              lagodolioL Offline
              lagodolio
              wrote on last edited by
              #6

              RISOLTO!
              Alla fine il problema era proprio nel #pragma !
              E' stato sufficiente inserire :

              #pragma pack(1)
              typedef struct
              {
               char start_char[1]; //1
               uint8_t  test;  //1
               int32_t  time_x;  //4
              } csv; 
              
              union assembl
              {
                csv csv_array;
                char buffer_csv[sizeof(csv)];
              }
              united_data;
              

              Il mio problema era che , per errore, avevo messo il #pragma dopo la struttura (avevo visto così in un esempio e avevo pensato che atollic volesse questa istruzione DOPO la struttura da allineare) e prima della union: quindi non allineava niente!
              Adesso ho:
              united_data.buffer_csv[2]=0xD0
              united_data.buffer_csv[3]=0xFB
              united_data.buffer_csv[4]=0x01
              united_data.buffer_csv[5]=0x0.

              Sembra che QT "capisca" che stiamo trattando LittleEndian (gli ARM dovrebbero usare questa convenzione, o almeno gli STM32 lo fanno) e riporta i dati correttamente!!
              Grazie mille , in effetti mi hai convinto sul fatto che con un allineamento "non allineato" non potevo andare lontano...
              Buona Giornata e grazie ancora!

              VRoninV 1 Reply Last reply
              0
              • lagodolioL lagodolio

                RISOLTO!
                Alla fine il problema era proprio nel #pragma !
                E' stato sufficiente inserire :

                #pragma pack(1)
                typedef struct
                {
                 char start_char[1]; //1
                 uint8_t  test;  //1
                 int32_t  time_x;  //4
                } csv; 
                
                union assembl
                {
                  csv csv_array;
                  char buffer_csv[sizeof(csv)];
                }
                united_data;
                

                Il mio problema era che , per errore, avevo messo il #pragma dopo la struttura (avevo visto così in un esempio e avevo pensato che atollic volesse questa istruzione DOPO la struttura da allineare) e prima della union: quindi non allineava niente!
                Adesso ho:
                united_data.buffer_csv[2]=0xD0
                united_data.buffer_csv[3]=0xFB
                united_data.buffer_csv[4]=0x01
                united_data.buffer_csv[5]=0x0.

                Sembra che QT "capisca" che stiamo trattando LittleEndian (gli ARM dovrebbero usare questa convenzione, o almeno gli STM32 lo fanno) e riporta i dati correttamente!!
                Grazie mille , in effetti mi hai convinto sul fatto che con un allineamento "non allineato" non potevo andare lontano...
                Buona Giornata e grazie ancora!

                VRoninV Offline
                VRoninV Offline
                VRonin
                wrote on last edited by VRonin
                #7

                @lagodolio said in Streaming int32_t tramite union struct tra QT e STM32F4:

                Sembra che QT "capisca" che stiamo trattando LittleEndian

                Dipende da cosa usi per leggere. Se usi QDataStream devi manualmente impostarlo su little endian, se leggi i dati grezzi usano la convenzione imposta dalla macchina su cui esegui il programma

                "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
                ~Napoleon Bonaparte

                On a crusade to banish setIndexWidget() from the holy land of Qt

                1 Reply Last reply
                0

                • Login

                • Login or register to search.
                • First post
                  Last post
                0
                • Categories
                • Recent
                • Tags
                • Popular
                • Users
                • Groups
                • Search
                • Get Qt Extensions
                • Unsolved