RTT Viewer 打印浮点会有精度问题,请改用串口打印

弄CC1101的频率设置问题,给用户实现一个函数,用户可以指定载波频率,然后在函数里设置这个频率

涉及到公式计算,f_carrier = f_xosc*FREQ/(2^16) (完整的公式涉及到信道号和信道间隔,为了简化,暂时没有使用信道,CHANNR配置为0

通过用户输入的想设置的载波频率,反推FREQ寄存器的值(24bits,实际是FREQ2/FREQ1/FREQ0三个寄存器)。

用户指定函数的合法参数范围为:434050–434790kHz and 868150–868550kHz.

本人菜且懒,用GEMINI生成代码(代码只是先计算,没有设置FREQ寄存器)如下:

#define LOWER_LIMIT_1 434050e3  // 434.05 MHz in Hz
#define UPPER_LIMIT_1 434790e3  // 434.79 MHz in Hz
#define LOWER_LIMIT_2 868150e3  // 868.15 MHz in Hz
#define UPPER_LIMIT_2 868550e3  // 868.55 MHz in Hz

uint32_t SetOperatingFrequency(double f_carrier) {
  const double f_xosc = 27e6; // 27 MHz in Hz

  // Check if f_carrier is within valid ranges
  if (f_carrier < LOWER_LIMIT_1 || (f_carrier > UPPER_LIMIT_1 &&
      f_carrier < LOWER_LIMIT_2) || f_carrier > UPPER_LIMIT_2) {
    print_log("Error: Carrier frequency %.2f kHz is outside valid ranges\n", f_carrier / 1e3);
    print_log("(%.2f-%.2f kHz or %.2f-%.2f kHz)\n", LOWER_LIMIT_1 / 1e3, UPPER_LIMIT_1 / 1e3, LOWER_LIMIT_2 / 1e3, UPPER_LIMIT_2 / 1e3);
    return UINT32_MAX; // Example: return maximum value to indicate error
  }

  // Calculate the ideal FREQ value
  double ideal_freq = (f_carrier * pow(2, 16)) / f_xosc;
	print_log("The ideal_freq: %f\n", ideal_freq);

  // Check if ideal_freq is within representable range of uint32_t
  if (ideal_freq > UINT32_MAX || ideal_freq < 0) {
    // Handle error: desired frequency outside representable range
    print_log("Error: Desired frequency cannot be represented due to hardware limitations.\n");
    return UINT32_MAX; // Example: return maximum value to indicate error
  }

  // Round the ideal FREQ to the nearest integer (24-bit representation)
  uint32_t freq = round(ideal_freq);
	print_log("The FREQ: %d\n", freq);
  // Calculate the actual carrier frequency based on the set FREQ
  double actual_f_carrier = f_xosc  / pow(2, 16) * freq;
	
	print_log("The actual_f_carrier : %.2f\n", actual_f_carrier);
  return actual_f_carrier;
	
}

(代码中的print_log是用RTT Viewer打印的函数,详细可以参考下列文章

【嵌入式小技巧】STM32 实现 SEGGER RTT 打印(超详细)-CSDN博客

GEMINI生成的代码,用了double作为形参, 虽然我觉得不是很有必要,但还是留下了,然后测试,

然后在main函数中调用,传入最大合法值868550kHz:

	uint32_t ActualFreq = SetOperatingFrequency(868550e3);
	print_log("ActualFreq: %d\n", ActualFreq);

输出结果为:

 手动算一下核对结果

根据公式 

 f_carrier = f_xosc*FREQ/(2^16)

那么

FREQ =  f_carrier * 2^16 / f_xosc  

晶振用的是27MHz,

FREQ = 868550*1000 * 2^16 / 27000000 = 2108196.0296

圆整为 2108196 = = 0x 202B24 ,这是 FREQ 应该设置的值

在用这个值代入f_carrier = f_xosc*FREQ/(2^16)算实际的频率值为:

f_carrier = 27000000 * 2108196 / 2^16 = 868,549,987.79296875

但奇怪的是在函数内输出的actual_f_carrier是868550016.00

	print_log("The actual_f_carrier : %.2f\n", actual_f_carrier);

可是函数返回的值把double转换成了uint32_t后输出的ActualFreq 却变正常了

	print_log("ActualFreq: %d\n", ActualFreq);

于是怀疑是和RTT 打印有关,因为毕竟官方没有支持浮点打印,是网友想出的办法,(虽然我参考的博文说实现了打印小数点后面6位,但可能值是不准确的。在我这里,似乎868550016.00这个值从8685后面的数字都是不准确的。是有点离谱的,具体没有费心去分析。)

为了验证这个想法,改用串口打印:

函数内actual_f_carrier的值变正常了。所以还是用串口打印浮点数靠谱点,除非实在串口接不出来另说。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值