J-Link RTT调试 教程

本文介绍如何使用J-Link RTT进行嵌入式系统的调试工作,包括安装驱动、配置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));

在这里插入图片描述

九、重定向printf

int fputc(int c, FILE *f)
{
  char ch = (char)c;
  SEGGER_RTT_Write(0, &ch, 1);
  return c;
}
评论 14
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值