J-Link RTT调试 教程


前言

在嵌入式开发过程中,经常需要进行打印调试,通常使用串口进行打印输出,
但通常串口资源有限,这时就可以通过J-Link工具里面自带的RTT实现打印,从而节约一个串口资源。


一、安装J-Link驱动

J-Link官网下载驱动
在这里插入图片描述
驱动自行选择一个版本进行安装,不建议安装太高的版本,毕竟大家使用的J-Link可能不是正品的。

二、查找RTT源文件

在J-Link驱动的安装路径下,找到RTT
在这里插入图片描述
在这里插入图片描述

最后直接将RTT添加到工程中即可(复制SEGGER_RTT_Conf.h到RTT文件夹)
在这里插入图片描述
在这里插入图片描述

三、使用

自行在工程中添加头文件,添加头文件的路径
使用非常简单,无需初始化,就添加下面3行代码就可以输出

#include "SEGGER_RTT.h"
SEGGER_RTT_SetTerminal(0);						// 选择终端(输入0-15)
SEGGER_RTT_printf(0,"Terminal(0) text \r\n");	// 输出日志

在这里插入图片描述

四、打开J-Link RTT Viewer

在这里插入图片描述
在这里插入图片描述
不出意外就可以正常输出了
在这里插入图片描述
可以手动打开相对应的终端
快捷键
F2:快速连接
F3:断开连接
在这里插入图片描述

五、输出不同颜色的文字

在这里插入图片描述

大家可以输入以下代码,体验一下

//方法1
SEGGER_RTT_SetTerminal(0);
SEGGER_RTT_printf(0,RTT_CTRL_TEXT_RED"Terminal(0)\r\n");

//方法2
SEGGER_RTT_SetTerminal(1);
SEGGER_RTT_printf(0,RTT_CTRL_TEXT_BRIGHT_RED);
SEGGER_RTT_printf(0,"Terminal(1)\r\n");

六、自定义封装一下

如果在程序中直接调用下面这两行代码,能用,但是感觉不优雅。

SEGGER_RTT_SetTerminal(0);
SEGGER_RTT_printf(0,RTT_CTRL_TEXT_RED"Terminal(0)\r\n");

我们可以使用#define进行定义一下

#define LOG_DATA(fmt, ...) SEGGER_RTT_SetTerminal(0); SEGGER_RTT_printf(0, fmt, ##__VA_ARGS__)

#define LOG_STATUS(fmt, ...) SEGGER_RTT_SetTerminal(1); SEGGER_RTT_printf(0, fmt, ##__VA_ARGS__)

#define LOG_ERROR(fmt, ...) SEGGER_RTT_SetTerminal(2); SEGGER_RTT_printf(0, fmt, ##__VA_ARGS__)

在程序中调用下面封装好得宏,简单又优雅 不支持输出中文的

LOG_DATA("LOG_DATA\r\n");

LOG_STATUS("LOG_STATUS\r\n");

LOG_ERROR("LOG_ERROR\r\n");

七、float类型输出

float类型数据是无法直接打印的

float float_data  = 3.14;
LOG_DATA("float_data = %f \r\n",float_data );

不过我们可以借用sprintf函数

#include<stdio.h>

char str[40];
float float_data  = 3.14;

sprintf(str,"float_data = %f \r\n",float_data );
LOG_DATA("%s",str);

八、自定义输出

Jlink_RTT.c

#include "Jlink_RTT.h"
#include <string.h>

static char log_buf[256]; // 日志缓存buff

/**
 * @brief   普通日志输出,不附带任何参数(白色)
 *
 * @param format    输出日志
 * @param ...
 */
void PRINTF_RTT_LOG(const char *format, ...)
{
    va_list args;
    va_start(args, format);
    vsnprintf(log_buf, sizeof(log_buf), format, args);
    printf_rtt("%s", log_buf);
    va_end(args);
}

/**
 * @brief   类型(LOGD)白色字体
 *
 * @param func      当前函数名
 * @param line      当前函数位置
 * @param format    输出日志
 * @param ...
 */
void PRINTF_RTT_LOGD(const char *func, const long line, const char *format, ...)
{
    va_list args;
    va_start(args, format);
    printf_rtt("(%s:%ld) ", func, line);
    vsnprintf(log_buf, sizeof(log_buf), format, args);
    printf_rtt("%s\r\n", log_buf);
    va_end(args);
}

/**
 * @brief   类型(LOGI)绿色字体
 *
 * @param func      当前函数名
 * @param line      当前函数位置
 * @param format    输出日志
 * @param ...
 */
void PRINTF_RTT_LOGI(const char *func, const long line, const char *format, ...)
{
    va_list args;
    va_start(args, format);
    printf_rtt(RTT_CTRL_TEXT_BRIGHT_GREEN); // 字体颜色:绿色
    printf_rtt("(%s:%ld) ", func, line);
    vsnprintf(log_buf, sizeof(log_buf), format, args);
    printf_rtt("%s\r\n", log_buf);
    printf_rtt(RTT_CTRL_RESET); // 恢复默认字体颜色
    va_end(args);
}

/**
 * @brief   类型(LOGE)红色字体
 *
 * @param func      当前函数名
 * @param line      当前函数位置
 * @param format    输出日志
 * @param ...
 */
void PRINTF_RTT_LOGE(const char *func, const long line, const char *format, ...)
{
    va_list args;
    va_start(args, format);
    printf_rtt(RTT_CTRL_TEXT_BRIGHT_RED); // 字体颜色:红色
    printf_rtt("(%s:%ld) ", func, line);
    vsnprintf(log_buf, sizeof(log_buf), format, args);
    printf_rtt("%s\r\n", log_buf);
    printf_rtt(RTT_CTRL_RESET); // 恢复默认字体颜色
    va_end(args);
}

/**
 * @brief   类型(LOGW)紫色字体
 *
 * @param func      当前函数名
 * @param line      当前函数位置
 * @param format    输出日志
 * @param ...
 */
void PRINTF_RTT_LOGW(const char *func, const long line, const char *format, ...)
{
    va_list args;
    va_start(args, format);
    printf_rtt(RTT_CTRL_TEXT_BRIGHT_MAGENTA); // 字体颜色:紫色
    printf_rtt("(%s:%ld) ", func, line);
    vsnprintf(log_buf, sizeof(log_buf), format, args);
    printf_rtt("%s\r\n", log_buf);
    printf_rtt(RTT_CTRL_RESET); // 恢复默认字体颜色
    va_end(args);
}

/**
 * @brief   类型(LOGV)黄色字体
 *
 * @param func      当前函数名
 * @param line      当前函数位置
 * @param format    输出日志
 * @param ...
 */
void PRINTF_RTT_LOGV(const char *func, const long line, const char *format, ...)
{
    va_list args;
    va_start(args, format);
    printf_rtt(RTT_CTRL_TEXT_BRIGHT_YELLOW); // 字体颜色:黄色
    printf_rtt("(%s:%ld) ", func, line);
    vsnprintf(log_buf, sizeof(log_buf), format, args);
    printf_rtt("%s\r\n", log_buf);
    printf_rtt(RTT_CTRL_RESET); // 恢复默认字体颜色
    va_end(args);
}

/**
 * @brief 以16进制的方式输出(青色)
 *
 * @param func      当前函数名
 * @param line      当前函数位置
 * @param title     标题
 * @param len       输出数据长度
 * @param format    输出16进制
 * @param ...
 */
void PRINTF_RTT_HEX(const char *func, const long line, const char *title, char *format, const int len)
{
    printf_rtt(RTT_CTRL_TEXT_BRIGHT_CYAN); // 字体颜色:青色
    printf_rtt("(%s:%ld) %s[%d]= ", func, line, title, len);
    for (int i = 0; i < len; i++)
    {
        printf_rtt("%02X ", *(format + i));
    }
    printf_rtt("\r\n");
    printf_rtt(RTT_CTRL_RESET); // 恢复默认字体颜色
}

/**
 * @brief 以16进制的方式输出(红色)
 *
 * @param func      当前函数名
 * @param line      当前函数位置
 * @param title     标题
 * @param len       输出数据长度
 * @param format    输出16进制
 * @param ...
 */
void PRINTF_RTT_ERR_HEX(const char *func, const long line, const char *title, char *format, const int len)
{
    printf_rtt(RTT_CTRL_TEXT_BRIGHT_RED); // 字体颜色:红色
    printf_rtt("(%s:%ld) %s[%d]= ", func, line, title, len);
    for (int i = 0; i < len; i++)
    {
        printf_rtt("%02X ", *(format + i));
    }
    printf_rtt("\r\n");
    printf_rtt(RTT_CTRL_RESET); // 恢复默认字体颜色
}

Jlink_RTT.h

#ifndef _JLINK_RTT_H__
#define _JLINK_RTT_H__

#include "SEGGER_RTT.h"
#include <stdio.h>
#include <stdarg.h> // 包含 va_list 相关宏的头文件

/************************************************
              通过JLink-RTT输出日志
*************************************************/

#if 1
#define printf_rtt(fmt, ...)   \
    SEGGER_RTT_SetTerminal(0); \
    SEGGER_RTT_printf(0, fmt, ##__VA_ARGS__)
#else
#define printf_rtt(fmt, ...)
#endif

extern void PRINTF_RTT_LOG(const char *format, ...);
extern void PRINTF_RTT_LOGD(const char *func, const long line, const char *format, ...);
extern void PRINTF_RTT_LOGI(const char *func, const long line, const char *format, ...);
extern void PRINTF_RTT_LOGE(const char *func, const long line, const char *format, ...);
extern void PRINTF_RTT_LOGW(const char *func, const long line, const char *format, ...);
extern void PRINTF_RTT_LOGV(const char *func, const long line, const char *format, ...);
extern void PRINTF_RTT_HEX(const char *func, const long line, const char *title, char *format, const int len);
extern void PRINTF_RTT_ERR_HEX(const char *func, const long line, const char *title, char *format, const int len);

#define RTT_LOG(...) PRINTF_RTT_LOG(__VA_ARGS__);                       // 白色
#define RTT_LOGI(...) PRINTF_RTT_LOGI(__func__, __LINE__, __VA_ARGS__); // 绿色
#define RTT_LOGD(...) PRINTF_RTT_LOGD(__func__, __LINE__, __VA_ARGS__); // 白色
#define RTT_LOGE(...) PRINTF_RTT_LOGE(__func__, __LINE__, __VA_ARGS__); // 红色
#define RTT_LOGW(...) PRINTF_RTT_LOGW(__func__, __LINE__, __VA_ARGS__); // 紫色
#define RTT_LOGV(...) PRINTF_RTT_LOGV(__func__, __LINE__, __VA_ARGS__); // 黄色

#define RTT_HEX(title, data, len) \
    PRINTF_RTT_HEX(__func__, __LINE__, title, data, len); // 青色
#define RTT_ERR_HEX(title, data, len) \
    PRINTF_RTT_ERR_HEX(__func__, __LINE__, title, data, len); // 红色

#endif

使用示例

char name[]="Test";
RTT_LOGD("delete nfc id:%s\n", name);
uint8_t NFC_ID[10]={1,2,3,4,5};
RTT_HEX("id", NFC_ID, strlen(NFC_ID));

在这里插入图片描述

  • 4
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 11
    评论
### 回答1: jlink rtt(Real-Time Transfer)是针对实时系统开发者的一种调试技术,它使用了一种特殊的数据通信方式,通过调试接口和目标设备之间实现实时传输和交互。 在jlink rtt中,对于浮点数的处理与其他数据类型是相同的。可以使用相应的函数来发送和接收浮点数数据。通常,开发者可以使用jlink rtt提供的API来进行浮点数的发送和接收操作。 首先,开发者需要在目标设备的代码中集成jlink rtt库,并初始化RTT通信。然后,可以使用相关的API函数来发送浮点数数据到主机,或者从主机接收浮点数数据。 例如,可以使用函数`SEGGER_RTT_printf()`来发送浮点数数据到主机,函数的用法与打印其他类型数据类似,只需指定格式为"%f"即可。另外,可以使用函数`SEGGER_RTT_Read()`从主机接收浮点数数据,读取到的数据可以直接赋值给浮点数变量。 需要注意的是,由于嵌入式系统的特殊性,浮点数的运算和表示可能会受到硬件和编译器的限制。在使用jlink rtt进行浮点数调试时,开发者需要注意目标设备上浮点数运算的精度、范围和所使用的浮点数格式。 总的来说,jlink rtt可以很好地支持对浮点数数据的发送和接收,方便开发者进行实时调试和数据交互,提高开发效率。 ### 回答2: J-Link Real-Time Transfer(RTT)是Segger公司开发的一种调试技术,可以在嵌入式系统中实现实时的数据传输和交互。浮点(Floating-Point)是一种用于表示和处理实数的数学运算方法。结合起来,J-Link RTT浮点指的是在使用J-Link RTT技术进行嵌入式系统调试时,涉及到实数类型的数据传输和处理。 在使用J-Link RTT时,可以通过RTT通道将浮点数发送到主机端的调试工具,从而达到实时监视和分析嵌入式系统中涉及到的浮点数数据。这对于调试和性能优化很有帮助,特别是当系统涉及到复杂的浮点计算时。通过J-Link RTT浮点技术,开发人员可以随时监控实时的浮点数据并进行相关的分析,从而提高系统的稳定性和性能。 J-Link RTT浮点技术的应用还可以扩展到调试和验证嵌入式系统中的浮点算法的正确性。通过实时传输浮点数据,可以比较和验证系统的计算结果是否正确,从而提高开发效率和减少调试时间。同时,J-Link RTT还支持通过调试工具与嵌入式系统进行交互,可以发送指令和参数到系统中,以控制和调整浮点计算的过程。 综上所述,J-Link RTT浮点是一种在嵌入式系统调试中使用J-Link RTT技术实现实时浮点数据传输和分析的方法,可提高系统的性能和稳定性,并支持浮点算法的验证和调试
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值