我正在为微控制器开发一个 C 代码,该代码接收来自传感器的输入,并将来自传感器的数据以及字母数字字符 LCD 上的其他字符串一起输出。 我通常使用 sprintf 来实现此目的,但我注意到,当使用 sprintf 将 floats 格式化为字符串时,它会占用太多的程序内存空间,这在微控制器上相当低。 (我所说的太多是指从程序内存的 34% 直接跳到 99.2%)
所以我的问题是,是否有一种占用空间较小的方法将浮点数格式化为字符串? 我只关心方法有多简单。
我在 PIC16F877a 8 位 MCU 上使用带有 XC8 编译器的 MPLABX IDE。
提前非常感谢。
是否有比使用 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 变量和数学并使用整数数学是关键。
有很多 printf 替代品可用,但它们都不完全符合标准,缺少某些功能来缩小代码大小。
我使用过的一些是 Mpaland printf 和 Menie printf
还有Chan printf,但它根本不支持浮动。
有没有一种占用空间较小的方法将浮点数格式化为字符串?
只需写入字节并在阅读器端进行转换即可。了解微控制器上浮点数的字节序和格式后,读者需要开发一种从字节读取浮点数的软件方式。
从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 可以在它们上工作。