Estoy escribiendo código para un PIC18F46K22 usando el compilador C18. quiero escribir el valor de un entero en ASCII sobre el USART a mi PC.
Para , es fácil:
Write1USART(n + 0x30); // 0x30 = '0'
Esto funcionaría para :
Write1USART((n/10) + 0x30);
Write1USART((n%10) + 0x30);
Pero esta no es la forma más rápida posible, probablemente.
Entonces , ¿hay una función incorporada o una función en algún lugar que pueda usar en lugar de rodar la mía ?
El compilador C18 es compatible con la familia de números a ascii de funciones C estándar en stdlib.h : itoa()
, ltoa()
, ultoa()
etcétera.
Dependiendo de qué compilador / stdlib.h tenga, el prototipo de función relevante sería:
extern char * itoa(char * buf, int val, int base); // signed int
extern char * utoa(char * buf, unsigned val, int base); // unsigned int
o
extern char * itoa(char * buf, int val); // signed int
extern char * utoa(char * buf, unsigned val); // unsigned int
Si estuviera buscando una forma C " estándar " incorporada relativamente robusta para convertir sus números a cadenas ASCII, estas xtoa()
funciones serían las que debe usar.
Si, por otro lado, está obligado a exprimir algunos ciclos adicionales o bytes de memoria del código final, entonces varias de las otras respuestas a su pregunta son el camino a seguir.
itoa
Podrían haberse originado en el antiguo Borland C, pero nunca llegó a ISO C. Sin embargo, no importa; si están ahí, úsalos.Podría probar una función que usa el método de fuerza bruta para convertir a cadena. La siguiente función no utiliza el operador de módulo ni la multiplicación. Devuelve una cadena.
/*
* Create a function that will return a string.
* It accepts 'inputValue' that is up to 255, but you can make it an int or longint...
* ...after you make some edits in the function.
* inputValue: 5 7 6
* Digits: 1st 2nd 3rd
*/
unsigned char* returnString(unsigned char inputValue)
{
static unsigned char processedString[4]; // Return a string of 3 digits.
unsigned char firstDigitCounter = 0; // Brute-force counter for first digit.
unsigned char secondDigitCounter = 0; // Brute-force counter for second digit.
if (inputValue > 99) // If we have a 3 digit number,
{
while (inputValue > 99) // Until our number is 3 digits, i.e. bigger than 99,
{
inputValue -= 100; // Subtract 100 and..
firstDigitCounter++; //.. increment first digit.
}
while (inputValue > 9) // Until our number is 3 digits, i.e. bigger than 9,
{
inputValue -= 10; // Subtract 10 and..
secondDigitCounter++; //.. increment second digit.
}
// Now, we have left the 'inputValue' as a single digit.
processedString[0] = firstDigitCounter + 0x30; // First digit
processedString[1] = secondDigitCounter + 0x30; // Second digit
processedString[2] = inputValue + 0x30; // Third digit
processedString[3] = '\0'; // String terminator.
}
else // If we have a 2 digit number,
{
while (inputValue > 9) // Until our number is 3 digits, i.e. bigger than 99,
{
inputValue -= 10; // Subtract 10 and..
secondDigitCounter++; //.. increment second digit.
}
processedString[0] = secondDigitCounter + 0x30; // Second digit
processedString[1] = inputValue + 0x30; // Third digit
processedString[2] = '\0'; // String terminator.
}
return processedString; // Return the processed string.
}
Pastebin del código anterior.
he usado sprintf();
antes. Además de ser conveniente con el formateo, no estoy completamente seguro de si es rápido y ocupa poco espacio. Viene con
#include <stdio.h>
const uint8_t stringLength = 16;
char string[ stringLength ] = { 0 };
volatile uint32_t measurement = 12345;
sprintf( string , "Measured: %lu milliseconds\n" , measurement );
uint8_t charCounter = 0;
while ( ( charCounter < stringLength ) and ( string[ charCounter ] != 0x00 ) ) {
serialByteOut( string[ charCounter ] ); // Send a single character
charCounter++;
}
¿Dónde measurement
se actualiza un entero de 32 bits en una ISR, que quiero imprimir y string
es el búfer de salida? %lu
indica que se va a imprimir un entero largo sin signo y \n es una nueva línea.
El uso es básicamente el mismo que para printf();
La documentación es extensa y se puede encontrar fácilmente en Internet en varios sitios web: http://linux.die.net/man/3/sprintf
Yo mismo he hecho una función:
void writeInteger(unsigned long input) {
unsigned long start = 1;
unsigned long counter;
while (start*10 <= input)
start *= 10;
for (counter = start; counter >= 1; counter /= 10)
Write1USART(((input / counter) % 10) + 0x30);
}
Podrías intentar esto:
void writeInteger(unsigned i)
{
if (i > 9)
writeInteger(i/10);
write1USART(i % 10 + '0');
}
Kortuk
usuario17592
unsigned long
.pete becker
n + 0x30
con un comentario que0x30 = '0'
, usen + '0'
. Tanto C como C ++ requieren que los dígitos tengan valores crecientes adyacentes, por lo que0
siempre funciona y es más claro.9
n + '0'