🕐 hal::rtc
Real-Time Clock - Tarih/Saat Yönetimi
379 lines
~12 function
Low-Power
📖 Overview
RTC (Real-Time Clock) modülü, düşük güç tüketimli tarih ve saat tutma işlevi sağlar. Batarya destekli çalışma, alarm ve takvim özellikleri sunar.
🔑 Key Features
- Date/time keeping
- Calendar with leap year
- 2 programmable alarms
- Wakeup timer
- Backup registers (80 bytes)
- Battery-backed operation
- Timestamp event
- Sub-second precision
🚀 Quick Start
import hal::rtc
// Initialize RTC
let rtc_handle = rtc.init(do
hour_format: rtc.FORMAT_24H,
async_prediv: 127,
sync_prediv: 255
end)
// Set time
rtc.set_time(rtc_handle, do
hours: 14,
minutes: 30,
seconds: 0
end)
// Set date
rtc.set_date(rtc_handle, do
year: 2024,
month: 12,
day: 25,
weekday: rtc.WEDNESDAY
end)
// Read time
let time = rtc.get_time(rtc_handle)
io.println("{:02}:{:02}:{:02}".formatla(time.hours, time.minutes, time.seconds))
💡 Example: Digital Clock Display
import hal::rtc, hal::core
struct DateTime do
year: int,
month: int,
day: int,
hours: int,
minutes: int,
seconds: int,
weekday: int
end
function weekday_name(day: int) -> str do
return match day do
1 => "Pazartesi",
2 => "Salı",
3 => "Çarşamba",
4 => "Perşembe",
5 => "Cuma",
6 => "Cumartesi",
7 => "Pazar",
_ => "Bilinmeyen"
end
end
function ana() do
core.system_init()
// Initialize RTC
let rtc_handle = rtc.init(do
hour_format: rtc.FORMAT_24H
end)
// Set initial time (2024-12-25 14:30:00 Wednesday)
rtc.set_date(rtc_handle, do
year: 2024,
month: 12,
day: 25,
weekday: rtc.WEDNESDAY
end)
rtc.set_time(rtc_handle, do
hours: 14,
minutes: 30,
seconds: 0
end)
loop do
// Read current time
let time = rtc.get_time(rtc_handle)
let date = rtc.get_date(rtc_handle)
// Display
io.print("\r") // Carriage return
io.print("{:02}/{:02}/{} {} {:02}:{:02}:{:02}".formatla(
date.day,
date.month,
date.year,
weekday_name(date.weekday),
time.hours,
time.minutes,
time.seconds
))
core.delay_ms(1000)
end
end
💡 Example: Alarm Clock
import hal::rtc
let alarm_triggered = false
function alarm_callback() do
alarm_triggered = true
io.println("\n🔔 ALARM! Wake up!")
end
function set_alarm(rtc_handle: rtc.Handle, hours: int, minutes: int) do
rtc.set_alarm(rtc_handle, rtc.ALARM_A, do
hours: hours,
minutes: minutes,
seconds: 0,
alarm_mask: rtc.MASK_SECONDS, // Ignore seconds
callback: alarm_callback
end)
io.println("Alarm set for {:02}:{:02}".formatla(hours, minutes))
end
function ana() do
let rtc_handle = rtc.init(do
hour_format: rtc.FORMAT_24H
end)
// Set current time: 07:58:00
rtc.set_time(rtc_handle, do
hours: 7,
minutes: 58,
seconds: 0
end)
// Set alarm for 08:00
set_alarm(rtc_handle, 8, 0)
loop do
let time = rtc.get_time(rtc_handle)
io.print("\r{:02}:{:02}:{:02}".formatla(
time.hours, time.minutes, time.seconds
))
if alarm_triggered ise do
alarm_triggered = false
// Snooze for 5 minutes
set_alarm(rtc_handle, time.hours, time.minutes + 5)
end
core.delay_ms(1000)
end
end
💡 Example: Wakeup Timer (Auto-Wakeup from Standby)
import hal::rtc, hal::core
function periodic_wakeup() do
let rtc_handle = rtc.init(do
hour_format: rtc.FORMAT_24H
end)
// Configure wakeup every 10 seconds
rtc.set_wakeup(rtc_handle, do
prescaler: rtc.WAKEUP_DIV_16, // 16Hz clock
counter: 160 // 160 / 16Hz = 10 seconds
end)
io.println("Entering standby, wakeup in 10s...")
core.delay_ms(100) // Flush UART
// Enter standby mode (lowest power)
core.standby()
// After wakeup, system resets
io.println("Woke up from standby!")
// Check wakeup flag
if rtc.was_wakeup_flag_set() ise do
io.println("Wakeup timer triggered")
rtc.clear_wakeup_flag()
end
end
function ana() do
// Count wakeups using backup register
let wakeup_count = rtc.read_backup(rtc_handle, 0)
wakeup_count += 1
rtc.write_backup(rtc_handle, 0, wakeup_count)
io.println("Wakeup count: {}", wakeup_count)
periodic_wakeup()
end
💡 Example: Battery-Backed Data Logger
import hal::rtc
// Store sensor readings in backup registers (survives power loss)
struct LogEntry do
timestamp: int, // Unix timestamp
temp: u16, // Temperature x100
humidity: u16 // Humidity x100
end
const MAX_ENTRIES = 20 // 80 bytes / 4 = 20 entries
function log_data(temp: float, humidity: float) do
let rtc_handle = rtc.init(do hour_format: rtc.FORMAT_24H end)
// Get current index
let index = rtc.read_backup(rtc_handle, 0)
if index >= MAX_ENTRIES ise index = 0
// Get timestamp
let time = rtc.get_time(rtc_handle)
let date = rtc.get_date(rtc_handle)
let timestamp = date_to_unix(date, time)
// Store in backup registers (4 bytes per entry)
let base = 1 + (index * 2)
rtc.write_backup(rtc_handle, base, timestamp)
rtc.write_backup(rtc_handle, base + 1,
((temp * 100.0).int() << 16) | (humidity * 100.0).int()
)
// Update index
rtc.write_backup(rtc_handle, 0, index + 1)
io.println("Logged: {}°C, {}%RH", temp, humidity)
end
function print_log() do
let rtc_handle = rtc.init(do hour_format: rtc.FORMAT_24H end)
let count = rtc.read_backup(rtc_handle, 0).min(MAX_ENTRIES)
io.println("\n=== Data Log ({} entries) ===", count)
each i forde 0..count for do
let base = 1 + (i * 2)
let timestamp = rtc.read_backup(rtc_handle, base)
let data = rtc.read_backup(rtc_handle, base + 1)
let temp = ((data >> 16) & 0xFFFF).float() / 100.0
let hum = (data & 0xFFFF).float() / 100.0
io.println("{}: {:.1f}°C, {:.1f}%",
unix_to_string(timestamp), temp, hum)
end
end
function date_to_unix(date: rtc.Date, time: rtc.Time) -> int do
// Simplified unix timestamp calculation
return (date.year - 1970) * 31536000 +
date.month * 2592000 +
date.day * 86400 +
time.hours * 3600 +
time.minutes * 60 +
time.seconds
end
function ana() do
// Simulate sensor readings
log_data(23.5, 65.2)
core.delay_ms(5000)
log_data(24.1, 63.8)
core.delay_ms(5000)
// Print all logged data
print_log()
end
💡 Example: Timestamp Events (Input Capture)
import hal::rtc, hal::gpio
let event_count = 0
function timestamp_callback() do
let rtc_handle = rtc.init(do hour_format: rtc.FORMAT_24H end)
// Get timestamp
let time = rtc.get_timestamp_time(rtc_handle)
let date = rtc.get_timestamp_date(rtc_handle)
event_count += 1
io.println("Event #{}: {:02}:{:02}:{:02}.{:03}",
event_count,
time.hours,
time.minutes,
time.seconds,
time.subseconds
)
end
function timestamp_input_capture() do
// Configure PA0 (WKUP pin) as timestamp trigger
gpio.clock_enable(gpio.PORT_A)
gpio.pin_init(gpio.PORT_A, 0, do
mode: gpio.MODE_INPUT,
pull: gpio.PULL_DOWN
end)
let rtc_handle = rtc.init(do
hour_format: rtc.FORMAT_24H
end)
// Enable timestamp on rising edge
rtc.enable_timestamp(rtc_handle, do
edge: rtc.TIMESTAMP_RISING_EDGE,
pin: rtc.TIMESTAMP_PIN_0,
callback: timestamp_callback
end)
io.println("Press button on PA0 to timestamp events...")
loop do
core.delay_ms(100)
end
end
function ana() do
timestamp_input_capture()
end
💡 Example: Multi-Alarm Scheduler
import hal::rtc
struct Task do
name: str,
alarm: rtc.Alarm,
callback: fn()
end
let tasks = []
function task_morning() do
io.println("🌅 Good morning! Time to wake up!")
end
function task_lunch() do
io.println("🍽️ Lunch break!")
end
function task_evening() do
io.println("🌙 Evening reminder: Review tasks")
end
function schedule_daily_tasks() do
let rtc_handle = rtc.init(do
hour_format: rtc.FORMAT_24H
end)
// Set current time (for testing: 06:58)
rtc.set_time(rtc_handle, do
hours: 6,
minutes: 58,
seconds: 0
end)
// Alarm A: Morning wakeup (07:00)
rtc.set_alarm(rtc_handle, rtc.ALARM_A, do
hours: 7,
minutes: 0,
seconds: 0,
alarm_mask: rtc.MASK_DATEWEEKDAY, // Daily
callback: task_morning
end)
// Alarm B: Lunch (12:00)
rtc.set_alarm(rtc_handle, rtc.ALARM_B, do
hours: 12,
minutes: 0,
seconds: 0,
alarm_mask: rtc.MASK_DATEWEEKDAY,
callback: task_lunch
end)
io.println("Scheduler started. Waiting for alarms...")
loop do
let time = rtc.get_time(rtc_handle)
io.print("\r{:02}:{:02}:{:02}",
time.hours, time.minutes, time.seconds)
core.delay_ms(1000)
end
end
function ana() do
schedule_daily_tasks()
end
⚙️ RTC structlandırma
// RTC Configuration
struct RTCConfig do
hour_format: HourFormat, // 12H or 24H
async_prediv: int, // Asynchronous prescaler (7-bit)
sync_prediv: int, // Synchronous prescaler (15-bit)
clock_source: ClockSource // LSE, LSI, HSE
end
// Hour Format
enum HourFormat {
FORMAT_12H, // AM/PM
FORMAT_24H // 00:00-23:59
}
// Clock Source
enum ClockSource {
LSE, // 32.768kHz external crystal (most accurate)
LSI, // 32kHz internal RC (less accurate, ±5%)
HSE // High-speed external (rarely used for RTC)
}
// Alarm Configuration
struct AlarmConfig do
hours: int,
minutes: int,
seconds: int,
alarm_mask: AlarmMask, // What to match
callback: fn() // Interrupt callback
end
// Alarm Mask (what to ignore)
enum AlarmMask {
MASK_NONE, // Match all (specific time)
MASK_DATEWEEKDAY, // Ignore date (daily alarm)
MASK_HOURS, // Every hour
MASK_MINUTES, // Every minute
MASK_SECONDS // Every second
}
// Wakeup Configuration
struct WakeupConfig do
prescaler: WakeupPrescaler,
counter: u16 // 0-65535
end
enum WakeupPrescaler {
WAKEUP_DIV_16, // RTC/16 (~2048Hz for 32kHz LSE)
WAKEUP_DIV_8, // RTC/8
WAKEUP_DIV_4, // RTC/4
WAKEUP_DIV_2 // RTC/2
}
📚 RTC functionları
// Initialization
function init(config: RTCConfig) -> Handle
function deinit(handle: Handle)
// Time/Date
function set_time(handle: Handle, time: Time)
function get_time(handle: Handle) -> Time
function set_date(handle: Handle, date: Date)
function get_date(handle: Handle) -> Date
// Alarms
function set_alarm(handle: Handle, alarm: Alarm, config: AlarmConfig)
function disable_alarm(handle: Handle, alarm: Alarm)
function get_alarm_flag(handle: Handle, alarm: Alarm) -> bool
function clear_alarm_flag(handle: Handle, alarm: Alarm)
// Wakeup timer
function set_wakeup(handle: Handle, config: WakeupConfig)
function disable_wakeup(handle: Handle)
function was_wakeup_flag_set() -> bool
function clear_wakeup_flag()
// Timestamp
function enable_timestamp(handle: Handle, config: TimestampConfig)
function get_timestamp_time(handle: Handle) -> Time
function get_timestamp_date(handle: Handle) -> Date
// Backup registers
function write_backup(handle: Handle, register: int, value: u32)
function read_backup(handle: Handle, register: int) -> u32
// Calibration
function calibrate(handle: Handle, ppm: float) // Fine-tune frequency
⚙️ RTC Backup Registers
// Store data that survives reset/power-down
rtc.write_backup(rtc_handle, 0, 0x12345678)
let value = rtc.read_backup(rtc_handle, 0)
// Common use cases:
// - Boot counter
// - Configuration persistence
// - Crash/reset reason
// - Sensor calibration data
// - Short-term data logging (80 bytes total)
// Example: Boot counter
let boot_count = rtc.read_backup(rtc_handle, 0)
boot_count += 1
rtc.write_backup(rtc_handle, 0, boot_count)
io.println("Boot count: {}", boot_count)
📊 RTC Use Cases
| Senaryo | Özellik | Güç Tüketimi | Açıklama |
|---|---|---|---|
| Digital Clock | Time/Date | Active | Real-time display |
| Alarm Clock | Alarm A/B | Sleep + Interrupt | Wake on alarm |
| Periodic Wakeup | Wakeup Timer | Standby (~1μA) | Ultra-low-power sensor reading |
| Event Timestamp | Timestamp | Active | Precise event logging |
| Data Logger | Backup Regs | VBAT (~1μA) | Survive power loss |
⚡ Performance Tips
- LSE Crystal: Kullanın en yüksek accuracy for (±20ppm)
- VBAT: CR2032 coin cell ile yıllarca RTC çalıştırabilir (~1μA)
- Wakeup Timer: Periodic sensor reading for ideal (standby mode)
- Backup Registers: Configuration data for kullanın (80 bytes)
- Calibration: Temperature compensation for smooth calibration
🖥️ Platform Support
- STM32F1: Basic RTC (1 alarm, backup regs)
- STM32F4/L4: Advanced RTC (2 alarms, wakeup, timestamp, 80 backup bytes)
- STM32H7: High-precision RTC with sub-second resolution
- ESP32: RTC with ULP coprocessor support
⚠️ Important Notes
- Clock Source: LSE (32.768kHz crystal, ±20ppm) en accurate, LSI (32kHz RC, ±5%) backup
- VBAT Pin: CR2032 battery (3V) ile power-down'da RTC çalışmaya devam eder
- Write Protection: RTC register'ları write-protected, unlock gerekir
- Alarm Interrupts: EXTI line 17 (Alarm A), 18 (Alarm B) kullanır
- Wakeup from Standby: Wakeup timer ile ultra-low-power periodic operation
- Backup Domain: RTC + backup regs separate power domain (VBAT)
- Calendar: Leap year otomatik hesaplanır, 2000-2099 range
- Sub-second: Synchronous prescaler ile ms resolution mümkün
🔗 Related Modules
hal::int- RTC alarm interrupts (NVIC)hal::core- System wakeup from standbyhal::gpio- Timestamp input pin
📖 References
- AN3371: Using STM32 RTC
- AN4759: Using STM32 RTC Wakeup Timer
- Reference Manual: Real-time clock (RTC) chapter