Convertir Hex à décimal quand aucun type de données peut contenir le nombre total

StackOverflow https://stackoverflow.com/questions/1143302

  •  16-09-2019
  •  | 
  •  

Question

Ok, donc je travaille avec un microprocesseur PIC, en C. Il est un 16F, donc il ne peut pas contenir des entiers supérieurs 32bits (int32 non signé est le plus grand datasize disponible)

D'un lecteur, je reçois un code d'identification de 5 octets. Pour transmettre, je dois codé BCD, chiffre par chiffre. Je ne peux pas sprinte à une chaîne, car il est plus grand que la taille des données, et ne peut pas traiter. Je ne peux pas le diviser, car aucune opération est définie pour elle.

Je ne peux pas comprendre une solution possible, ce que quelqu'un a traité auparavant?

EDIT:

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 (Prenez ASCII, et l'envoyer) Je l'ai déjà travailler, mais je dois la représentation de chaîne du nombre total avant que je puisse faire quoi que ce soit avec lui.

Était-ce utile?

La solution

En supposant que vous avez 32 bits arithmétique: 2 ** 24 = 16777216, afin de prendre x les 2 octets les plus significatifs et y comme le moins significatif 3:

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

Le premier terme peut être calculée en 32 bits sans trop-plein (depuis x < 2**16). Le deuxième terme peut également être calculé sans trop-plein (depuis x < 2**16 et y < 2**24).

Il est essentiellement division longue dans 2**24 de base d'une valeur à 2 chiffres, mais avec des termes pré-calculé sachant que le diviseur est 1000. Un millier est choisi parce qu'il est le moins puissance de 10 supérieure à 2**8.

Ainsi, on calcule d'abord les plus bas de trois chiffres, utilisez le fait que (2**32) % 1000 == 296. Cette fois-ci, nous allons prendre x comme le plus haut octet et y comme les 4 octets 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

diviser ensuite le nombre original de 1000 en utilisant la formule ci-dessus. Ensuite, vous êtes en toute sécurité sur le territoire 32 bits et peut churn les chiffres restants en utilisant la boucle normale.

BTW, je vérifie les résultats si je vous: je ne l'ai pas testé et il est possible que je l'ai fait une erreur quelque part. Il devrait être facile à comparer les résultats des conversions de Bcd effectuées en utilisant les moyens habituels dans un entier de 64 bits sur un PC.

Autres conseils

Qu'est-ce que je ferais, est de mettre en œuvre addition et la multiplication des numéros codés sous forme de chaîne (sorte de BigNum). De cette façon, vous pouvez sprintf l'octet le plus important de votre ID à une chaîne « A », il faut multiplier avec la chaîne « 4294967296 » (256 ^ 4) vous donnant chaîne « B », sprintf les 4 octets les moins significatifs de votre ID en une autre chaîne "C", et enfin ajouter "B" et "C".

Il est pas très sexy, en particulier sur un micro-contrôleur, mais cela fonctionne:)

Le PIC16F n'a pas de multiplication de matériel ou d'une unité de partage, de sorte que si vous multipliant ou en divisant par une puissance de 2, il est taxer au processeur. Voici une routine qui fait un BCD sur un nombre de 32 bits et ne nécessite pas la division ou la multiplication. Vous pouvez adapter à un nombre de 5 octets en faisant en morceaux.

BCD32 void (int32u NUMIN) {     int8u chiffres = 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 » à une chaîne vous-même manuellement. aller sur l'octet de données après l'octet et le convertir en une chaîne numérique par des caractères individuels.

Le noyau de ce problème, je dirais est l'un des « division longue » pour convertir en décimal. Pas tout à fait la différence division longue que vous avez appris à l'école primaire, mais avec des nombres binaires, division longue est beaucoup plus simple. Mais il est encore beaucoup de travail.

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

Vous devrez implémenter votre propre soustraction multi-octets et changer les routines.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top