我正在将B-L072Z-LRWAN1与CMWX1ZZABZ-091LoRa®/ Sigfox™模块(村田)一起使用
内部RTC(实时时钟)不准确,我发现某些模块每天损失10秒。
我的问题是,为什么会这样?数据表显示LSE为1.73秒/ 20ppm。 TXCO为2ppm。如何使用TXCO校准RTC?
我知道还有温度会影响精度,但是我认为这个范围很小,即不能解释10秒/天。
答案 0 :(得分:3)
(已删除有关LSE的错误陈述)
如何使用TXCO校准RTC?
TXCO可以提供HSE,并且您可以通过一系列预分频器从HSE导出RTC时钟。
User Manual中的8.5节说,
当STM32需要精确的外部高速时钟时,通过闭合SB13,由模块引脚PH0_OSC_IN提供TCXO_OUT时钟引脚。
首先,用一滴锡关闭SB13。
PH0_OSC_IN是HSE旁路时钟源。在HSEBYP
中先设置HSEON
,然后再设置RCC->CR
,以获得准确的32 MHz HSE时钟。但是,等等,首先您必须将RTCPRE
设置为3
,以便将RTC模块的比例预先缩放16。在RCC->CSR
中选择它作为RTC时钟。
现在,RCC为RTC生成2 MHz时钟(f RTCCLK = 2000000)。您可以使用RTC->PRER
寄存器将其进一步缩小至1 Hz(f CK_SPRE = 1)。它具有两个位域,PREDIV_A
可以从0
到127
,PREDIV_S
从0
到32767
。求解整数方程
f CK_SPRE = f RTCCLK / ((PREDIV_S + 1) × (PREDIV_A + 1))
具有上述限制的
PREDIV_S = 24999
PREDIV_A = 79
因此使用
RTC->PRER = (79 << 16) | 24999;
您将有一个准确的1 Hz RTC时钟。
答案 1 :(得分:3)
如何使用TXCO校准RTC?
不久前,我问自己一个相同的问题,花了一段时间才找到解决方案,因为参考手册中记录了许多选项,并且该主题可能非常令人困惑。
在我的情况下,我需要在没有HSE谐振器的板上校准RTC(这是一个小型手表原型,仅带有LSE晶体(32.768 kHz),该板没有HSE,并且需要时钟来自不稳定的RC内部振荡器)。但是对我有用的方法也应该适用于您的情况。
我的RTC校准方法的关键是:
在我的情况下,校准步骤如下:
在开始校准之前,请确保撤消所有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类型无关。就我而言,我在STM32F4发现板上使用了8 MHz HSE和32位计数器。但是,当存在快速,稳定的HSE时,该方法也应以修改后的形式工作,而无需使用其他硬件(除了1PPS源)。 -我设法使偏差保持在1 PPM以下,并且RTC在几天内准确地保持了时间(温度变化可能会影响精度,这是我必须找出的)。
在STM32论坛上也讨论了这些发现,但是页面现在不正确,所以我无法将您指向that ...
答案 2 :(得分:0)
从LSE运行RTC,但将其校准为HSE。
执行my previous answer中的第一步,以获取准确的HSE时钟,但保持其在LSE上运行。
根据参考手册,
22.4.12 RTC平滑数字校准
可以以大约0.954 ppm的分辨率对RTC频率进行数字校准,范围为-487.1 ppm至+488.5 ppm。
校准在RTC->CALR
寄存器中进行,即使在时钟运行时也可以平滑地进行调整。调整周期必须为32秒,才能达到0.954 ppm的精度。
配置RTC定期唤醒定时器以每32秒生成一次中断。将RTC警报连接到TIM21
寄存器中TIM21->OR
的TI1输入。配置TIM21以捕获TI1边缘。由于定时器只有16位,因此您必须计算TIM21中断处理程序中的溢出(更新事件)。发生捕获事件时,您将拥有经过的周期数,更新计数中的高半字,捕获寄存器中的低半字。如果它与标称值32 * 32 * 10 6 明显不同,请调整RTC->CALR
并重复。
当更新和捕获大约同时发生时,难点在于正确,因此代码无法可靠地确定首先发生的是哪个。稍后再考虑。