找回密码
立即注册
搜索
热搜: 活动 交友 discuz
发新帖

134

积分

0

好友

2

主题
发表于 2023-9-7 15:28:28 | 查看: 1689| 回复: 4 IP:中国 中国广播电视网络有限公司
rt-thread-studio 不支持printf打印浮点数,是否可以添加编译选择支持打印浮点,要怎么添加编译选项
发表于 2023-9-7 15:37:58 IP:中国 中国广播电视网络有限公司
方法一:将rt_kprintf函数中的rt_vsnprintf替换为标准C库中的vsnprintf。这样可以直接使用%f或%lf格式化浮点数,但是会增加ROM(Flash)的占用,大概增加了7KB左右。
方法二:重写rt_kprintf函数,将rt_vsnprintf改为vsnprintf。这样可以避免修改RT-Thread系统的代码,但是也会增加ROM(Flash)的占用。
方法三:单独实现一个浮点数打印的函数,基于vsnprintf,类似于rt_kprintf。这样可以只在需要打印浮点数的时候调用该函数,不影响其他地方的打印。
方法四:开启ulog组件,并且开启浮点支持。这样可以使用ulog提供的LOG_D等宏来打印浮点数,并且可以实现LOG分级输出控制等功能。



发表于 2023-9-7 16:07:41 IP:中国广东省 中国电信

简介

RT-Thread 的rt_kprintf,普通的格式打印没有问题,但是暂不支持打印%lf、%f这种浮点打印

如何格式化打印浮点数呢?如float类型,如double类型

默认rt_kprintf格式化打印浮点数:

rt_kprintf("RMC : Latitude: %lf[%c], Longitude: %lf[%c], Fix: %c\n", pack.lat, pack.ns,        pack.lon, pack.ew, pack.status);

打印结果:

RMC : Latitude: %f[E], Longitude: %f[󪟆ix: H

打印原理

  • 标准C库提供字符串的格式化函数,rt_kprintf没有使用标准C库,为了降低ROM(Flash)的开销
  • 这里不直接使用标准C库的printf、sprintf,使用的是:vsnprintf
  • RT-Thread rt_kprintf为了缩小代码体积,通过重新实现rt_vsnprintf的方式,实现了大部分vsnprintf功能。

第一种方法

  • 既然RT-Thread rt_kprintf使用了:rt_vsnprintf,直接改为:vsnprintf,就可以实现浮点数打印了
RMC : Latitude: 3115.642200[N], Longitude: 12127.549000[E], Fix: A
  • 当然增加了ROM(Flash)的占用,大概增加了7KB左右吧
  • 修改RT-Thread 系统的代码,总感觉不太好,还好,rt_kprintf是 weak弱属性,也就是用户可以重写

第二种方法

  • rt_kprintf的重写
  • 重写的代码的位置可以随便放,只是把rt_vsnprintf改为:vsnprintf

第三种方法:

  • 浮点打印的毕竟是少数,可以单独实现一个浮点打印的函数,基于vsnprintf,类似于rt_kprintf,如下:
#include <stdio.h>
#define DBG_BUFF_MAX_LEN          256
/* debug print : support float double */
int dbg_printf(const char *fmt, ...)
{
    va_list args;
    static char rt_log_buf[DBG_BUFF_MAX_LEN] = { 0 };
    va_start(args, fmt);
    int length = vsnprintf(rt_log_buf, sizeof(rt_log_buf) - 1, fmt, args);
    rt_kputs(rt_log_buf);
    return length;
}

第四种方法

  • 开启ulog组件,并且开启浮点支持

69d1bd848bd35041fe7d7ab5450ce1ee.png

  • 因为ulog组件里的字符串格式化输出,开启浮点支持后,也调用了vsnprintf
  • 演示:
define DBG_TAG “nmea.test”
define DBG_LVL DBG_LOG
include
void nmea_parse_test_rmc(void)
{
nmea_rmc_t pack = { 0 };

nmea_parse_rmc(rmc_buf, rt_strlen(rmc_buf), &pack);
LOG_D("RMC : Latitude: %lf[%c], Longitude: %lf[%c], Fix: %c\n", pack.lat, pack.ns,
    pack.lon, pack.ew, pack.status);
}
MSH_CMD_EXPORT(nmea_parse_test_rmc, nmea_parse_test_rmc);
  • 效果:
[6466] D/nmea.test: RMC : Latitude: 3115.642200[N], Longitude: 12127.549000[E], Fix: A

终极方法

  • 以上只是为了调试方便,简单的实现了浮点的打印,真正的实现就是优化: rt_vsnprintf,让它实现浮点的打印
  • 这要考虑实现的复杂度,是否代码的ROM(Flash)占用比标准C库小
  • 这个放在后面实现,可以参考一些类似于gcc的c库,参考标准C库vsnprintf【暂未实现】

小结

  • 普通的调试rt_kprintf本身就够了
  • 若有浮点打印需求,可以直接写一个专用的可以输出浮点的函数,类似于上面的【方法三】
  • 可以使用ulog等组件,实现LOG分级输出控制等,让输出管理起来更便捷
发表于 2023-9-7 16:08:41 IP:中国广东省 中国电信
【RT-Thread中关于浮点数如何使用rt_kprintf打印输出 - CSDN App】http://t.csdn.cn/35qJT
发表于 2023-9-7 16:30:28 IP:中国 中国广播电视网络有限公司

可以使用下面这种方法解决RT-Thread中printf不支持打印浮点数的问题:

第一步:打开RT-Thread的bsp.h文件,找到如下代码:

#ifdef RT_USING_FINSH
#define RT_USING_DEVICE_CONSOLE
#endif

第二步:在这段代码的下面添加如下代码:

#define RT_USING_FLOAT

第三步:保存文件,重新编译项目。

这样,就可以使用printf打印浮点数了。如果还是无法打印浮点数,可以尝试使用如下代码:

float f = 1.23;
char buf[32];
sprintf(buf, "%.2f", f);
rt_kprintf("f=%.2f\n", f);

这个方法是使用sprintf将浮点数转换为字符串,然后再使用rt_kprintf打印字符串。

*滑块验证:
您需要登录后才可以回帖 登录 | 立即注册

手机版|小黑屋|国产电子社区 ( 沪ICP备2023018578号-1|

苏公网安备 32011102010465号


)|网站地图

GMT+8, 2024-11-7 16:53 , Processed in 0.061603 second(s), 25 queries , MemCached On.

Powered by Discuz! X3.5

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表