Stocker des uint32_t dans un tableau de uint16_t

Bonjour,
Je travaille actuellement sur un projet dans lequel j'utilise le protocole modbus.

Ce protocole met à disposition plusieurs registres, représentés dans le code par des tableaux d'uint16_t pour les holding registers par exemple (R/W de la part du maître et du slave).

Dans mon projet, j'ai créé une classe dans laquelle je ne veux pas utiliser de variables membres (recréées à chaque instanciation), mais un pointeur vers une case du tableau modbus (économie de mémoire + màj en direct des valeurs).

➜ Petit problème, les données que je souhaite stocker dans ce tableau proviennent de millis et sont des uint32_t. La question est donc de savoir comment je peux convertir mes valeurs sur 32 bits en valeurs stockables dans un tableau d'uint16_t ?

Merci d'avance pour vos réponses!

Cordialement,
Pandaroux007

J'ai édité mon message, la question n'était pas claire.

Bonjour @pandaroux007

Je n’ai pas trop de temps mais il me semble sans avoir trop cherché à comprendre. Je n’ai pas lu la totalité de ta demande. À cette question peut-être une réponse simple :
MSB + LSB = 16 + 16 =32

Bonne journée

Il suffit je pense de faire un cast du pointeur pour lui dire qu'il pointe sur un uint32_t.

Bonjour @philippe86220 et @fdufnews
Merci pour vos réponses!

Si j'ai bien compris, vous me suggérez de "construire" à partir de deux cases du tableau sur 16 bit une variable de 32 bit et inversement ? (D'ailleurs je viens enfin de comprendre le sens de bit de poid fort/faible :roll_eyes:). C'est possible ?


Je ne suis pas sûr de comprendre, désolé :woozy_face: Comment le fait de faire un cast du pointeur peut permettre d'utiliser deux uint16_t ensemble ?

Sachant qu'à ma question initiale je dois ajouter une contrainte, c'est que chaque instance va chercher plusieurs variables dans le tableau. Pour cela il suffit de faire :
index réel de l'instance = index de l'instance * nombre de case du tableau pour chaque instance
Mais il faut que la méthode pour utiliser des uint32_t dans ce tableau soit compatible avec ce calcul, ou alors changer de système ici aussi ?

Je dois admettre que ça dépasse mes compétences...
Cordialement,
Pandaroux007


uint16_t monTableau[6] = {0x1234, 0x3456, 0x4567,0x5678,0x6789, 0x789A};
uint32_t maVar32 = 0x89abcdef;

void displayTab(){
  for (int i = 0; i< 6; i++){
    Serial.print(monTableau[i], HEX);
    Serial.print(" ");
  }
  Serial.println();
}

void setup() {
  Serial.begin(115200);
  Serial.println("Original");
  displayTab();
  uint32_t *ptr = (uint32_t *) &monTableau[2];
  *ptr = maVar32;
  Serial.println("Modified");
  displayTab();
}

void loop() {
  // put your main code here, to run repeatedly:

}

Bingo ça fonctionne (testé sur wokwi). Merci beaucoup! Mais je ne suis pas sûr de comprendre comment ça fonctionne, comment la variable uint32_t se "coupe"-t-elle toute seule en deux uint16_t ?

Tu écris une variable uint32_t à l'adresse pointée par le pointeur donc elle va occuper 4 octets en mémoire.

Quelque chose de plus général


uint8_t monTableau[32];
uint32_t *ptr32 = (uint32_t *) monTableau;
uint16_t *ptr16 = (uint16_t *)monTableau;

void displayTab(uint8_t format){
  if (format == 1){
    for (uint8_t i = 0; i < sizeof(monTableau); i++){
      Serial.print(monTableau[i], HEX);
      Serial.print(" ");
    }
  } else if (format == 2){
    for (uint8_t i = 0; i < sizeof(monTableau)/ sizeof(uint16_t); i++){
      Serial.print(ptr16[i], HEX);
      Serial.print(" ");
    }
  } else if (format == 4){
    for (uint8_t i = 0; i < sizeof(monTableau)/ sizeof(uint32_t); i++){
      Serial.print(ptr32[i], HEX);
      Serial.print(" ");
    }
 }
  Serial.println();
}

void fillTab(){
  for (uint8_t i = 0; i < sizeof(monTableau); i++){
    monTableau[i] = 0x10 + i;
  }
}

void setup() {
  Serial.begin(115200);
  fillTab();
  Serial.println("Original");
  displayTab(1);
  *(ptr32 + 1) = 0x89abcdef;
  *(ptr32 + 5) = 0x12345678;
  *(ptr16) = 0xff34;
  *(ptr16 + 8) = 0x34f9;
  Serial.println("Modified");
  displayTab(1);
  displayTab(2);
  displayTab(4);
}

void loop() {
  // put your main code here, to run repeatedly:

}

Qui donne ceci dans le moniteur série

Original
10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F 
Modified
34 FF 12 13 EF CD AB 89 18 19 1A 1B 1C 1D 1E 1F F9 34 22 23 78 56 34 12 28 29 2A 2B 2C 2D 2E 2F 
FF34 1312 CDEF 89AB 1918 1B1A 1D1C 1F1E 34F9 2322 5678 1234 2928 2B2A 2D2C 2F2E 
1312FF34 89ABCDEF 1B1A1918 1F1E1D1C 232234F9 12345678 2B2A2928 2F2E2D2C 

Attention quand même, ces manips avec des pointeurs peuvent vite devenir casse-gueule et on peut écraser des portions de mémoire par erreur.

1 Like

on te susurre la solution à demi mot

Oui et pour un stockage sur 328p ou esp32 c’est du Little-endian donc contrairement à mon message #3 il faut lire :
LSB + MSB sinon c’est du Big-endian

Et oui ce sont les joies de l’endianness.

Bon codage :wink:

Si on utilise directement des pointeurs sur le type correct on évite justement ce casse-tête.

Oui mais comme j’avais suggéré un stockage MSB + LSB autant rectifier. Mais c’est vrai que ça n’a pas d’incidence …
PS : Autant être précis.

1 Like