c-如何提高CMWX1ZZABZ-091实时时钟的精度



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

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

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

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

如何使用TXCO校准RTC?

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

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

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

  1. 快速、稳定的参考时钟我使用了STM32F4发现板(带有8 MHz HSE晶体,APB时钟速度为25 MHz(PLL'ed up),计时器用于下面描述的测量)
  2. 非常精确的1PPS校准输入(每秒1次Pluse)。-我使用了一个GPS模块,其中一个引脚上有1PPS输出

在我的情况下,校准步骤如下:

  1. 使用计数器/计时器的输入捕获方法(选择合适的计时器宽度(16比32位)和时钟分频(最好不分频以获得最大分辨率)),在连接到1PPS信号源(在我的情况下是GPS模块)的引脚上,计算多个1PPS事件之间的系统时钟滴答数。然后取平均值,了解与假设时钟速度(在我的情况下为25 MHz)的偏差。它应该是稳定的,在测量过程中变化不大(32秒的校准时间就足够了)
  2. 然后计算多个1 Hz校准输出节拍之间的系统时钟节拍数(由目标MCU的LSE驱动)(使用不同引脚上的输入捕获),并取平均值
  3. 现在计算所需的LSE校正。并使用目标STM32上的RTC校准寄存器来调整RTC(另请参阅参考手册或本应用说明(AN3371)中的RTC平滑校准)
  4. 重做步骤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:rn%f / %f =rn%.20frnrn", 
calib_avg_ext_rtc, calib_avg_1pps, corr);
const float c = corr - 1.0f;
if (corr > 1.0f) {
log("RTC crystal vibrates too fast!rn");
log("correction: %.20f ppmrn", -1.0e6f * c);
}
else if (corr < 1.0f) {
log("RTC crystal vibrates too slow!rn");
log("correction: %.20f ppmrn",  1.0e6f * c);
}
else {
log("your RTC crystal is running exactly at the right speed. - STRANGE!rn");
}
const int16_t calib32s = (int16_t)roundf(c * 32*32768);
if (calib32s != 0) {
log("correction value (ticks +/- 32 s interval):rn");
if (corr < 1.0f) {
log("MINUS %drn", -calib32s); /* clock TOO SLOW, REMOVE cycles */
log("rnuse this on the target:rn");
log("HAL_RTCEx_SetSmoothCalib(&hrtc, RTC_SMOOTHCALIB_PERIOD_32SEC,
RTC_SMOOTHCALIB_PLUSPULSES_RESET, %d);",
-calib32s);
}
else {
log("PLUS %drn", calib32s); /* clock TOO FAST, ADD cycles */
log("rnuse this on the target:rn");
log("HAL_RTCEx_SetSmoothCalib(&hrtc, RTC_SMOOTHCALIB_PERIOD_32SEC,
RTC_SMOOTHCALIB_PLUSPULSES_SET, 0x1FF - %d);",
calib32s);
}
}
else {
log("calibration complete! NO FURTHER CORRECTION REQUIREDrn");
}

在测量了所需的校正后,我手动复制粘贴了代码,并必须闪烁目标板以验证校准。稍后,最好可以选择在设备已经部署时进行校准。。。

我在STM32L011上使用过这个,但这个方法或多或少与MCU的类型无关。在我的案例中,我使用了STM32F4发现板上的8 MHz HSE和32位计数器。但是,当存在快速、稳定的HSE时,这种方法也应该在没有额外硬件(除了1PPS源)的情况下以修改的形式工作我设法获得了小于1 PPM的偏差,RTC在几天内准确地保持了时间(正如我必须发现的那样,温度的变化会对准确性产生很大影响)。

STM32论坛也讨论了这些发现,但页面现在已经关闭,所以我不能向您指出。。。

(关于LSE的错误声明已删除)

如何使用TXCO校准RTC?

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

用户手册第8.5节规定,

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

首先,用一滴锡关闭SB13。

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

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

fCK_SPRE=fRTCCLK/ ((PREDIV_S + 1) × (PREDIV_A + 1))

有了上述约束条件,

PREDIV_S = 24999
PREDIV_A = 79

所以使用

RTC->PRER = (79 << 16) | 24999;

你会有一个准确的1赫兹时钟RTC。

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

按照我之前回答的第一步来获得准确的HSE时钟,但不要让它在伦敦政治经济学院运行。

参考手册,

22.4.12 RTC平滑数字校准

RTC频率可以以大约0.954ppm的分辨率进行数字校准,范围从-487.1ppm到+48.85ppm。

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

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

困难在于,当更新和捕获大约同时发生时,代码无法可靠地决定哪一个先发生。我稍后会再考虑一下。

最新更新