Buffer mise en forme

Bonjour à tous,

Je me heurte à un petit problème et j’arrive pas à trouver la solution.
Je possède un tableau qui ressemble à ca:

static const unsigned char model[38870UL + 1] = {
  0x00, 0x08, 0x00, 0x20, 0x89, 0x96, 0x00, 0x00, 0x25, 0x53, 0x00, 0x00, 0x2D, 0x53,.............

J’aimerais envoyer ce tableau par buffer de 56 avec le code suivant:

  uint32_t taille = 560;
  unsigned char memarea[56];
  for (int i = 0; i < taille / 56; i++) {
    for (int j = 0; j < 56; j++) {
      memarea[j] = model[i * 56 + j];
      Serial.print(memarea[j],HEX);
    }
    Serial.println();
  }

Mais il m’affiche le résultat suivant:

080208996002553002D53003553003D53

En fait, j’aimerais qu’il m’affiche 000800208996 mais il m’affiche 0 pour 00 et 8 pour 08 etc…
J’ai essayé un sprintf: sprintf(memarea[j],"%02u",model[i * 56 + j]);

Mais ca fonctionne pas… avez vous une idée pour que j’affiche entièrement, sur 2 octets la vraie valeur “08” au lieu de “8” etc…

Merci de votre aide !

Quel Arduino avez vous? C’est un gros tableau!

votre code est incomplet on ne sait pas ce que vous faites. postez un sketch complet

Vous n’avez pas besoin de buffer intermédiaire en faisant un

Serial.write(&(model[indice]), 56);

vous émettez 56 octets sur le port série. Il suffit ensuite d’incrémenter indice de 56 en 56 jusqu’à la fin du tableau et pour la dernière émission envoyer le reste (si vous n’avez pas un multiple de 56). En faisant comme cela vous envoyez du binaire, cela dit.

Si vous voulez imprimer la représentation de chaque octet en ascii alors un parcours du grand tableau suffit, je ne vois pas non plus à quoi sert le buffer intermédiaire

voici cependant un bout de code qui fait un peu ce que vous voulez

const uint8_t grosBuffer[] = {
  0x00, 0x08, 0x00, 0x20, 0x89, 0x96, 0x00, 0x00, 0x25, 0x53,   // 10 données
  0x01, 0x08, 0x00, 0x20, 0x89, 0x96, 0x00, 0x00, 0x25, 0x53,
  0x02, 0x08, 0x00, 0x20, 0x89, 0x96, 0x00, 0x00, 0x25, 0x53,
  0x03, 0x08, 0x00, 0x20, 0x89, 0x96, 0x00, 0x00, 0x25, 0x53,
  0x04, 0x08, 0x00, 0x20, 0x89, 0x96, 0x00, 0x00, 0x25, 0x53,
  0x05, 0x08, 0x00, 0x20, 0x89, 0x96, 0x00, 0x00, 0x25, 0x53,
  0x06, 0x08, 0x00, 0x20, 0x89, 0x96, 0x00, 0x00, 0x25, 0x53,
  0x07, 0x08, 0x00, 0x20, 0x89, 0x96, 0x00, 0x00, 0x25, 0x53,
  0x08, 0x08, 0x00, 0x20, 0x89, 0x96, 0x00, 0x00, 0x25, 0x53,
  0x09, 0x08, 0x00, 0x20, 0x89, 0x96, 0x00, 0x00, 0x25, 0x53,
  0x0A, 0x08, 0x00, 0x20, 0x89, 0x96, 0x00, 0x00, 0x25, 0x53,
  0x0B, 0x08, 0x00, 0x20, 0x89, 0x96, 0x00, 0x00, 0x25, 0x53,
  0x0C, 0x08, 0x00, 0x20, 0x89, 0x96, 0x00, 0x00, 0x25, 0x53,
  0x0D, 0x08, 0x00, 0x20, 0x89, 0x96, 0x00, 0x00, 0x25, 0x53,
  0x0E, 0x08, 0x00, 0x20, 0x89, 0x96, 0x00, 0x00, 0x25, 0x53,
  0x0F, 0x08, 0x00, 0x20, 0x89, 0x96,                           // dernière ligne incomplète pour démonstration
};
const size_t dimension = sizeof grosBuffer / sizeof grosBuffer[0];
const size_t decoupage = 10;

void setup() {
  Serial.begin(115200);
  // on imprime par buffer de taille decoupage
  for (size_t i = 0; i < dimension / decoupage; i++) {
    uint8_t bufferTemporaireInutile[decoupage];
    for (size_t j = 0; j < decoupage; j++) {
      bufferTemporaireInutile[j] = grosBuffer[decoupage * i + j];
      Serial.print(F("0x"));
      if (bufferTemporaireInutile[j] < 16) Serial.write('0');
      Serial.print(bufferTemporaireInutile[j], HEX);
      if (j != decoupage - 1) Serial.print(F(", "));
      else Serial.println();
    }
  }

  // il reste peut être un bout qu'on n'a pas imprimé
  size_t resteNonTraite = dimension % decoupage;
  if (resteNonTraite != 0) {
    uint8_t bufferTemporaireInutile[decoupage];
    for (size_t j = 0; j < resteNonTraite; j++) {
      bufferTemporaireInutile[j] = grosBuffer[decoupage * (dimension / decoupage) + j];
      Serial.print(F("0x"));
      if (bufferTemporaireInutile[j] < 16) Serial.write('0');
      Serial.print(bufferTemporaireInutile[j], HEX);
      if (j != resteNonTraite - 1) Serial.print(F(", "));
      else Serial.println();
    }
  }
}

void loop() {}

le moniteur série (à 115200 bauds) affichera

[color=purple]
0x00, 0x08, 0x00, 0x20, 0x89, 0x96, 0x00, 0x00, 0x25, 0x53
0x01, 0x08, 0x00, 0x20, 0x89, 0x96, 0x00, 0x00, 0x25, 0x53
0x02, 0x08, 0x00, 0x20, 0x89, 0x96, 0x00, 0x00, 0x25, 0x53
0x03, 0x08, 0x00, 0x20, 0x89, 0x96, 0x00, 0x00, 0x25, 0x53
0x04, 0x08, 0x00, 0x20, 0x89, 0x96, 0x00, 0x00, 0x25, 0x53
0x05, 0x08, 0x00, 0x20, 0x89, 0x96, 0x00, 0x00, 0x25, 0x53
0x06, 0x08, 0x00, 0x20, 0x89, 0x96, 0x00, 0x00, 0x25, 0x53
0x07, 0x08, 0x00, 0x20, 0x89, 0x96, 0x00, 0x00, 0x25, 0x53
0x08, 0x08, 0x00, 0x20, 0x89, 0x96, 0x00, 0x00, 0x25, 0x53
0x09, 0x08, 0x00, 0x20, 0x89, 0x96, 0x00, 0x00, 0x25, 0x53
0x0A, 0x08, 0x00, 0x20, 0x89, 0x96, 0x00, 0x00, 0x25, 0x53
0x0B, 0x08, 0x00, 0x20, 0x89, 0x96, 0x00, 0x00, 0x25, 0x53
0x0C, 0x08, 0x00, 0x20, 0x89, 0x96, 0x00, 0x00, 0x25, 0x53
0x0D, 0x08, 0x00, 0x20, 0x89, 0x96, 0x00, 0x00, 0x25, 0x53
0x0E, 0x08, 0x00, 0x20, 0x89, 0x96, 0x00, 0x00, 0x25, 0x53
0x0F, 0x08, 0x00, 0x20, 0x89, 0x96

[/color]

donc on voit bien toutes nos données (le premier octet s’incrémente, les autres sont tous les mêmes par flemme dans mon copier coller)

Notre ami ne veut pas impriner 0x00, ni 0, il veut 00
C'est bizarre, sprintf() devrait marcher ? A moins que la libC Arduino n'ait fait quelques coupes sombres ...
Ca sort quoi avec sprintf() ?

biggil:
Notre ami ne veut pas impriner 0x00,

oui il suffit d’enlever leSerial.print(F("0x"));de mon exemple et les virgules de séparation et le retour à la ligne. c’était pour l’exemple.

quand on Print un octet en HEX, si on a que 1 seul chiffre significatif, on n’a pas le 0 devant

donc son 0x0[color=red]0[/color], 0x0[color=red]8[/color], 0x0[color=red]0[/color], 0x[color=red]20[/color], 0x[color=red]89[/color]... va imprimer [color=red]0802089...[/color] ce qui est bien ce qui est vu

si on veut toujours 2 caractères il faut tester si on n’a qu’un seul digit et dans ce cas écrire soit même le ‘0’ sur la console avant d’écrire le chiffre lui même en Hexa, ce que je fais dans mon code avec

      if (bufferTemporaireInutile[j] < 16) Serial.write('0');
      Serial.print(bufferTemporaireInutile[j], HEX);

“%02u” n’est pas adapté pour de l’hexadécimal. Avec sprintf() et le formatage “%02X” ça donne cela:

const uint8_t grosBuffer[] = {
  0x00, 0x08, 0x00, 0x20, 0x89, 0x96, 0x00, 0x00, 0x25, 0x53,   // 10 données
  0x01, 0x08, 0x00, 0x20, 0x89, 0x96, 0x00, 0x00, 0x25, 0x53,
  0x02, 0x08, 0x00, 0x20, 0x89, 0x96, 0x00, 0x00, 0x25, 0x53,
  0x03, 0x08, 0x00, 0x20, 0x89, 0x96, 0x00, 0x00, 0x25, 0x53,
  0x04, 0x08, 0x00, 0x20, 0x89, 0x96, 0x00, 0x00, 0x25, 0x53,
  0x05, 0x08, 0x00, 0x20, 0x89, 0x96, 0x00, 0x00, 0x25, 0x53,
  0x06, 0x08, 0x00, 0x20, 0x89, 0x96, 0x00, 0x00, 0x25, 0x53,
  0x07, 0x08, 0x00, 0x20, 0x89, 0x96, 0x00, 0x00, 0x25, 0x53,
  0x08, 0x08, 0x00, 0x20, 0x89, 0x96, 0x00, 0x00, 0x25, 0x53,
  0x09, 0x08, 0x00, 0x20, 0x89, 0x96, 0x00, 0x00, 0x25, 0x53,
  0x0A, 0x08, 0x00, 0x20, 0x89, 0x96, 0x00, 0x00, 0x25, 0x53,
  0x0B, 0x08, 0x00, 0x20, 0x89, 0x96, 0x00, 0x00, 0x25, 0x53,
  0x0C, 0x08, 0x00, 0x20, 0x89, 0x96, 0x00, 0x00, 0x25, 0x53,
  0x0D, 0x08, 0x00, 0x20, 0x89, 0x96, 0x00, 0x00, 0x25, 0x53,
  0x0E, 0x08, 0x00, 0x20, 0x89, 0x96, 0x00, 0x00, 0x25, 0x53,
  0x0F, 0x08, 0x00, 0x20, 0x89, 0x96,                           // dernière ligne incomplète pour démonstration
};
const size_t dimension = sizeof grosBuffer / sizeof grosBuffer[0];
const size_t decoupage = 10;

void setup() {
  Serial.begin(115200);
  // on imprime par buffer de taille decoupage
  for (size_t i = 0; i < dimension / decoupage; i++) {
    uint8_t bufferTemporaireInutile[decoupage];
    for (size_t j = 0; j < decoupage; j++) {
      bufferTemporaireInutile[j] = grosBuffer[decoupage * i + j];
      char bufferAffichage[5]; // 3 est suffisant pour un octet en HEX
      Serial.print(F("0x"));
      sprintf(bufferAffichage, "%02X", bufferTemporaireInutile[j]);
      Serial.print(bufferAffichage);
      if (j != decoupage - 1) Serial.print(F(", "));
      else Serial.println();
    }
  }

  // il reste peut être un bout qu'on n'a pas imprimé
  size_t resteNonTraite = dimension % decoupage;
  if (resteNonTraite != 0) {
    uint8_t bufferTemporaireInutile[decoupage];
    for (size_t j = 0; j < resteNonTraite; j++) {
      bufferTemporaireInutile[j] = grosBuffer[decoupage * (dimension / decoupage) + j];
      char bufferAffichage[3];
      Serial.print(F("0x"));
      sprintf(bufferAffichage, "%02X", bufferTemporaireInutile[j]);
      Serial.print(bufferAffichage);
      if (j != resteNonTraite - 1) Serial.print(F(", "));
      else Serial.println();
    }
  }
}

void loop() {}

et on a la même chose sur la console série

J-M-L:
"%02u" n'est pas adapté pour de l'hexadécimal. Avec sprintf() et le formatage "%02X"

Mais où avais-je la tête ?

Effectivement c'est un gros tableau, c'est un firmware pour un autre micro..

L'idée est d'embarquer un FW pour stm32 sur un esp8266. Je met à jour l'esp8266 en FOTA qui contient le FW pour mon stm32 sous forme de tableau et je lui balance après en uart.

Tout fonctionne mais je suis super nase en déclaration de variable que je me panique vite et me dis j'y arriverai pas... Si vous avez des tutos pour savoir quand utiliser int, uint8 etc.... Je suis une vraie catastrophe..
J'ai complètement bug dessus mais maintenant ca fonctionne beaucoup mieux, je te remercie beaucoup ! ton code est 100X plus propre que le miens ahahah

L'exemple en sprintf fonctionne bien mieux avec le bon formatage...

Merci, à vous!

uint8_t c'est un type de base qui veut dire 1 octet, sous forme d'entier non signé. c'est un peu tout ce qu'il y a à savoir dessus... c'est le type le plus utilisé quand on manipule du binaire.

Je suppose que quand vous poussez votre tableau vers votre stm32 vous ne l'envoyez pas en ASCII, mais en binaire ?

Je le pousse en ASCII :slight_smile: (enfin je dois envoyer des caractères que je convertis en ASCII)
En fait, le bootloader coté STM32 est bien foutu, j'ai juste fais du reverse pour matcher avec et ca fonctionne bien :slight_smile:

uint8_t est 1 octet, ca va, mais quand je commence à voir des truc du style:

[color=#d4d4d4]checksum_computed == *(([color=#569cd6]uint32_t[/color] *) max[/color]

j'y comprend plus rien ahah.

Je suis entrain de créer mon switch case pour réaliser l'envoi du FW en sécurité, acquire, répétitions si non reçu etc...

Si ca vous intéresse je partage surtout que j'ai trouvé un petit soft pour esp8266 pour faire une MaJ FOTA depuis github :slight_smile:

comprendre cela n'est pas super compliqué, il faut procéder avec méthode:

checksum_computed [color=purple]==[/color] [color=red]*[/color]([color=blue](uint32_t *)[/color] max);

on commence par regarder l'expression: c'est une comparaison puisqu'on a ==

le côté gauche de l'expression est simple, on comparera le contenu de la variable checksum_computed avec ce qui est de l'autre côté du ==

de l'autre côté il y a des parenthèses. Donc on commence par ce qui est au coeur de parenthèses:

  • c'est un cast (changement de type): On dit donc que le contenu de la variable max doit être interprété par le compilateur comme un pointeur sur une variable non signée qui occupe 4 octets (uint32_t *) (donc en gros max est une adresse en mémoire d'un processeur 32 bits).

Ensuite on suit l'indirection (déréférencement) * qui nous dit donc d'aller lire le contenu pointé par ce pointeur. Comme le pointeur pointe sur 4 octets, ce déréférencement lit les 4 octets stockés à l'adresse mémoire renseignée dans max.

on a maintenant une valeur des 2 côtés, le compilateur peut effectuer la comparaison et retourne vrai ou faux (true ou false) en fonction de l'égalité des 2 valeurs

Si vous voulez en savoir plus, j'ai un tuto intitulé: Introduction à la mémoire et aux pointeurs sur Arduino

Maxvi33:
Je le pousse en ASCII :slight_smile: (enfin je dois envoyer des caractères que je convertis en ASCII)

Les éléments que tu veux envoyer sont des octets.
Si tu les envoies en binaire, il passent tels quels sur la ligne. 1 octet par élément.
Si tu envoies en ascii, et en codage héxadécimal, , chaque élément (octet) est traduit par 2 caractères héxa. Sur la ligne passent 2 octets (2caractères) par élément (octet) à transférer. (et plus si tu ajoutes des virgules ou des espaces)
Si tu envoies en ascii, et en codage décimal, , chaque élément (octet) est traduit par 1 à 4 caractères (par ex: -127). Sur la ligne passent 1 à 4 octets (caractères) par élément (octet) à transférer. (et plus si tu ajoutes des virgules ou des espaces)