Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/61.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何提高CMWX1ZZABZ-091 RTC(实时时钟)的精度_C_Embedded_Stm32_Real Time Clock - Fatal编程技术网

如何提高CMWX1ZZABZ-091 RTC(实时时钟)的精度

如何提高CMWX1ZZABZ-091 RTC(实时时钟)的精度,c,embedded,stm32,real-time-clock,C,Embedded,Stm32,Real Time Clock,我将B-L072Z-LRWAN1与CMWX1ZZABZ-091 LoRa®/Sigfox一起使用™ 村田模块 内部RTC实时时钟不准确,我看到一些模块每天损失10秒 我的问题是,为什么会这样?数据表显示LSE为1.73秒/20ppm。TXCO为2ppm。如何使用TXCO校准RTC 我知道温度也会影响精度,但我认为这是一个微不足道的范围,即不能解释10秒/天。关于LSE的错误声明已删除 如何使用TXCO校准RTC TXCO可以提供HSE,您可以通过一系列预分频器从HSE获得RTC时钟 第8.5节中

我将B-L072Z-LRWAN1与CMWX1ZZABZ-091 LoRa®/Sigfox一起使用™ 村田模块

内部RTC实时时钟不准确,我看到一些模块每天损失10秒

我的问题是,为什么会这样?数据表显示LSE为1.73秒/20ppm。TXCO为2ppm。如何使用TXCO校准RTC

我知道温度也会影响精度,但我认为这是一个微不足道的范围,即不能解释10秒/天。

关于LSE的错误声明已删除

如何使用TXCO校准RTC

TXCO可以提供HSE,您可以通过一系列预分频器从HSE获得RTC时钟

第8.5节中提到

当STM32需要精确的外部高速时钟时,TCXO_OUT时钟引脚由模块引脚PH0_OSC_IN通过闭合SB13提供

首先,用一滴锡封闭SB13

PH0_OSC_IN是HSE旁路时钟源。在RCC->CR中设置HSEBYP和HSEON,以获得准确的32 MHz HSE时钟。但是,请稍候,首先必须将RTCPRE设置为3,以便为RTC模块将其预刻度为16。在RCC->CSR中选择此作为RTC时钟

现在,RCC为RTC fRTCCLK=2000000生成一个2 MHz时钟。您可以使用RTC->PRER寄存器将其进一步缩小到1 Hz fCK_SPRE=1。它有两个位字段,PREDIV_A可以从0到127,PREDIV_S可以从0到32767。求解整数方程

fCK_SPRE=fRTCCLK/PREDIV_S+1×PREDIV_A+1

根据上述约束条件,我们可以给出

PREDIV_S = 24999
PREDIV_A = 79
所以使用

RTC->PRER = (79 << 16) | 24999;
您将有一个精确的RTC 1 Hz时钟。

删除关于LSE的错误声明

如何使用TXCO校准RTC

TXCO可以提供HSE,您可以通过一系列预分频器从HSE获得RTC时钟

第8.5节中提到

当STM32需要精确的外部高速时钟时,TCXO_OUT时钟引脚由模块引脚PH0_OSC_IN通过闭合SB13提供

首先,用一滴锡封闭SB13

PH0_OSC_IN是HSE旁路时钟源。在RCC->CR中设置HSEBYP和HSEON,以获得准确的32 MHz HSE时钟。但是,请稍候,首先必须将RTCPRE设置为3,以便为RTC模块将其预刻度为16。在RCC->CSR中选择此作为RTC时钟

现在,RCC为RTC fRTCCLK=2000000生成一个2 MHz时钟。您可以使用RTC->PRER寄存器将其进一步缩小到1 Hz fCK_SPRE=1。它有两个位字段,PREDIV_A可以从0到127,PREDIV_S可以从0到32767。求解整数方程

fCK_SPRE=fRTCCLK/PREDIV_S+1×PREDIV_A+1

根据上述约束条件,我们可以给出

PREDIV_S = 24999
PREDIV_A = 79
所以使用

RTC->PRER = (79 << 16) | 24999;
您将有一个精确的RTC 1 Hz时钟。

从LSE运行RTC,但将其校准到HSE

执行中的第一步以获得准确的HSE时钟,但让它从LSE运行

从参考手册中

22.4.12 RTC平滑数字校准

RTC频率可进行数字校准,分辨率约为0.954 ppm,范围为-487.1 ppm至+488.5 ppm

校准在RTC->CALR寄存器中完成,即使在时钟运行时也可以顺利调整。调整周期必须为32秒,精度为0.954 ppm

将RTC定期唤醒计时器配置为每32秒生成一次中断。将RTC警报连接至TIM21->OR寄存器中TIM21的TI1输入。配置TIM21以捕获TI1边缘。由于计时器只有16位,因此必须在TIM21中断处理程序中计算溢出更新事件。当捕获事件发生时,您拥有经过的周期数、更新计数中的高半字、捕获寄存器中的低半字。如果与32*32*106的标称值有显著差异,则调整RTC->CALR并重复

困难在于,当更新和捕获几乎同时发生时,要正确执行,因此代码无法可靠地确定哪一个先发生。稍后我将对此进行更多思考。

从LSE运行RTC,但将其校准到HSE

执行中的第一步以获得准确的HSE时钟,但让它从LSE运行

从参考手册中

22.4.12 RTC平滑数字校准

RTC频率可进行数字校准,分辨率约为0.954 ppm,范围为-487.1 ppm至+488.5 ppm

校准在RTC->CALR寄存器中完成,即使在时钟运行时也可以顺利调整。调整周期必须为32秒,精度为0.954 ppm

将RTC定期唤醒计时器配置为每32秒生成一次中断。将RTC警报连接至TIM21->OR寄存器中TIM21的TI1输入。配置TIM21以捕获TI1边缘。由于计时器只有16位,因此必须在TIM21中断处理程序中计算溢出更新事件。当捕获事件发生时,您有 经过的周期数,更新计数中的高半字,捕获寄存器中的低半字。如果与32*32*106的标称值有显著差异,则调整RTC->CALR并重复

困难在于,当更新和捕获几乎同时发生时,要正确执行,因此代码无法可靠地确定哪一个先发生。我以后再考虑一下

如何使用TXCO校准RTC

不久前,我问了自己同样的问题,我花了一段时间才找到解决方案,因为参考手册中记录了许多选项,这个主题可能会很混乱

在我的例子中,我需要在没有HSE谐振器的板上校准RTC。这是一个只有LSE晶体32.768 kHz的小型腕表原型,该板没有HSE,并且由不稳定的RC内部振荡器计时。但对我有效的方法也应该适用于你的情况

我的RTC校准方法的关键是:

一种快速、稳定的基准时钟。我使用了一个STM32F4发现板,带有一个8MHz的HSE晶体,APB时钟速度为25MHz的PLL'ed,定时器用于下面描述的测量。 非常精确的1PPS校准输入每秒1个脉冲。-我使用了一个GPS模块,其中一个引脚上有1PPS的输出。 在我的案例中,校准步骤如下:

在我的情况下,使用计数器/定时器的输入捕获方法,计算连接到1PPS信号源GPS模块的引脚上多个1PPS事件之间的系统时钟滴答数选择正确的定时器宽度16 vs 32位,时钟除法最好不除法,以获得最大分辨率。然后取平均值,以了解与假设时钟速度25 MHz的偏差。它应该是稳定的,并且在测量过程中变化不大。32秒的校准时间足够了。 然后,使用不同引脚上的输入捕获,计算目标MCU的LSE驱动的多个1Hz校准输出信号之间的系统时钟信号数量,并取平均值。 现在计算所需的LSE校正。并使用目标STM32上的RTC校准寄存器调整RTC。另请参阅参考手册或本手册中的RTC平滑校准。 重做步骤1和2以验证更正。 开始校准前,确保撤消任何RTC校正:

 if (HAL_RTCEx_SetSmoothCalib(
        &hrtc,
        RTC_SMOOTHCALIB_PERIOD_32SEC,
        RTC_SMOOTHCALIB_PLUSPULSES_RESET,
        0) != HAL_OK) {
    error_handler();
  }
  start_calibration();
为了计算修正,我使用了类似的方法:

const float corr = calib_avg_ext_rtc / calib_avg_1pps;

log("correction:\r\n%f / %f =\r\n%.20f\r\n\r\n", 
  calib_avg_ext_rtc, calib_avg_1pps, corr);

const float c = corr - 1.0f;
if (corr > 1.0f) {
  log("RTC crystal vibrates too fast!\r\n");
  log("correction: %.20f ppm\r\n", -1.0e6f * c);
}
else if (corr < 1.0f) {
  log("RTC crystal vibrates too slow!\r\n");
  log("correction: %.20f ppm\r\n",  1.0e6f * c);
}
else {
  log("your RTC crystal is running exactly at the right speed. - STRANGE!\r\n");
}

const int16_t calib32s = (int16_t)roundf(c * 32*32768);
if (calib32s != 0) {
  log("correction value (ticks +/- 32 s interval):\r\n");
  if (corr < 1.0f) {
    log("MINUS %d\r\n", -calib32s); /* clock TOO SLOW, REMOVE cycles */
    log("\r\nuse this on the target:\r\n");
    log("HAL_RTCEx_SetSmoothCalib(&hrtc, RTC_SMOOTHCALIB_PERIOD_32SEC,\
        RTC_SMOOTHCALIB_PLUSPULSES_RESET, %d);",
      -calib32s);
  }
  else {
    log("PLUS %d\r\n", calib32s); /* clock TOO FAST, ADD cycles */
    log("\r\nuse this on the target:\r\n");
    log("HAL_RTCEx_SetSmoothCalib(&hrtc, RTC_SMOOTHCALIB_PERIOD_32SEC,\
        RTC_SMOOTHCALIB_PLUSPULSES_SET, 0x1FF - %d);",
      calib32s);
  }
}
else {
  log("calibration complete! NO FURTHER CORRECTION REQUIRED\r\n");
}
在测量了所需的校正后,我手动复制粘贴了代码,并且必须刷新目标板以验证校准。稍后,最好在设备已部署时选择进行校准

我已经在STM32L011上使用过这个方法,但该方法或多或少与MCU的类型无关。在我的例子中,我使用了8 MHz HSE和STM32F4发现板上的32位计数器。但是,当存在快速、稳定的HSE时,该方法也应在修改后的形式下工作,而无需除1PPS源之外的额外硬件。-我设法得到小于1 PPM的偏差,RTC在几天内保持时间准确。正如我不得不发现的那样,温度的变化会对精度产生相当大的影响

研究结果也在STM32论坛上讨论过,但是现在页面已经关闭,所以我不能告诉你

如何使用TXCO校准RTC

不久前,我问了自己同样的问题,我花了一段时间才找到解决方案,因为参考手册中记录了许多选项,这个主题可能会很混乱

在我的例子中,我需要在没有HSE谐振器的板上校准RTC。这是一个只有LSE晶体32.768 kHz的小型腕表原型,该板没有HSE,并且由不稳定的RC内部振荡器计时。但对我有效的方法也应该适用于你的情况

我的RTC校准方法的关键是:

一种快速、稳定的基准时钟。我使用了一个STM32F4发现板,带有一个8MHz的HSE晶体,APB时钟速度为25MHz的PLL'ed,定时器用于下面描述的测量。 非常精确的1PPS校准输入每秒1个脉冲。-我使用了一个GPS模块,其中一个引脚上有1PPS的输出。 在我的案例中,校准步骤如下:

在我的情况下,使用计数器/定时器的输入捕获方法,计算连接到1PPS信号源GPS模块的引脚上多个1PPS事件之间的系统时钟滴答数选择正确的定时器宽度16 vs 32位,时钟除法最好不除法,以获得最大分辨率。然后取平均值,以了解与假设时钟速度25 MHz的偏差。它应该是稳定的,并且在测量过程中变化不大。32秒的校准时间足够了。 然后,使用输入捕获o统计目标MCU的LSE驱动的多个1Hz校准输出信号之间的系统时钟信号数量 n另一个别针,取平均值。 现在计算所需的LSE校正。并使用目标STM32上的RTC校准寄存器调整RTC。另请参阅参考手册或本手册中的RTC平滑校准。 重做步骤1和2以验证更正。 开始校准前,确保撤消任何RTC校正:

 if (HAL_RTCEx_SetSmoothCalib(
        &hrtc,
        RTC_SMOOTHCALIB_PERIOD_32SEC,
        RTC_SMOOTHCALIB_PLUSPULSES_RESET,
        0) != HAL_OK) {
    error_handler();
  }
  start_calibration();
为了计算修正,我使用了类似的方法:

const float corr = calib_avg_ext_rtc / calib_avg_1pps;

log("correction:\r\n%f / %f =\r\n%.20f\r\n\r\n", 
  calib_avg_ext_rtc, calib_avg_1pps, corr);

const float c = corr - 1.0f;
if (corr > 1.0f) {
  log("RTC crystal vibrates too fast!\r\n");
  log("correction: %.20f ppm\r\n", -1.0e6f * c);
}
else if (corr < 1.0f) {
  log("RTC crystal vibrates too slow!\r\n");
  log("correction: %.20f ppm\r\n",  1.0e6f * c);
}
else {
  log("your RTC crystal is running exactly at the right speed. - STRANGE!\r\n");
}

const int16_t calib32s = (int16_t)roundf(c * 32*32768);
if (calib32s != 0) {
  log("correction value (ticks +/- 32 s interval):\r\n");
  if (corr < 1.0f) {
    log("MINUS %d\r\n", -calib32s); /* clock TOO SLOW, REMOVE cycles */
    log("\r\nuse this on the target:\r\n");
    log("HAL_RTCEx_SetSmoothCalib(&hrtc, RTC_SMOOTHCALIB_PERIOD_32SEC,\
        RTC_SMOOTHCALIB_PLUSPULSES_RESET, %d);",
      -calib32s);
  }
  else {
    log("PLUS %d\r\n", calib32s); /* clock TOO FAST, ADD cycles */
    log("\r\nuse this on the target:\r\n");
    log("HAL_RTCEx_SetSmoothCalib(&hrtc, RTC_SMOOTHCALIB_PERIOD_32SEC,\
        RTC_SMOOTHCALIB_PLUSPULSES_SET, 0x1FF - %d);",
      calib32s);
  }
}
else {
  log("calibration complete! NO FURTHER CORRECTION REQUIRED\r\n");
}
在测量了所需的校正后,我手动复制粘贴了代码,并且必须刷新目标板以验证校准。稍后,最好在设备已部署时选择进行校准

我已经在STM32L011上使用过这个方法,但该方法或多或少与MCU的类型无关。在我的例子中,我使用了8 MHz HSE和STM32F4发现板上的32位计数器。但是,当存在快速、稳定的HSE时,该方法也应在修改后的形式下工作,而无需除1PPS源之外的额外硬件。-我设法得到小于1 PPM的偏差,RTC在几天内保持时间准确。正如我不得不发现的那样,温度的变化会对精度产生相当大的影响


STM32论坛上也讨论了这些发现,但现在页面已关闭,因此我无法向您指出…

这里可能是离题,可能更多的是硬件问题,而不是软件问题。考虑使用。如何使用NTP是一个不同的问题,可能是操作系统特定的问题。我投票结束这个问题,因为它是关于硬件实时时钟模块的,而不是关于编程。你可能会得到更好的回答。但是,请务必阅读并验证您发布的任何问题是否适合该网站。@JimGarrison这不是一个硬件主题,而是一个关于用于校准硬件的软件的问题。这里可能是一个硬件问题,而不是软件问题。考虑使用。如何使用NTP是一个不同的问题,可能是操作系统特定的问题。我投票结束这个问题,因为它是关于硬件实时时钟模块的,而不是关于编程。你可能会得到更好的回答。但是,请务必阅读并验证您发布的任何问题是否适合该站点。@JimGarrison这不是一个硬件主题,而是一个关于用于校准硬件的软件的问题模块的LSE运行频率为32KHz。LSE集成到模块chipRight中,经过编辑。RTC需要运行LSE,因为需要低功耗睡眠,问题更多:RTC运行的是20ppm LSE,但其错误超过20ppm什么软件错误会导致此错误模块的LSE运行频率为32KHz。LSE集成到模块chipRight中,经过编辑。RTC需要运行LSE,因为需要低功耗睡眠,问题更多:RTC运行的是20ppm LSE,但错误超过20ppm。什么软件错误会导致这种情况