有没有比使用 sprintf 将浮点数格式化为字符串更节省空间的方法?

问题描述 投票:0回答:3

我正在为微控制器开发一个 C 代码,该代码接收来自传感器的输入,并将来自传感器的数据以及字母数字字符 LCD 上的其他字符串一起输出。 我通常使用 sprintf 来实现此目的,但我注意到,当使用 sprintf 将 floats 格式化为字符串时,它会占用太多的程序内存空间,这在微控制器上相当低。 (我所说的太多是指从程序内存的 34% 直接跳到 99.2%)

所以我的问题是,是否有一种占用空间较小的方法将浮点数格式化为字符串? 我只关心方法有多简单。

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

提前非常感谢。

c printf microcontroller
3个回答
7
投票

是否有比使用 sprintf 将浮点数格式化为字符串更节省空间的方法?
...代码从传感器获取输入,并输出来自传感器的数据以及字母数字字符上的其他字符串

根本不要使用浮点。 @user3386109

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

TMP235示例

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

#define SCALE_NUM ((int32_t)(150 - -40) * 10)
#define SCALE_DEN (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 变量和数学并使用整数数学是关键。


1
投票

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

我使用过的一些是 Mpaland printfMenie printf

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


1
投票

有没有一种占用空间较小的方法将浮点数格式化为字符串?

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

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

浮点是使用 IEEE 754 32 位格式或其截断的 24 位格式实现的。

您可以在微控制器方面执行以下操作:

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);
}

转换数据几乎不需要任何成本。编写您自己的字节->十六进制转换,并且根本不使用

sprintf
以节省更多内存。

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

但从务实的角度来看...

在 PIC16F877a 8 位 MCU 上。

您永远不会在如此小的 MCU 上使用浮点数。当您似乎想要传输温度时,以毫摄氏度表示的 32 位

long
数字将为您提供无限的温度范围。但即使是用摄氏度表示的 16 位
short
数字也足够了。根本不要使用浮点数。将所有代码转换为仅使用整数。

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

© www.soinside.com 2019 - 2024. All rights reserved.