今天在调试一个射频通信的时候,需要测试一下SNR,这个参数是一个float类型的数据,开始没注意,直接使用RTT进行LOG 打印。
教你如何使用SEGGER RTT优雅的实现日志系统
void OnSlave(void)
{
uint8_t i = 0;
if (rf_get_recv_flag() == RADIO_FLAG_RXDONE)
{
rf_set_recv_flag(RADIO_FLAG_IDLE);
Rssi_dBm = RxDoneParams.Rssi; // RSSI 的测量范围是-60 到-140
Snr_value = RxDoneParams.Snr; // snr float类型
for (i = 0; i < RxDoneParams.Size; i++)
{
rx_test_buf[i] = RxDoneParams.Payload[i];
}
LOG("rf_rssi:%dn",Rssi_dBm);
LOG("rf_snr: %fn", Snr_value);
rf_enter_single_timeout_rx(15000); //重新进入接收模式
LedToggle(); // LED闪
}
}
打印出来的结果令人匪夷所思
rssi数据可以正常输出,但是snr打印出来是空的,就是浮点类型转换有问题,也不至于输出空的,起码是一个乱的数才对。于是跟进了RTT的源代码,进一步发现,原来RTT的打印处理函数中没有处理%f的逻辑。
接下来,如果我们想要打印这个浮点数据的话,就需要自己稍加处理,思考了一下,应该可以用两种方法来实现。第一, 自己先将float类型转换成字符串,然后通过RTT进行字符串打印。第二,直接修改RTT源代码,增加对浮点数据的打印支持。我对比了一下这两种方式的代码量,最终还是决定修改RTT的源代码来兼容打印浮点数据的功能。以下是对比细节,对比过程中不改变其他代码,只涉及浮点打印部分。
自行转换字符串方式:
Rssi_dBm = RxDoneParams.Rssi; // RSSI 的测量范围是-60 到-140
Snr_value = RxDoneParams.Snr;
for (i = 0; i < RxDoneParams.Size; i++)
{
rx_test_buf[i] = RxDoneParams.Payload[i];
}
LOG("rf_rssi:%dn",Rssi_dBm);
sprintf(buffer, "%.2f", Snr_value); // 手动将float转换为字符串
LOG("rf_snr: %sn", buffer);
以上代码通过sprintf来进行浮点到字符串的转换,这里会用到C的微库,编译后的代码大小如下:
修改RTT源码方式:
修改代码部分内容:
case 'f':
{
float fv = (float)va_arg(*pParamList, double); // 取出输入的浮点数值
if(fv < 0) _StoreChar(&BufferDesc, '-'); // 判断正负号
v = abs((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;
}
打印输出部分就可以直接按照%f进行输出了。
Rssi_dBm = RxDoneParams.Rssi; // RSSI 的测量范围是-60 到-140
Snr_value = RxDoneParams.Snr;
for (i = 0; i < RxDoneParams.Size; i++)
{
rx_test_buf[i] = RxDoneParams.Payload[i];
}
LOG("rf_rssi:%dn",Rssi_dBm);
LOG("rf_snr: %fn", Snr_value);
这样就可以正常的输出结果,编译的代码大小如下图
对比代码大小可以看出,直接修改RTT源代码的方案生成的代码更小,因此,我更新了自己常用的RTT工具包,以后使用就方便了。