好用的开源日志输出:SEGGER_RTT日志移植与应用指南
·
目录
1 什么是日志
日志索引用于记录日志在存储介质中的位置信息,断电日志存储区用于记录系统断电前的重要信息,日志存储区是日志信息的主体存储区域。
2 RTT的移植与使用
1. 下载与移植
第一步、下载Jlink驱动
SEGGER RTT是Jlink驱动里面的功能,要使用SEGGER RTT,就一定要下载Jlink 的驱动: 访问SEGGER的官网,在Jlink的下载页进行下载即可:
https://www.segger.com/downloads/jlink/

第二步、提取单片机上的RTT库
打开Jlink驱动的安装位置(默认为:C:\Program Files\SEGGER\JLink),不知道的话就右键打开文件位置去找

解压后我们会用到压缩包里面的这两个文件夹:

第三步、移植RTT
新建文件夹Middlewares->RTT,添加文件



然后添加组:

包含路径:

包含头文件:

进行初始化:

测试用例:
void SEGGER_RTT_Test(void)
{
SEGGER_RTT_Init(); //初始化只需在单片机运行开始时调用一次即可
uint32_t cycle = 1000;
while (cycle--)
{
SEGGER_RTT_printf(0, "0123456789abcdefgh\r\n");
}
}
为了更加优雅的使用,我们可以进行封装:
#ifndef _LOG_H_
#define _LOH_H_
#include "SEGGER_RTT.h"
#define LOG_DEBUG 1
#if LOG_DEBUG
#define LOG_PROTO(type,color,format,...) \
SEGGER_RTT_printf(0," %s%s"format"\r\n%s", \
color, \
type, \
##__VA_ARGS__, \
RTT_CTRL_RESET)
/* 清屏*/
#define LOG_CLEAR() SEGGER_RTT_WriteString(0, " "RTT_CTRL_CLEAR)
/* 无颜色日志输出 */
#define LOG(format,...) LOG_PROTO("","",format,##__VA_ARGS__)
/* 有颜色格式日志输出 */
#define LOGI(format,...) LOG_PROTO("I: ", RTT_CTRL_TEXT_BRIGHT_GREEN , format, ##__VA_ARGS__)
#define LOGW(format,...) LOG_PROTO("W: ", RTT_CTRL_TEXT_BRIGHT_YELLOW, format, ##__VA_ARGS__)
#define LOGE(format,...) LOG_PROTO("E: ", RTT_CTRL_TEXT_BRIGHT_RED , format, ##__VA_ARGS__)
#else
#define LOG_CLEAR()
#define LOG
#define LOGI
#define LOGW
#define LOGE
#endif
#endif // !_LOG_H_
用的时候先include “LOG.h”,然后这样用:

效果:

在viewer上查看



配置缓冲区的大小

2. 虚拟终端的用法
a.实现分流

b.改变终端输出字体颜色


c.重定向



d.输出浮点数
找到SEGGER_RTT_printf的实现


在SEGGER_RTT_vprintf的实现中加入输出浮点数的逻辑

case 'f':
case 'F': {
float fv = (float)va_arg(*pParamList, double); // 从参数列表获取float(可变参数默认提升为double)
unsigned int decimal_part;
unsigned int precision = NumDigits; // 使用NumDigits作为小数精度(解析格式时的.n),默认0位
// 处理负号
if (fv < 0.0f) {
_StoreChar(&BufferDesc, '-');
fv = -fv; // 转为正数处理,简化后续逻辑
}
// 处理整数部分(提取小数点前的数字)
int int_part = (int)fv;
_PrintInt(&BufferDesc, int_part, 10u, 0u, FieldWidth, FormatFlags); // 整数部分不需要NumDigits(精度),传0
// 处理小数部分(默认至少1位小数,若未指定精度则按1位处理)
if (precision == 0u) {
precision = 1u; // 若未指定精度(如%f),默认保留1位小数
}
_StoreChar(&BufferDesc, '.'); // 输出小数点
// 计算小数部分:将float放大 precision 倍,取整数后取模(避免浮点误差)
float decimal_f = fv - (float)int_part; // 提取小数部分(0 <= decimal_f < 1)
// 生成10^precision(如precision=2则为100),用于放大小数部分
unsigned int scale = 1u;
for (unsigned int i = 0u; i < precision; i++) {
scale *= 10u;
}
decimal_part = (unsigned int)(decimal_f * scale + 0.5f); // +0.5f 实现四舍五入
decimal_part %= scale; // 确保不超出precision位(防止浮点误差导致的溢出)
// 输出小数部分,不足precision位时补前导0(如0.5 → 0.50 当precision=2时)
_PrintUnsigned(&BufferDesc, decimal_part, 10u, precision, precision, 0u);
break;
}
测试:

3. SEGGER_RTT实现机制解析
DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。
更多推荐


所有评论(0)