有没有比使用 sprintf 将浮点数格式化为字符串更少 space 的方式?

Is there a less-space taking way than using sprintf to format floats to strings?

我正在为微控制器开发 C 代码,此代码从传感器获取输入并将来自传感器的数据与字母数字字符 LCD 上的其他字符串一起输出。 我一般用sprintf,但是我发现用sprintf把floats格式化成字符串的时候,占用的程序内存太多space,在一个微控制器。 (太多了,我的意思是从程序内存的 34% 直接跳到 99.2%)

所以我的问题是,是否有一种less-space taking 方法可以将浮点数格式化为字符串? 我只关心方法简单

我在 PIC16F877a 8 位 MCU 上使用 MPLABX IDE 和 XC8 编译器。

非常感谢。

有很多 printf 替代品可用,但它们都不完全符合标准,缺少某些功能以减少代码大小。

我用过的一些是Mpaland printf and Menie printf

还有Chan printf,但它根本不支持浮动。

is there a less-space taking method to format floats into strings?

只需写入字节并在 reader 端进行转换。了解微控制器上浮点数的字节顺序和格式后,reader 需要开发一种 软件 从字节读取浮点数的方法。

XC8文档你知道浮点数的格式:

Floating point is implemented using either a IEEE 754 32-bit format, or a truncated, 24-bit form of this.

你会在微控制器端做:

void send_byte(unsigned char b) {
    // send the bytes as is as binary - the simplest there is
    hardware_send(b);
    // or as hex readable number
    // depending on if you want it human readable or not.
    char buf[10];
    int len = snprintf(buf, sizeof(buf), "%#02x", b);
    for (unsigned char i = 0; i < len; ++i) {
       hardware_send(buf[i]);
    }
}

void send_float(float data) {
    const unsigned char *b = (const unsigned char*)&data;
    for (unsigned char i = 0; i < sizeof(data); ++i) {
        send_byte(b[i]);
    }
}

int main() {
    float data = get_data();
    send_float(data);
}

转换数据几乎不需要花费任何费用。编写您自己的 byte->hex 转换并且完全不使用 sprintf 以节省更多内存。

在远程端,您将编写软件转换为浮点数。将字节累积到缓冲区中,修复输入的字节顺序。使用按位运算提取符号、尾数和指数。在 C 中,您将使用 scalb 将尾数和指数转换为浮点数,然后乘以符号。但更好的选择是尽可能在 PC 端使用更灵活的编程语言——我会选择 python.

但从务实的角度...

on a PIC16F877a 8-bit MCU.

你永远不会在这么小的 MCU 上使用浮点数。由于您似乎想要传输温度,因此以毫摄氏度表示的 32 位 long 数字将为您提供无限范围的温度。但即使是用摄氏度表示的 16 位 short 数字也足够了。根本不要使用浮点数。将所有代码转换为仅使用整数。

@subjective-side-note:我使用 XC8 的旅程非常不愉快。 XC8 的免费版本生成非常糟糕且未优化的代码,我更喜欢 sdcc。如果这是一个业余项目,我建议转移到 STM32(例如 blue-pill)或 Arduino(例如 ESP8266,即使有 wifi ......),它们更便宜,更容易使用,现代和 gcc 在它们上工作。

Is there a less-space taking way than using sprintf to format floats to strings?
... code takes input from sensors and outputs the data from the sensors along with other strings on an alphanumeric character

完全不要使用浮点数。

传感器的读数肯定是一个整数。使用整数数学将该读数转换为摄氏分度,然后打印。

TMP235 示例

Temperature  Output
-40 C         100
  0 C         500
150 C        2000

#define SCALE_NUM ((int32_t)(150 - -40) * 10)
#define SCALE_DEM (2000 - 100)
#define OFFSET    (500)

int temperature_raw = temperature_sensor();
int temperature_decidegreesC = (temperature_raw - OFFSET)*SCALE_NUM/SCALE_DEN;
send_integer(temperature_decidegreesC/10);
send_char('.');
send_char(abs(temperature_decidegreesC/10) + '0');

可以进行其他改进,但避免 FP 变量和数学运算并使用整数数学运算是关键。