文章目录
Linux RTC 从入门到精通教程
一、RTC 基础概念
1.1 什么是 RTC?
RTC(Real-Time Clock)是实时时钟,是计算机系统中的一个独立时钟电路,即使在系统断电的情况下也能继续计时。
1.2 为什么需要 RTC?
- 保持准确时间
- 系统断电后继续计时
- 提供定时唤醒功能
- 支持系统时间同步
二、基础操作
2.1 查看系统时间
# 查看系统时间
date
# 查看硬件时钟
hwclock --show
2.2 时间同步操作
# 系统时间同步到硬件时钟
hwclock --systohc
# 硬件时钟同步到系统时间
hwclock --hctosys
三、初级编程示例
3.1 读取 RTC 时间
#include <stdio.h>
#include <linux/rtc.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <unistd.h>
int main() {
int fd;
struct rtc_time rtc_tm;
// 打开RTC设备
fd = open("/dev/rtc0", O_RDONLY);
if (fd == -1) {
perror("打开RTC设备失败");
return -1;
}
// 读取RTC时间
if (ioctl(fd, RTC_RD_TIME, &rtc_tm) == -1) {
perror("读取RTC时间失败");
close(fd);
return -1;
}
// 打印时间
printf("当前时间: %d-%02d-%02d %02d:%02d:%02d\n",
rtc_tm.tm_year + 1900,
rtc_tm.tm_mon + 1,
rtc_tm.tm_mday,
rtc_tm.tm_hour,
rtc_tm.tm_min,
rtc_tm.tm_sec);
close(fd);
return 0;
}
四、中级应用
4.1 设置 RTC 时间
#include <stdio.h>
#include <linux/rtc.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <unistd.h>
#include <time.h>
int main() {
int fd;
struct rtc_time rtc_tm;
time_t current_time;
struct tm *time_info;
// 获取当前系统时间
time(¤t_time);
time_info = localtime(¤t_time);
// 设置RTC时间结构体
rtc_tm.tm_year = time_info->tm_year;
rtc_tm.tm_mon = time_info->tm_mon;
rtc_tm.tm_mday = time_info->tm_mday;
rtc_tm.tm_hour = time_info->tm_hour;
rtc_tm.tm_min = time_info->tm_min;
rtc_tm.tm_sec = time_info->tm_sec;
fd = open("/dev/rtc0", O_RDWR);
if (fd == -1) {
perror("打开RTC设备失败");
return -1;
}
// 设置RTC时间
if (ioctl(fd, RTC_SET_TIME, &rtc_tm) == -1) {
perror("设置RTC时间失败");
close(fd);
return -1;
}
printf("RTC时间设置成功\n");
close(fd);
return 0;
}
4.2 简单闹钟功能
#include <stdio.h>
#include <linux/rtc.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <unistd.h>
int main() {
int fd;
struct rtc_time alarm_tm;
unsigned long data;
fd = open("/dev/rtc0", O_RDWR);
if (fd == -1) {
perror("打开RTC设备失败");
return -1;
}
// 设置闹钟时间(5秒后)
if (ioctl(fd, RTC_RD_TIME, &alarm_tm) == -1) {
perror("读取当前时间失败");
close(fd);
return -1;
}
alarm_tm.tm_sec += 5; // 5秒后
if (alarm_tm.tm_sec >= 60) {
alarm_tm.tm_sec -= 60;
alarm_tm.tm_min++;
}
// 设置闹钟
if (ioctl(fd, RTC_ALM_SET, &alarm_tm) == -1) {
perror("设置闹钟失败");
close(fd);
return -1;
}
// 启用闹钟中断
if (ioctl(fd, RTC_AIE_ON, 0) == -1) {
perror("启用闹钟中断失败");
close(fd);
return -1;
}
printf("等待闹钟触发...\n");
read(fd, &data, sizeof(unsigned long));
printf("闹钟触发!\n");
close(fd);
return 0;
}
五、高级特性
5.1 周期性中断
#include <stdio.h>
#include <linux/rtc.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <unistd.h>
int main() {
int fd;
unsigned long data;
int retval;
fd = open("/dev/rtc0", O_RDONLY);
if (fd == -1) {
perror("打开RTC设备失败");
return -1;
}
// 设置中断频率(2Hz)
retval = ioctl(fd, RTC_IRQP_SET, 2);
if (retval == -1) {
perror("设置中断频率失败");
close(fd);
return -1;
}
// 启用周期性中断
retval = ioctl(fd, RTC_PIE_ON, 0);
if (retval == -1) {
perror("启用周期性中断失败");
close(fd);
return -1;
}
printf("开始接收周期性中断...\n");
for (int i = 0; i < 10; i++) { // 接收10次中断
read(fd, &data, sizeof(unsigned long));
printf("收到中断 #%d\n", i + 1);
}
// 关闭中断
ioctl(fd, RTC_PIE_OFF, 0);
close(fd);
return 0;
}
六、实际应用场景
6.1 系统时间同步
- NTP 服务集成
- 定期校准
- 时区处理
6.2 低功耗应用
- 系统休眠唤醒
- 定时开关机
- 电源管理
6.3 数据记录
- 日志时间戳
- 事件计时
- 定时采样
七、调试技巧
7.1 常用调试命令
# 查看RTC状态
cat /proc/driver/rtc
# 查看系统日志
dmesg | grep rtc
# 查看设备信息
ls -l /sys/class/rtc/
7.2 常见问题解决
-
权限问题
- 使用 sudo
- 检查设备权限
-
时间同步问题
- 检查时区设置
- 验证硬件时钟
-
中断处理
- 检查中断配置
- 验证中断频率