RT-Thread|RT-Thread 入门学习笔记(vsnprintf来替代rt_vsnprintf来打印浮点)

前言

  • 有童鞋说在gcc下,vsnprintf来替代rt_vsnprintf来打印浮点会引发死机
  • 经过实际验证,没有发现死机
  • 但并不建议直接用vsnprintf来替代rt_vsnprintf,打印浮点多半用于调试,可以独立成一个专门的打印函数
  • vsnprintf只是用于把浮点格式化到字符串,只要字符串长度不溢出,理论上不会造成死机
  • 如果发现死机,需要确认打印的环境,如中断中,尤其在串口输出的情况下
测试例程
  • RT-Thread Studio arm-none-eabi-gcc 环境:未发现死机现象
  • Keil MDK5 环境:未发现死机现象
  • cygwin gcc 环境:未发现死机现象
  • 可以正常的用于浮点数的调试打印
/* * Copyright (c) 2006-2018, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * * Change Logs: * DateAuthorNotes * 2018-11-06SummerGiftchange to new framework */#include #include #include #include "drv_gpio.h" /* defined the LED0 pin: PA5 */ #define LED0_PINGET_PIN(A, 5)#include #define DBG_BUFF_MAX_LEN256/* 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; }int main(void) { double a = 334455.00123345; double b = 667788.14234234; dbg_printf("double a = %lf\r\n", a); int count = 1; /* set LED0 pin mode to output */ rt_pin_mode(LED0_PIN, PIN_MODE_OUTPUT); while (count++) { rt_pin_write(LED0_PIN, PIN_HIGH); dbg_printf("double a + b = %lf\r\n", a+b+count); rt_thread_mdelay(1000); rt_pin_write(LED0_PIN, PIN_LOW); rt_thread_mdelay(2000); }return RT_EOK; }

  • cygwin的测试
/* vsnprintf example */ #include #include #define DBG_BUFF_MAX_LEN256/* 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); printf("%s\r\n", rt_log_buf); return length; } int main () { double a = 123453.0001444; dbg_printf("%lf", a); return 0; }

输出效果
msh > \ | / - RT -Thread Operating System / | \4.1.0 build Feb3 2022 21:11:28 2006 - 2022 Copyright by RT-Thread team double a = 334455.001233 double a + b = 1002245.143576 msh >double a + b = 1002246.143576 double a + b = 1002247.143576 double a + b = 1002248.143576 double a + b = 1002249.143576 double a + b = 1002250.143576 double a + b = 1002251.143576 double a + b = 1002252.143576 double a + b = 1002253.143576 double a + b = 1002254.143576 double a + b = 1002255.143576 double a + b = 1002256.143576 double a + b = 1002257.143576 double a + b = 1002258.143576 double a + b = 1002259.143576 double a + b = 1002260.143576 double a + b = 1002261.143576

  • cygwin的打印:
$ ./a.exe 123453.000144

小结
  • rt_kprintf,采用不依赖标准C库的方式,主要目的是为了减少ROM(Flash)的占用
  • 如果实际中需要浮点打印(如打印到串口、打印到文件),可以基于vsnprintf编写一个简单的全功能格式打印函数
  • RT-Thread ulog可以开启浮点支持,开启后使用:vsnprintf

    推荐阅读