Convertir Hex en Décimal quand aucun type de données ne peut contenir le nombre entier

Ok, je travaille donc avec un microprocesseur PIC, en C. Il s’agit d’un 16F, il ne peut donc pas contenir d’entiers supérieurs à 32 bits (int32 non signé est la plus grande taille de données disponible).

D’un lecteur, je reçois un code d’identification de 5 octets. Pour le transmettre, je dois encoder en BCD, chiffre par chiffre. Je ne peux pas le sprint sur une chaîne, car il est plus grand que la taille des données et je ne peux pas le traiter. Je ne peux pas le diviser parce qu’aucune opération n’est définie pour cela.

Je ne peux trouver aucune solution possible, est-ce que quelqu’un a déjà réglé ce problème?

MODIFIER:

Je reçois le numéro dans une série de 5 octets: “FF-FF-FF-FF-FF”. Je dois le convertir en décimal “0123456789012” (13 chiffres, longueur de 256 ^ 5 en décimal) pour l’envoyer par RS232. La deuxième fonction (Prendre l’ASCII et l’envoyer) Je le fais déjà fonctionner, mais j’ai besoin de la représentation sous forme de chaîne du nombre entier avant de pouvoir faire quoi que ce soit avec.

En supposant que vous ayez une arithmétique de 32 bits: 2 ** 24 = 16777216, donc si x est le plus significatif des 2 octets et y est le moins significatif des 3:

(16777216 * x + y) / 1000 = (16777000 * x + 216 * x + y) / 1000 = 16777 * x + (216 * x + y) / 1000 

Le premier terme peut être calculé sur 32 bits sans dépassement de capacité (puisque x < 2**16 ). Le second terme peut également être calculé sans dépassement de capacité (puisque x < 2**16 et y < 2**24 ).

Il s’agit essentiellement d’une division longue en base 2**24 d’une valeur à 2 chiffres, mais avec des termes pré-calculés en sachant que le diviseur est 1000. Mille est choisi car c’est la plus petite puissance de 10 supérieure à 2**8 .

Donc, calculez d’abord les trois derniers chiffres, utilisez le fait que (2**32) % 1000 == 296 . Donc, cette fois, nous allons prendre x comme octet le plus élevé et y comme les 4 octets les plus bas

 ((2**32) * x + y) % 1000 = ((2**32) * x) % 1000 + y % 1000 (modulo 1000) = (296 * x) % 1000 + y % 1000 (modulo 1000) ((2**32) * x + y) % 1000 = ((296 * x) % 1000 + y % 1000) % 1000 

Divisez ensuite le nombre initial par 1000 en utilisant la formule ci-dessus. Vous êtes alors en sécurité sur le territoire 32 bits et pouvez convertir les chiffres restants en utilisant la boucle normale.

Au fait, je vérifierais les résultats si j'étais vous: je n'ai pas testé cela et il est possible que j'ai commis une erreur quelque part. Il devrait être facile de comparer les résultats des conversions bcd effectuées à l’aide des moyens habituels dans un entier 64 bits sur un PC.

Ce que je ferais, c’est d’implémenter l’addition et la multiplication de nombres codés sous forme de chaîne (sorte de BigNum). De cette façon, vous pouvez sprintf l’octet le plus significatif de votre ID vers une chaîne “A”, multipliez-le avec la chaîne “4294967296” (256 ^ 4) en vous donnant la chaîne “B”, sprintf les 4 octets les moins significatifs de votre ID une autre chaîne “C”, et en ajoutant enfin “B” et “C”.

Ce n’est pas très sexy, surtout sur un micro-contrôleur, mais ça marche 🙂

Le PIC16F ne dispose pas d’une unité de multiplication ni de division du matériel. Par conséquent, à moins de multiplier ou de diviser par 2, le processeur en subira les conséquences. Voici une routine qui effectue un BCD sur un nombre de 32 bits et ne nécessite pas de division ni de multiplication. Vous pouvez adapter ceci à un nombre de 5 octets en le faisant par morceaux.

void BCD32 (int32u numIn) {int8u digit = 0;

 while (numIn >= 1000000000) { numIn -= 1000000000; digit++; } debug[0] = digit + 48; digit = 0; while (numIn >= 100000000) { numIn -= 100000000; digit++; } debug[1] = digit + 48; digit = 0; while (numIn >= 10000000) { numIn -= 10000000; digit++; } debug[2] = digit + 48; digit = 0; while (numIn >= 1000000) { numIn -= 1000000; digit++; } debug[3] = digit + 48; digit = 0; while (numIn >= 100000) { numIn -= 100000; digit++; } debug[4] = digit + 48; digit = 0; while (numIn >= 10000) { numIn -= 10000; digit++; } debug[5] = digit + 48; digit = 0; while (numIn >= 1000) { numIn -= 1000; digit++; } debug[6] = digit + 48; digit = 0; while (numIn >= 100) { numIn -= 100; digit++; } debug[7] = digit + 48; digit = 0; while (numIn >= 10) { numIn -= 10; digit++; } debug[8] = digit + 48; digit = 0; while (numIn >= 1) { numIn -= 1; digit++; } debug[9] = digit + 48; debug[10] = CARRIAGE_RETURN; debug[11] = NEW_LINE_FEED; SendUart(12); 

}

Vous pouvez toujours “sprintf” le faire manuellement à une chaîne. parcourez octet après octet et convertissez-le en chaîne en ajoutant des caractères individuels.

Je dirais que le cœur de ce problème est un problème de “division longue” à convertir en nombre décimal. Ce n’est pas tout à fait contrairement à la division longue que vous avez apprise à l’école primaire, bien qu’avec les nombres binarys, la division longue soit beaucoup plus simple. Mais c’est encore beaucoup de travail.

essayer:
http://mathforum.org/library/drmath/view/55951.html

Vous devrez implémenter vos propres routines de soustraction et de décalage sur plusieurs octets.