J-Link RTT使用

一、测试环境
1> 测试环境
系统:WIN7
MDK:keil v5.26
开发板:GD32F303C-EVAL
固件库:V1.0.2
FreeRTOS版本:V10.4.0
支持内核: ARM Cortex-M0/M0+/M1/M3/M4/M7/M23/M33 and Renesas RX100/200/600
更多详情可以参考官网:RTT
中文可以参考:仿真器代替串口打印
2> 找到JLINK驱动的安装目录。
在这里插入图片描述
解压后可以看到如下图所示文件,Example目录是参考的demo,RTT和Syscalls文件夹下就是移植所需要的文件
在这里插入图片描述
RTT目录内容:
在这里插入图片描述
Syscalls目录内容:
在这里插入图片描述
二、添加文件到工程
1> 在工程下新建一个文件夹,将上述中提到的文件放到这个文件夹中
在这里插入图片描述

2> 添加文件到工程
在这里插入图片描述
3> 添加头文件路径
在这里插入图片描述
三、测试使用
1>测试代码如下:

#include "gd32f30x.h"
#include "led.h"
#include "systick.h"
#include "timer.h"
#include <stdio.h>
#include "key.h"
#include "gpio.h"
#include "usart_shell.h"
#include "shell_port.h"
#include "gd25qxx.h"
#include <math.h>
#include <string.h>
#include "SEGGER_RTT.h"

#if 0
/* USER CODE BEGIN 0 */
int test(int i, char ch, char *str)
{
    printf("input int: %d, char: %c, string: %s\r\n", i, ch, str);
	
	return 0;
}

int func(int argc, char *agrv[])
{
    printf("%dparameter(s)\r\n", argc);
    for (char i = 1; i < argc; i++)
    {
        printf("%s\r\n", agrv[i]);
    }
		return 0;
}
SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0)|SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN), func, func, test2);

//导出到命令列表里
SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0)|SHELL_CMD_TYPE(SHELL_TYPE_CMD_FUNC), test, test, test);

/* USER CODE END 0 */
#endif

volatile int _Cnt=0;
unsigned char *out_float(double value, unsigned char decimal_digit, unsigned char *output_length);
int main(void)
{
	 float value = 3.1415;
   unsigned char length;
   
		 
	delay_init();
	/*添加上行数据缓冲区,函数原型:
	int SEGGER_RTT_ConfigUpBuffer(unsigned BufferIndex, const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags) 
	若BufferIndex=0,RTT组件将使用默认的缓冲和大小,其大小由SEGGER_RTT_Conf.h中的BUFFER_SIZE_UP决定,所以使用这个缓存区0比较简单,
	令BufferIndex=0,pBuffer=NULL,BufferSize=NULL
	方向:MCU-->PC
	同理:SEGGER_RTT_ConfigDownBuffer,和它一样,仅仅方向不同,PC-->MCU
	*/
  SEGGER_RTT_ConfigUpBuffer(0, NULL, NULL, 0, SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL);

	/*打印字符串函数*/
  SEGGER_RTT_WriteString(0, "SEGGER Real-Time-Terminal Sample\r\n\r\n");
  SEGGER_RTT_WriteString(0, "###### Testing SEGGER_printf() ######\r\n");
	SEGGER_RTT_WriteString(0, "###### 中文 ######\r\n");
	SEGGER_RTT_printf(0,"value = %s \n",out_float(value,4,&length));
	/*与C库中printf类似,区别是不支持浮点数*/
  SEGGER_RTT_printf(0, "printf Test: %%c,         'S' : %c.\r\n", 'S');
  SEGGER_RTT_printf(0, "printf Test: %%5c,        'E' : %5c.\r\n", 'E');
  SEGGER_RTT_printf(0, "printf Test: %%-5c,       'G' : %-5c.\r\n", 'G');
  SEGGER_RTT_printf(0, "printf Test: %%5.3c,      'G' : %-5c.\r\n", 'G');
  SEGGER_RTT_printf(0, "printf Test: %%.3c,       'E' : %-5c.\r\n", 'E');
  SEGGER_RTT_printf(0, "printf Test: %%c,         'R' : %c.\r\n", 'R');

  SEGGER_RTT_printf(0, "printf Test: %%s,      \"RTT\" : %s.\r\n", "RTT");
  SEGGER_RTT_printf(0, "printf Test: %%s, \"RTT\\r\\nRocks.\" : %s.\r\n", "RTT\r\nRocks.");

  SEGGER_RTT_printf(0, "printf Test: %%u,       12345 : %u.\r\n", 12345);
  SEGGER_RTT_printf(0, "printf Test: %%+u,      12345 : %+u.\r\n", 12345);
  SEGGER_RTT_printf(0, "printf Test: %%.3u,     12345 : %.3u.\r\n", 12345);
  SEGGER_RTT_printf(0, "printf Test: %%.6u,     12345 : %.6u.\r\n", 12345);
  SEGGER_RTT_printf(0, "printf Test: %%6.3u,    12345 : %6.3u.\r\n", 12345);
  SEGGER_RTT_printf(0, "printf Test: %%8.6u,    12345 : %8.6u.\r\n", 12345);
  SEGGER_RTT_printf(0, "printf Test: %%08u,     12345 : %08u.\r\n", 12345);
  SEGGER_RTT_printf(0, "printf Test: %%08.6u,   12345 : %08.6u.\r\n", 12345);
  SEGGER_RTT_printf(0, "printf Test: %%0u,      12345 : %0u.\r\n", 12345);
  SEGGER_RTT_printf(0, "printf Test: %%-.6u,    12345 : %-.6u.\r\n", 12345);
  SEGGER_RTT_printf(0, "printf Test: %%-6.3u,   12345 : %-6.3u.\r\n", 12345);
  SEGGER_RTT_printf(0, "printf Test: %%-8.6u,   12345 : %-8.6u.\r\n", 12345);
  SEGGER_RTT_printf(0, "printf Test: %%-08u,    12345 : %-08u.\r\n", 12345);
  SEGGER_RTT_printf(0, "printf Test: %%-08.6u,  12345 : %-08.6u.\r\n", 12345);
  SEGGER_RTT_printf(0, "printf Test: %%-0u,     12345 : %-0u.\r\n", 12345);

  SEGGER_RTT_printf(0, "printf Test: %%u,      -12345 : %u.\r\n", -12345);
  SEGGER_RTT_printf(0, "printf Test: %%+u,     -12345 : %+u.\r\n", -12345);
  SEGGER_RTT_printf(0, "printf Test: %%.3u,    -12345 : %.3u.\r\n", -12345);
  SEGGER_RTT_printf(0, "printf Test: %%.6u,    -12345 : %.6u.\r\n", -12345);
  SEGGER_RTT_printf(0, "printf Test: %%6.3u,   -12345 : %6.3u.\r\n", -12345);
  SEGGER_RTT_printf(0, "printf Test: %%8.6u,   -12345 : %8.6u.\r\n", -12345);
  SEGGER_RTT_printf(0, "printf Test: %%08u,    -12345 : %08u.\r\n", -12345);
  SEGGER_RTT_printf(0, "printf Test: %%08.6u,  -12345 : %08.6u.\r\n", -12345);
  SEGGER_RTT_printf(0, "printf Test: %%0u,     -12345 : %0u.\r\n", -12345);
  SEGGER_RTT_printf(0, "printf Test: %%-.6u,   -12345 : %-.6u.\r\n", -12345);
  SEGGER_RTT_printf(0, "printf Test: %%-6.3u,  -12345 : %-6.3u.\r\n", -12345);
  SEGGER_RTT_printf(0, "printf Test: %%-8.6u,  -12345 : %-8.6u.\r\n", -12345);
  SEGGER_RTT_printf(0, "printf Test: %%-08u,   -12345 : %-08u.\r\n", -12345);
  SEGGER_RTT_printf(0, "printf Test: %%-08.6u, -12345 : %-08.6u.\r\n", -12345);
  SEGGER_RTT_printf(0, "printf Test: %%-0u,    -12345 : %-0u.\r\n", -12345);

  SEGGER_RTT_printf(0, "printf Test: %%d,      -12345 : %d.\r\n", -12345);
  SEGGER_RTT_printf(0, "printf Test: %%+d,     -12345 : %+d.\r\n", -12345);
  SEGGER_RTT_printf(0, "printf Test: %%.3d,    -12345 : %.3d.\r\n", -12345);
  SEGGER_RTT_printf(0, "printf Test: %%.6d,    -12345 : %.6d.\r\n", -12345);
  SEGGER_RTT_printf(0, "printf Test: %%6.3d,   -12345 : %6.3d.\r\n", -12345);
  SEGGER_RTT_printf(0, "printf Test: %%8.6d,   -12345 : %8.6d.\r\n", -12345);
  SEGGER_RTT_printf(0, "printf Test: %%08d,    -12345 : %08d.\r\n", -12345);
  SEGGER_RTT_printf(0, "printf Test: %%08.6d,  -12345 : %08.6d.\r\n", -12345);
  SEGGER_RTT_printf(0, "printf Test: %%0d,     -12345 : %0d.\r\n", -12345);
  SEGGER_RTT_printf(0, "printf Test: %%-.6d,   -12345 : %-.6d.\r\n", -12345);
  SEGGER_RTT_printf(0, "printf Test: %%-6.3d,  -12345 : %-6.3d.\r\n", -12345);
  SEGGER_RTT_printf(0, "printf Test: %%-8.6d,  -12345 : %-8.6d.\r\n", -12345);
  SEGGER_RTT_printf(0, "printf Test: %%-08d,   -12345 : %-08d.\r\n", -12345);
  SEGGER_RTT_printf(0, "printf Test: %%-08.6d, -12345 : %-08.6d.\r\n", -12345);
  SEGGER_RTT_printf(0, "printf Test: %%-0d,    -12345 : %-0d.\r\n", -12345);

  SEGGER_RTT_printf(0, "printf Test: %%x,      0x1234ABC : %x.\r\n", 0x1234ABC);
  SEGGER_RTT_printf(0, "printf Test: %%+x,     0x1234ABC : %+x.\r\n", 0x1234ABC);
  SEGGER_RTT_printf(0, "printf Test: %%.3x,    0x1234ABC : %.3x.\r\n", 0x1234ABC);
  SEGGER_RTT_printf(0, "printf Test: %%.6x,    0x1234ABC : %.6x.\r\n", 0x1234ABC);
  SEGGER_RTT_printf(0, "printf Test: %%6.3x,   0x1234ABC : %6.3x.\r\n", 0x1234ABC);
  SEGGER_RTT_printf(0, "printf Test: %%8.6x,   0x1234ABC : %8.6x.\r\n", 0x1234ABC);
  SEGGER_RTT_printf(0, "printf Test: %%08x,    0x1234ABC : %08x.\r\n", 0x1234ABC);
  SEGGER_RTT_printf(0, "printf Test: %%08.6x,  0x1234ABC : %08.6x.\r\n", 0x1234ABC);
  SEGGER_RTT_printf(0, "printf Test: %%0x,     0x1234ABC : %0x.\r\n", 0x1234ABC);
  SEGGER_RTT_printf(0, "printf Test: %%-.6x,   0x1234ABC : %-.6x.\r\n", 0x1234ABC);
  SEGGER_RTT_printf(0, "printf Test: %%-6.3x,  0x1234ABC : %-6.3x.\r\n", 0x1234ABC);
  SEGGER_RTT_printf(0, "printf Test: %%-8.6x,  0x1234ABC : %-8.6x.\r\n", 0x1234ABC);
  SEGGER_RTT_printf(0, "printf Test: %%-08x,   0x1234ABC : %-08x.\r\n", 0x1234ABC);
  SEGGER_RTT_printf(0, "printf Test: %%-08.6x, 0x1234ABC : %-08.6x.\r\n", 0x1234ABC);
  SEGGER_RTT_printf(0, "printf Test: %%-0x,    0x1234ABC : %-0x.\r\n", 0x1234ABC);

  SEGGER_RTT_printf(0, "printf Test: %%p,      &_Cnt      : %p.\r\n", &_Cnt);

  SEGGER_RTT_WriteString(0, "###### SEGGER_printf() Tests done. ######\r\n");
  do {
    _Cnt++;
		SEGGER_RTT_printf(0, "%d\r\n", _Cnt);
		delay_xms(100);
  } while (1);
}
/*
SEGGER_RTT_printf不支持浮点
这里引用网友写的一个浮点转字符的函数:
https://www.cnblogs.com/snowsad/p/12076740.html
Parameter:
Value						Meaning
value						想要打印的数据
decimal_digit		数字小数部分的位数
_output_length	输出字符串的长度

Return Value:
Value	Meaning
unsigned char*	返回一个字符串指针
*/
unsigned char *out_float(double value, unsigned char decimal_digit, unsigned char *output_length)
{
	unsigned char _output[20];
	unsigned long integer;
	unsigned long decimal;
	unsigned char _output_length = 0;
	unsigned char _length_buff = 0;
	static unsigned char *return_pointer;
	unsigned char signal_flag;
	if (value < 0)
		signal_flag = 1;
	else
		signal_flag = 0;
	value = fabs(value);
	integer = (unsigned long)value;
	decimal = (unsigned long)((value - integer) * pow(10, decimal_digit));

	unsigned long integer_buff = integer;
	unsigned long decimal_buff = decimal;

	while (1)
	{
		if (integer / 10 != 0)
			_length_buff++;
		else
		{
			_length_buff++;
			break;
		}
		integer = integer / 10;
	}
	for (int i = 0; i < _length_buff; i++)
	{
		if (i == _length_buff - 1)
			_output[_output_length] = integer_buff % 10 + 0x30;
		else
		{
			//_output[_output_length] = integer_buff / 10 % 10 + 0x30;
			_output[_output_length] = integer_buff / (unsigned long)pow(10, _length_buff - i - 1) % 10 + 0x30;
			integer_buff = integer_buff % (unsigned long)pow(10, _length_buff - i - 1);
			//integer_buff = integer_buff % 10;
		}
		_output_length++;
	}
	_output[_output_length] = '.';
	_output_length++;
	_length_buff = 0;
	while (1)
	{
		if (decimal / 10 != 0)
			_length_buff++;
		else
		{
			_length_buff++;
			break;
		}
		decimal = decimal / 10;
	}
	for (int i = 0; i < _length_buff; i++)
	{
		if (i == _length_buff - 1)
			_output[_output_length] = decimal_buff % 10 + 0x30;
		else
		{
			_output[_output_length] = decimal_buff / (unsigned long)pow(10, _length_buff-i-1) % 10 + 0x30;
			decimal_buff = decimal_buff % (unsigned long)pow(10, _length_buff - i - 1);
		}
			
		_output_length++;
	}
	_output[_output_length] = 0x00;
	_output_length++;
	return_pointer = (unsigned char *)realloc(return_pointer,_output_length);

	*output_length = _output_length - 1;
	if (return_pointer == 0)
		return 0;
	else
	{
		if (signal_flag == 1)
		{
			return_pointer[0] = '-';
			memcpy(return_pointer+1, _output, _output_length);
		}
		else
			memcpy(return_pointer, _output, _output_length);
	}
	return return_pointer;
}


2>编译下载,重新上电,然后打开J-Link RTT Viewer,点击OK就可以看到输出结果,如果想仿真调试,需要先进入仿真状态,然后在点击OK。
在这里插入图片描述
3> 测试结果
在这里插入图片描述
4>将上面的代码编译,进入仿真,然后打开J-Link RTT Client软件,如下图,说明连接成功。
在这里插入图片描述
5>点击全速运行或单步调试就可以在窗口看到相应的打印信息。
在这里插入图片描述
6>client与viewer区别
client需要配合仿真使用,而viewer不需要。
client支持中文输出,而viewer不支持
四、输入测试
1>输入单个字符:
代码如下:

volatile int _Cnt;
volatile int _Delay;

static char r;
char acIn[20];
int ReadNum=0;
uint16_t i=0;
/*********************************************************************
*
*       main
*/
int main(void) {

 	 SEGGER_RTT_WriteString(0, "SEGGER Real-Time-Terminal Sample\r\n");
 	 SEGGER_RTT_ConfigUpBuffer(0, NULL, NULL, 0, SEGGER_RTT_MODE_NO_BLOCK_SKIP);
 
	while(1)
	{
		/*读取一个键值的第一种方式*/
		/*判断RTT的BUF缓冲区中是否有可用数据*/
		if(SEGGER_RTT_HasKey())
		{
				/*从RTT的BUF0的缓冲区内读取一个键值*/
			  r = SEGGER_RTT_GetKey();
				if(r=='q')
				{
					SEGGER_RTT_WriteString(0,"input :q\r\n");
				}
		}
		/*读取一个键值的第二种方式*/
//		do{
//			r = SEGGER_RTT_WaitKey();
//			SEGGER_RTT_printf(0,"input key is: %c\r\n",r);
//		}while(r != 'q');
//		SEGGER_RTT_printf(0,"host has been read q\r\n");
		

	}

}

注意,这种读取键值的方式,只支持Terminal0,打开J-Link RTT Viewer进行如下配置:
在这里插入图片描述
如果没有自动连接,可以按F2再次进行连接,F3为断开连接。
测试结果:
在这里插入图片描述

2> 输入多个字符串
测试代码:

volatile int _Cnt;
volatile int _Delay;

static char r;
char acIn[20];
int ReadNum=0;
uint16_t i=0;
/*********************************************************************
*
*       main
*/
int main(void) {

  SEGGER_RTT_WriteString(0, "SEGGER Real-Time-Terminal Sample\r\n");
  SEGGER_RTT_ConfigUpBuffer(0, NULL, NULL, 0, SEGGER_RTT_MODE_NO_BLOCK_SKIP);
 
	while(1)
	{
		/*判断RTT的BUF缓冲区中是否有可用数据*/
		if(SEGGER_RTT_HasKey())
		{
				/*从RTT的BUF0的缓冲区内读取一个键值*/
			  ReadNum = SEGGER_RTT_Read(0,&acIn[0],sizeof(acIn));
				for(i=0;i<20;i++)
				{
					if(0x0A != acIn[i])
					{
						ReadNum++;
					}
					else
					{
						break;
					}
				}
				SEGGER_RTT_Write(0,acIn,ReadNum);
				ReadNum=0;
				memset(acIn,0,sizeof(acIn));
		}
	}

}

这种方式支持多个Terminal,打开J-Link RTT Viewer进行如下配置:
在这里插入图片描述
测试结果:
在这里插入图片描述

五、使用小技巧
可以使用多个Terminal终端来输出不同的内容,比如终端0输出打印信息,终端1输出错误信息,J-Link RTT Viewer最多支持16个终端。
另外,还可以配置字体不同的打印颜色,方便识别,这个要远比串口好用的多。
测试代码如下:

static void _Delay(int period) 
{
	int i = 100000*period;
	do { ; } while (i--);
}
int main(void) 
{
	int cnt=0;
	while(1)
	{
		SEGGER_RTT_SetTerminal(1);
		SEGGER_RTT_WriteString(0,RTT_CTRL_RESET"Red: "\
														RTT_CTRL_TEXT_RED"This text is red."\
														RTT_CTRL_TEXT_BLACK""\
														RTT_CTRL_BG_BRIGHT_GREEN"This background is green."\
														RTT_CTRL_RESET"Normal text again.\r\n");
		_Delay(200);
		cnt++;
		SEGGER_RTT_SetTerminal(0);
		SEGGER_RTT_WriteString(0,RTT_CTRL_RESET"Terminal:\r\n");
		SEGGER_RTT_printf(0,"%sCounter:%s%d\r\n",RTT_CTRL_RESET,RTT_CTRL_TEXT_YELLOW,cnt);
		if(cnt > 5)
		{
			SEGGER_RTT_TerminalOut(0,RTT_CTRL_TEXT_RED"Counter overflow!\r\n");
			cnt=0;
		}
	}
	return 0;
}

测试结果:
在这里插入图片描述
这个是所有终端的信息,不过这个颜色是和我们想要测试的不同的,不过信息是正确的。在这里插入图片描述
在这里插入图片描述
这里可以看出Terminal0, Terminal1这两个终端既是我们设置的颜色的输出。

  • 2
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值