要在FRDM KV31F评估板上获取实时时间戳,可以按照以下步骤操作:
1. 启用RTC模块
MKV31F512VLL12内置硬件RTC模块,支持独立供电的32.768kHz时钟源。若评估板未外接晶振,需使用内部时钟(精度较低)。
配置步骤:
// 启用RTC时钟门控
SIM->SCGC6 |= SIM_SCGC6_RTC_MASK;
// 选择时钟源(此处使用内部1kHz LPO)
RTC->CR &= ~RTC_CR_OSCE_MASK; // 禁用外部晶振
RTC->CR |= RTC_CR_CLKO_MASK; // 启用内部1kHz时钟
// 设置预分频器为32768分频(得到1Hz)
RTC->TPR = 32768 - 1;
// 启动RTC
RTC->SR |= RTC_SR_TCE_MASK;
2. 设置初始时间
通过寄存器设置初始时间戳(Unix时间戳格式):
uint32_t initialEpoch = 1672531200; // 2023-01-01 00:00:00 UTC
RTC->TSR = initialEpoch;
3. 结合PIT获取毫秒级精度
使用PIT定时器(配置为1ms中断)实现亚秒级计数:
// 初始化PIT
SIM->SCGC6 |= SIM_SCGC6_PIT_MASK;
PIT->MCR = 0; // 启用PIT
PIT->CHANNEL[0].LDVAL = 48000 - 1; // 1ms @48MHz
PIT->CHANNEL[0].TCTRL |= PIT_TCTRL_TIE_MASK | PIT_TCTRL_TEN_MASK;
NVIC_EnableIRQ(PIT0_IRQn);
4. 维护时间结构体
在中断中更新全局时间变量:
volatile struct {
uint32_t epoch;
uint16_t milliseconds;
} realTime;
void PIT0_IRQHandler(void) {
PIT->CHANNEL[0].TFLG = PIT_TFLG_TIF_MASK;
realTime.milliseconds++;
if (realTime.milliseconds >= 1000) {
realTime.epoch++;
realTime.milliseconds = 0;
}
}
5. 原子读取时间戳
通过临界区保护确保数据一致性:
void getTimestamp(uint32_t *epoch, uint16_t *ms) {
__disable_irq();
*epoch = RTC->TSR + realTime.epoch;
*ms = realTime.milliseconds;
__enable_irq();
}
6. 数据打包与发送
在发送数据时组合时间戳:
uint8_t payload[8];
uint32_t currentEpoch;
uint16_t currentMs;
getTimestamp(¤tEpoch, ¤tMs);
memcpy(payload, ¤tEpoch, 4);
memcpy(payload+4, ¤tMs, 2);
// 通过UART/I2C发送payload
注意事项:
- 时钟校准:若使用内部时钟,需定期校准(误差可能达±2%)。
- 电源管理:确保VBAT引脚供电以保持RTC运行(开发板需保持通电)。
- 闰秒处理:RTC不自动处理闰秒,需固件更新。
- 时区转换:在应用层处理UTC到本地时间的转换。
完整示例代码需结合NXP官方SDK(如KSDK 3.0)中的驱动库实现更简洁的操作。建议参考fsl_rtc.h
和fsl_pit.h
中的API简化开发。