Entero a ASCII en C18

6

Estoy escribiendo el código para un PIC18F46K22 usando el compilador C18. Quiero escribir el valor de un entero \ $ n \ $ en ASCII sobre el USART en mi PC.

Para \ $ n < 10 \ $, es fácil:

Write1USART(n + 0x30); // 0x30 = '0'

Esto funcionaría para \ $ 10 \ le {} n \ le100 \ $:

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?

    
pregunta Keelan

5 respuestas

9

El compilador C18 admite la familia de números a ascii de funciones C estándar en stdlib.h : itoa() , ltoa() , ultoa() et cetera .

Dependiendo de qué compilador / stdlib.h tenga, la función relevante de prototipo 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 relativamente sólida " estándar " incorporada para convertir sus números a cadenas ASCII, estas funciones xtoa() serían las que debería usar.

Si, por otro lado, está obligado a eliminar algunos códigos o bytes extra de memoria del código final, entonces hay varias otras respuestas a su pregunta.

    
respondido por el Anindo Ghosh
3

Puedes probar una función que usa el método de fuerza bruta para convertir en cadena. La función de abajo no usa operador de módulo ni 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] = '
/*
 *  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] = '%pre%'; // 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] = '%pre%'; // String terminator.
    }
    return processedString; // Return the processed string.
}
'; // 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] = '%pre%'; // String terminator. } return processedString; // Return the processed string. }

Pastebin del código anterior.

    
respondido por el abdullah kahraman
3

He usado sprintf(); antes. Además de ser conveniente con el formateo, no estoy completamente seguro de si es rápido y tiene una huella pequeña. 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++;
}

Donde measurement es un entero de 32 bits actualizado en un ISR, que quiero imprimir y string es el búfer de salida. %lu indica que se imprimirá un entero sin signo largo y \ n es una nueva línea.

El uso es mayormente el mismo que para printf(); La documentación es extensa y se puede encontrar fácilmente en Internet en varios sitios web: enlace

    
respondido por el jippie
3

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);
}
    
respondido por el Keelan
1

Puedes probar esto:

void writeInteger(unsigned i)
{
   if (i > 9)
     writeInteger(i/10);
   write1USART(i % 10 + '0');
}
    
respondido por el user207421

Lea otras preguntas en las etiquetas