Convierta la temperatura DS18B20 a una cadena

3

Quiero convertir DS18B20 temperatura (código de 4 bytes de la hoja de datos) en una cadena con Precisión 0.1 ° C (como sprintf %.1f ). AVR. Lenguaje C (avr-gcc). Necesito el código pequeño , por lo que sprintf , tipos de punto flotante y round de math.h es una mala idea. Mi siguiente código actual también es malo:

void reverse_string(char *s)
{
    char *p, c;

    for (p = s + strlen(s) - 1; s <= p; ++s, --p) {
        c = *p;
        *p = *s;
        *s = c;
    }
}

void ts_to_string(uint16_t ts, char *s)
{
    int8_t n = (int8_t)(ts >> 4);
    uint8_t neg = n & 0x80;
    char *p = s;
    float f;

    if (neg)
        n = -n-1;
    do {
        *p++ = n % 10 + '0';
    } while ((n /= 10) > 0);

    if (neg)
        *p++ = '-';

    *p = '
void reverse_string(char *s)
{
    char *p, c;

    for (p = s + strlen(s) - 1; s <= p; ++s, --p) {
        c = *p;
        *p = *s;
        *s = c;
    }
}

void ts_to_string(uint16_t ts, char *s)
{
    int8_t n = (int8_t)(ts >> 4);
    uint8_t neg = n & 0x80;
    char *p = s;
    float f;

    if (neg)
        n = -n-1;
    do {
        *p++ = n % 10 + '0';
    } while ((n /= 10) > 0);

    if (neg)
        *p++ = '-';

    *p = '%pre%';
    reverse_string(s);
    *p++ = '.';

    f = (float)(ts & 0xf) / 16.0;
    if (neg)
        f = 1.0-f;
    *p++ = (char)round(f * 10.0) + '0';
    *p = '%pre%';
}
'; reverse_string(s); *p++ = '.'; f = (float)(ts & 0xf) / 16.0; if (neg) f = 1.0-f; *p++ = (char)round(f * 10.0) + '0'; *p = '%pre%'; }
    
pregunta

2 respuestas

2

Mi solución final:

void ts_to_string(uint16_t ts, char *s)
{
    int8_t t, neg;
    char *p = s;

    // integer part processing
    //
    t = (int8_t)(ts >> 4);
    neg = t & 0x80;
    if (neg)
        t = ~t;
    do {
        *p++ = t % 10 + '0';
    } while ((t /= 10) > 0);


    *p++ = neg ? '-' : '+';

    *p = '
void ts_to_string(uint16_t ts, char *s)
{
    int8_t t, neg;
    char *p = s;

    // integer part processing
    //
    t = (int8_t)(ts >> 4);
    neg = t & 0x80;
    if (neg)
        t = ~t;
    do {
        *p++ = t % 10 + '0';
    } while ((t /= 10) > 0);


    *p++ = neg ? '-' : '+';

    *p = '%pre%';
    reverse_string(s);

    // fractional part processing
    //
    *p++ = '.';
    t = (int8_t)ts & 0xf;
    if (neg)
        t = (-t) & 0xf;
    t = ((int16_t)t * 100) >> 4; // shift on 2 dec. digit, then mul 0.0625
    if ((t % 10) >= 5) // round
        t += 10;
    t /= 10; // shift on 1 decimal digit
    *p++ = (char)t + '0';

    *p = '%pre%';
}
'; reverse_string(s); // fractional part processing // *p++ = '.'; t = (int8_t)ts & 0xf; if (neg) t = (-t) & 0xf; t = ((int16_t)t * 100) >> 4; // shift on 2 dec. digit, then mul 0.0625 if ((t % 10) >= 5) // round t += 10; t /= 10; // shift on 1 decimal digit *p++ = (char)t + '0'; *p = '%pre%'; }

Su tamaño aprox. 100 bytes, eso es suficiente para mí. (La solución de la pregunta tiene un tamaño aproximado de 3 KB debido a float y round .)

    
respondido por el user54579
3
Los algoritmos

(Conversión) son una compensación entre tamaño y velocidad. La conversión más rápida es a través de una tabla de búsqueda, pero eso requiere mucho tamaño de código, ¡especialmente para 16 bits!

Esta nota de aplicación AVR muestra métodos para convertir entre binario y BCD para diferentes longitudes de palabras. La nota de la aplicación está escrita para el ensamblaje de AVR, pero describe los algoritmos en el texto y los diagramas de flujo, por lo que también debería ser utilizable para otros controladores. Primero tendrá que tomar el valor absoluto, ya que los algoritmos parecen estar escritos para números sin firmar.

Si no entiende completamente el algoritmo, use el BCD como un paso intermedio. El último paso, de BCD a ASCII debería ser fácil. De lo contrario, puede ajustar el algoritmo para que MSD y LSD se desplacen a bytes diferentes, de modo que solo tenga que OR con 0x30 para obtener el valor ASCII.

Dado que esto se escribió para el ensamblaje, puede ser más eficiente en código escribirlo en ensamblado en línea, en lugar de C.

    
respondido por el stevenvh

Lea otras preguntas en las etiquetas