Comment composer une chaine de binaire

Bonjour,
je souhaite réaliser une communication SPI sur 32 bit . J'ai besoin que le data, l'adresse et le CRC qui composera mon signal MOSI soit rentrer par l'utilisateur, je souhaiterais donc les accoler pour les envoyer au capteur. Comment puis-je réaliser cela en code ?

Merci pour vos réponses.

:warning:
Post mis dans la mauvaise section, on parle anglais dans les forums généraux. ➜ déplacé vers le forum francophone.

Merci de prendre en compte les recommandations listées dans "Les bonnes pratiques du Forum Francophone”

Si le port série est dispo ou un keypad, vous pouvez jeter un oeil à mon petit tuto

Avant de parler code, il faudrait peut-être parler matériel.
Quel moyen de saisie pour entrer les différentes informations?
Quel est ton problème, la saisie? la concaténation des données? leur émission?

1 Like

Mon problème est au niveau de la concaténation des données. Je ne sais pas comment faire en sorte d'avoir une chaine de 32 binaires.
Pour l'instant j'ai réalisée 3 octets mais ça me pause un problème pour calculer mon CRC.

Avec 3 octets tu auras du mal à faire 32 bits... Mais avec 4 :

uint32_t chaine;
uint8_t, octet1, octet2, octet3, octet4;
chaine = octet1 << 24 + octet2 << 16 + octet3 << 8 + octet4;

chaine contiendra les contenus octet1 octet2 octet3 octet4

1 Like

Avec ce que j'ai fait j'obtient 0 quand j'affiche chaine

#include <SPI.h>
 
  // Input 
int address=0x1F;
int data=0xFFFF;
  
  //pin definition
const int cs=9;

void setup() {
  
   Serial.begin(9600);
   SPI.begin();
   pinMode(cs, OUTPUT);
   digitalWrite(cs, HIGH);
   SPI.beginTransaction(SPISettings(3000000, MSBFIRST, SPI_MODE3));
   delay (10);
}

void loop() {
   // Création de la chaine MOSI en 4 Byte pour read request
    // Byte 1 (00addres0)
    byte mosi1 = address<<1;
    Serial.println(mosi1,BIN);
    
    // Byte 2 
    byte mosi2 = data>>8;
Serial.println(mosi2, BIN);

    // Byte 3
    byte mosi3 = data>>2;
Serial.println(mosi3, BIN);

  // Byte 4
byte mosi4 = data<<6;
Serial.println(mosi4, BIN);

uint32_t chaine;
chaine = mosi1 << 24 + mosi2 << 16 + mosi3 << 8 + mosi4;
Serial.println(chaine, BIN);

 delay(1000);


}

Déjà 0xFFFF ne rentre pas dans un int. Il te faut :
uint16_t data = 0xFFFF;

Ensuite que donnent les valeurs des 4 octets ?

Un byte va de 0 à 0xFF.

Si tu prends 0xFFFF et que tu le décales de 8 bits vers la droite, tu vas obtenir 0xFF : ça rentre.
Par contre

ça donne 0x3FFF, ça ne rentre pas dans un byte. Je suppose qu'il va conserver 0x3F, mais est-ce bien sûr ?
Quant à

ça donne 0x3FFFC0 !!!

Au besoin, tu peux changer les + en ||
chaine = (mosi1 << 24) | (mosi2 << 16) | (mosi3 << 8) | mosi4;
mais le résultat devrait être le même (corrigé)

si mais c'est -1 :slight_smile:

attention aux décalages avec des byte, le compilateur C++ passe en int

Je pense que tu veux dire changer les + en |

Oui, oups !!

c'est un tableau de 4 octets que vous voulez ou un uint32_t ?

Alors :
chaine = (mosi1 * pow(2,24)) + (mosi2 * pow(2,16)) + (mosi3 * pow(2,8)) + mosi4;
ou
chaine = (mosi1 * 16777216ul) + (mosi2 * 65536ul) + (mosi3 *256ul) + mosi4;

:slight_smile:

faut juste faire attention - idéalement on met les mois dans le format destination et on shift ensuite, comme ça on est sûr d'avoir des 0 là où il faut

Quelque part, je ne vois pas l'intérêt de concaténer les 4 octets pour faire un mot de 32 bits alors que le port SPI attend des octets

oui d'où ma question

Ensuite que donnent les valeurs des 4 octets ?
Mon signal mosi doit être =

0 0 A A A A A 0 0 0 d d d d d d d d d d d d d d d d 0 C C C C C
avec A mon address, d mon data et C mon CRC
j'ai ensuite découpé en octet
|Octet 1 :|0|0|A|A|A|A|A|0|
|Octet 2 :|0|0|d|d|d|d|d|d|
|Octet 3 :|d|d|d|d|d|d|d|d|
|Octet 4 :|d|d|0|CRC|CRC|CRC|CRC|CRC|

Je souhaite refaire la chaine de 32 bit pour pouvoir calculer le CRC car je doit avoir le bit 30 au 5. Je me suis dit que ce serait le plus simple. Sinon je peut faire des boucles pour chaques octets ?

Ma question était : qu'est-ce qui s'affiche avec tes println ?
Mais, au final si tu as déjà des variables contenant le AAAA, dddd et CCCC, il est peut-être plus simple de les intégrer directement dans la chaine.

Dans ton exemple, tu as :

Supposons que le CRC vaut 0x1F au maximum (0b11111), disons 0x15 par exemple.
Tu devrais pouvoir faire un truc comme ceci :

uint8_t CRC = 0x15;                            // 010101
uint16_t data=0xFFFF;         // 1111111111111111
uint8_t address = 0x1F; // 11111
uint32_t chaine = CRC | (data << 6) | (address << 25);

Tu obtiens : 00111110001111111111111111010101

Note les types des variables : byte (équivalent de uint8_t), unsigned int (équivalent de uint16_t) et unsigned long (équivalent de uint32_t)

Ma question était : qu'est-ce qui s'affiche avec tes println ?

C'était juste des indicateurs pour voir ce que je fesais :slight_smile: .