可提供操作系统级别的采样速度,远远大于jscope和vofa正常的串口通信,用于参数辨识+控制设计
1.啁啾信号
定义:频率随着时间增加或减小的信号。

使用C实现:
1 2 3 4 5 6 7 8 9 10 11 12 13
| float chirp = 0; float chirp_zero_phase= 0; float chirp_f0 = 0; float chirp_k = 0.0025; float chirp_t = 0; float chirp_f = 0; float Chrip_Amplitude = 6000; void Make_Chirp(int t) { chirp_f = chirp_f0 + chirp_k * t; chirp = Chrip_Amplitude*sinf(chirp_zero_phase + 2 * PI* (chirp_f0+chirp_k*0.5f*t)* t/1000); }
|
使用1ms定时器中断运行产生啁啾信号函数,运行120s,产生0-300Hz的幅值为6000的啁啾信号,图像如图所示。

香农采样定理:要想根据采样准确的再现信号,信号中必须不含有高于1/2采样速率的频率成分。
2.Jlink RTT
系统运行频率为1kHz,频率最大值可以根据香农采样定理初步确定为500Hz以下,然后可以根据系统具 体情况确定扫频最大频率。
Jlink RTT耗费系统资源少,不影响系统的实时性。RTT的性能明显高于其他将数据输出到主机的模式。平均一行文本可以在1微秒或更短的时间内输出。基本上相当于做一个memcopy()的时间。RTT速度由调用发送函数的速度决定,速度可以达到很高。局限在于无法通过曲线直观观察数据,无法用于在线调试。但用来做参数辨识及更细的分析很合适
2.1 移植RTT
RTT源码包在JLINK驱动的目录中。

将RTT文件夹复制到工程文件夹中,并在工程中新建RTT分组,将RTT文件中两个.c文件添加进来,并在魔术棒中添加RTT的头文件路径。之后可以正常使用Jlink RTT
2.2 使用RTT
常用函数 SEGGER_RTT_SetTerminal(unsigned char TerminalId) 该函数传入参数为终端ID,在Jlink RTT Viewer中可以打开不同终端窗口查看数据,同时在初始窗口中会 显示所有终端数据。 SEGGER_RTT_printf(unsigned BufferIndex, const char * sFormat, …) 该函数用于打印数据,常用参数格式为
1 2 3 4 5 6 7 8 9 10 11 12
| %[flags][Fieldwidth][.Precision]ConversionSpecifier Supported flags: -: 字段宽度内左对齐 +: 为有符号参数打印符号 0: 用0代替空格. 使用“-”或精度时忽略 Supported conversion specifiers: c: 将参数打印为一个字符 d: 将参数打印为有符号整数 u: 将参数打印为无符号整数 x: 将参数打印为十六进制整数 s: 打印参数指向的字符串 p: 将参数打印为 8 位十六进制整数.(参数应该是一个指向 void 的指针)
|
打印整型(u8 u16 u32 s8 s16 s32)时使用“d” 打印字符串时使用“s” 打印浮点数时,使用out_float函数将float型转换为字符串后打印。或通过在SEGGER_RTT_vprintf中添 加下列代码实现:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112
| #ifdef SEGGER_RTT_PRINT_FLOAT_ENABLE case 'f': case 'F': { float fv; fv = (float)va_arg(*pParamList, double); v = (int)fv; _PrintInt(&BufferDesc, v, 10u, NumDigits, FieldWidth, FormatFlags);
_StoreChar(&BufferDesc, '.'); v = abs((int)(fv * 100)); v = v % 100; _PrintInt(&BufferDesc, v, 10u, 2, FieldWidth, FormatFlags); } break; #endif
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.0, 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 / (unsigned long)pow(10.0, _length_buff - i - 1) % 10 + 0x30; integer_buff = integer_buff % (unsigned long)pow(10.0, _length_buff - i - 1); } _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.0, _length_buff-i-1) % 10 + 0x30; decimal_buff = decimal_buff % (unsigned long)pow(10.0, _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; }
|
3.使用示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| void SEGGERRTTTask(void) { timestamp = TIM5->CNT; if(RTT_Send_flag) { SEGGER_RTT_SetTerminal(0); SEGGER_RTT_printf(0,"Des = %s \n", out_float(g_stGM_YawSpeedPID.fpDes,4,&length)); SEGGER_RTT_printf(0,"U = %s \n", out_float(g_stGM_YawSpeedPID.fpU,4,&length));
SEGGER_RTT_SetTerminal(1); SEGGER_RTT_printf(0,"FB = %s \n", out_float(g_stGM_YawSpeedPID.fpFB,4,&length)); SEGGER_RTT_printf(0,"YY = %s \n", out_float(g_stGM_YawSpeedPID.fpFB,4,&length)); } }
|
一般使用JLinkRTTViewer观看数据
过低版本的jlink可能不自带RTT Viewer的安装包,如果在jlink的安装文件夹里面找不到RTTViewer的话升个版本就行

将Specify Target Device选为对应的型号 Target Interface & Speed选为对应的接口。
关于最后的RTT Control Block的Address,可以通过工程编译生成的.map文件(双击HITCRT_ENGINEER_2024即可打开)查看
[]: https://blog.csdn.net/qq_38295600/article/details/129331670 “查看MAP”

在文件中查询_SEGGER_RTT得到类似下面的代码
1
| _SEGGER_RTT 0x20002f50 Data 168 segger_rtt.o(.bss)
|
其中0x20002f50即为the address of the RTT Control block。
连接后就可以观看JLink RTT发送的数据。

使用JLinkRTTViewer导出数据时,可以点击工具栏中Logging->Start Terminals Logging,之后Terminals中的数据就会被存储在.log文件中,之后再次点击Logging->Stop Terminals Logging终止数据记录。
如果数据更新不正常可以修改浮点数精度
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| 0> 42466 0.0 0.0 0.0 0.0 0> 42468 0.0 0.0 0.0 0.0 0> 42470 0.0 0.0 0.0 0.0 0> 42472 0.0 0.0 0.0 0.0 0> 42474 0.0 0.0 0.0 0.0 0> 42476 0.5 11.600 299.899 5803.935 0> 42478 0.29 34.793 299.700 5800.202 0> 42480 0.98 81.148 299.500 5784.846 0> 42482 0.284 173.781 299.299 5746.227 0> 42484 0.747 358.877 299.100 5661.67 0> 42486 1.859 728.712 298.899 5482.806 0> 42488 4.452 1467.655 298.700 5118.334 0> 42492 10.384 2946.81 298.300 4387.412 0> 42496 53.297 11787.771 297.900 -68.46 0> 42500 118.456 23579.550 297.500 -6031.500 0> 42504 567.645 94098.648 297.100 -41811.968 0> 42508 1230.136 188146.62 296.500 -185136.546 0> 42514 5672.13 751090.0 295.900 -758900.125 0> 42520 25687.847 2998271.750 295.300 -3055603.0 0> 42528 241244.750 23896540.0 294.300 -24520456.0 0> 42536 1061137.875 190583856.0 293.500 -98301464.0 0> 42546 9632197.0 1519956224.0 292.300 -1574043008.0 0> 42558 178292192.0 3540067328.0 291.100 -4037248000.0 0> 42570 1572560768.0 4164190208.0 289.899 -321142784.0 0> 42582 2459584512.0 3717332992.0 288.700 -2777284608.0 0> 42594 3926392832.0 3791650816.0 287.500 -4118806528.0 0> 42606 1244397568.0 369098752.0 286.299 -1610612736.0 0> 42618 3019898880.0 2684354560.0 285.100 -0.0 0> 42628 2415919104.0 2147483648.0 284.100 -0.0 0> 42638 3489660928.0 0.0 283.299 -0.0 0> 42644 3221225472.0 0.0 282.699 -0.0
|