今天在调试一个射频通信的时候,需要测试一下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 到-140Snr_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 到-140Snr_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 到-140Snr_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工具包,以后使用就方便了。
4005