简介
- 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
#define DBG_BUFF_MAX_LEN 256
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组件里的字符串格式化输出,开启浮点支持后,也调用了
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分级输出控制等,让输出管理起来更便捷