【开放原子训练营第三季RT-Thread Nano学习营心得】Rtthread中的打印函数问题

【开放原子训练营第二季RT-Thread Nano学习营心得】Rtthread中的打印函数问题

1 概述

2023年4月22号参加开放原子训练营第三季RT-Thread Nano的线下培训培训的老师们都很专业,讲了不少入门级知识,线下的交流群里有位大哥说要带孩子去听课,感触很深,小朋友们都这么上进了么~到了现场发现真的是老中青少四代齐聚啊!感慨一下我们国产嵌入式操作系统做这么好,对于国内的嵌入式工程师们也是件值得自豪的事儿。虽然是入门级培训,但对RT-Studio的操作还是熟悉了一把,以前都是用MDK的由于工作原因,可能后续还是会继续使用MDK但RT-Studio还是让人耳目一新,国产的操作系统配上国产环境生态已经健全起来了,之所以继续使用MDK还是RT-Studio需要联网才能发挥全部亮点的原因。
进入正题,RT的打印函数rt_kprintf,在刚接触时很让人诧异,这么完善的系统中为什么打印函数却不完备,现场培训结尾有自由提问时间,我向现场讲解的老师提出该问题:
(1) RT的rt_kprintf函数为什么不能打印浮点数即%f;
(2) 使用sprintf或sprintf_s函数输出字符串后再用rt_kprintf可以么;
现场的讲解人员回答:
(1) 现在的rt_kprintf可以打印浮点数了,但需要在RT-Studio中安装一个软件包,然后演示软件包安装及配置,并解释说原本的rt_kprintf不能打印%f是因为容易出错,但没有解释为什么容易出错;
(2) 使用sprintf或sprintf_s函数输出%f字符串后再用rt_kprintf输出是可以的。

2 printf实现原理

2.1 rt_kprintf实现原理

由于我是个比较保守的人,所以一直使用rt-thread的nano比较低的版本,一直在用的是3.1.3,rt-thread3.1.3中rt_kprintf实现代码如下

void rt_kprintf(const char *fmt, ...)
{
    va_list args;
    rt_size_t length;
    static char rt_log_buf[RT_CONSOLEBUF_SIZE];
    va_start(args, fmt);
    length = rt_vsnprintf(rt_log_buf, sizeof(rt_log_buf) - 1, fmt, args);
    if (length > RT_CONSOLEBUF_SIZE - 1)
        length = RT_CONSOLEBUF_SIZE - 1;
    rt_hw_console_output(rt_log_buf);
    va_end(args);
}

由于我不使用设备,所以不相关的部分被忽略掉,可以看到这里同样用到了可变参数,可变参数意思就是不规定参数有多少,通通压入函数栈。定义了rt_log_buf,这个数组就是RT向串口打印的数据缓存,大小RT_CONSOLEBUF_SIZE在rtconfig.h中定义默认是128字节,由于最后一个字节是‘\0’所以有效长度是RT_CONSOLEBUF_SIZE-1。va_start(args, fmt)将从函数栈中从低地址中将压栈数据读出来,rt_vsnprintf就是将这些数据按%c、%d、%x等按数据长度提取并按格式输出了,其中就是没有%f。

2.2 sprintf、sprintf_s实现原理

sprintf()与sprintf_s()都使用格式化字符串来指定串的格式,在格式串内部使用一些以“%”开头的格式说明符来占据一个位置,在栈中按顺序提取参数,在参数提取过程中同样用到了val_list可变参数的相关功能。
sprintf()与sprintf_s()的区别在于sprintf不指定字符长度容易造成溢出,sprintf_s是sprintf的安全版本,需指定字符长度,使得函数应用更加安全,在高级语言的编辑器中如果sprintf甚至会提示使用sprintf_s来替换,也是出于安全考虑。
sprintf、sprintf_s的输出格式包括标识符、宽度、精度、指定参数等。这为sprintf提供了及其丰富的输出格式。

2.3 rt_kprintf没有%f的分析

rt-thread中rt_kprintf仅实现部分简单的格式化字符输出可以在rt_vsnprintf函数中看到仅对%后字符‘c’、‘s’、‘p’、‘%’、‘o’、‘x’、‘d’、、‘i’、‘u’进行了处理。格式并不完全,甚至打印精度都是可选项,但这些对于整形和字符来说一方面是足够使用的,另一方面实现起来也比较容易,但对于浮点数而言,标示符、宽度、精度等格式难以和整形及字符进行统一格式规整,并且其可出现的组合也是相当复杂。
RT一方面想要完全自成体系,全部函数实现自身集成,在体系健全的前提下让所有功能函数可以统一命名规则,另一方面我觉得或多或少有些想摆脱一些看不见的束缚的影子。在实现了部分功能的时候做出一些放弃应该有其更深层次的原因,毕竟庞大的系统都做出来了一个小小的格式化输出做到完整并正确并非难事。

3 在RT中打印浮点数

我们可以在不安装软件包的情况下需要打印浮点数的时候加载stdio.h头文件后先调用sprintf生成包含浮点数的字符串,再通过rt_kprintf输出该字符串来实现浮点数的输出,示例如下:

char buf[128]={0};
len=sprintf(tmp,"%.5f",(float)3.1415926);
rt_kprintf(%s”,tmp);

输出:3.14159。

4 结束语

通过简单的函数转换就可以完善rt_kprintf的功能,在非RT-Studio的环境下也能很好的实现字符格式化输出。RT是非常好的嵌入式操作系统,对国内的嵌入式的工程师来时无疑是国产化的福音,我能看到周围的人都在从UCOS、FREERTOS转换到RT,多么让人欢欣鼓舞的一件事~

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值