版本 cd362b08cff9874f7de7ba83a6b67cc45390001f
embedded/RTC
Introduction
Real-Time Clock(RTC)是負責記錄時間的元件,出現在需要長期使用時鐘的電子設備中。
RTC block diagram
.. image:: /rtc_block.png
How it works
Generate 1Hz
http://wiki.csie.ncku.edu.tw/embedded/RTC RTC基本計算單位為一秒鐘。
由於clock source速度太快,我們需要用prescaler去轉換成一秒鐘。
.. image:: /stm32 RTC prescaler.png
基於省電需求,將prescaler分為兩個區塊,首先經由較省電的Asynchronous prescaler,再透過較耗能量的Synchronous prescaler輸出1Hz。
根據clock source的頻率不同,我們調整不同的prescaler參數。
.. image:: /embedded/RTC/ck_spre_formula.png
LSE: 32.768kHz / (127+1) / (255+1) = 1Hz
LSI: 32kHz / (127+1) /(249+1) =1Hz
Alarm
鬧鐘。
calendar register與alarm作比較,如果相同則將對應的flag拉起來。
.. image:: /embedded/RTC/alarm_pass.png
Functionality
Prescaler
Prescaler generates the clock to update the calendar.
To minimize power comsuption the prescaler is split into two prescalers, asynchronous and synchronous. It is recommended to configure the asynchronous prescaler to a high value to minimize consumption.
asynchronous prescaler clocks subsecond of calendar and propagates to synchronous prescaler to update date and time by second.
One can configure them through PREDIV_A
and PREDIV_S
bits in RTC_PRER
Calendar and Alarm
A calendar keeps track of the date (day, week, month, year) and time (hours, minutes and seconds) and even subseconds. It manages of numbers of days of mouths automaticly. Daylight saving time adjustment is programmable by software.
Binary repersentation is in binary-coded decimal (BCD) format.
Data can be read indirectly from shadow registers or directly from counters. The former method delays some clocks but ensures consistency between date and time registers; the later is opposite but this is especially useful after exiting from low power modes, since the shadow registers are not updated during these modes.
Data, time, and subsecond are separately recorded in RTC_DR
, RTC_TR
, and RTC_SSR
. With BYPSHAD
bit set, data can be read directly from counter.
Two programmable alarms (Alarm A, Alarm B) with interrupt function. The alarms can be triggered by any combination of the calendar fields.
An alarm consists of a register with the same length as the RTC time counter. When the RTC time counter reaches the value programmed in the alarm register, a flag is set to indicate that an alarm event occurred.
In addition to the time to trigger, alarm can be configured to mask some fields and do not compare.
Auto periodic wakeup
A periodic timebase and wakeup unit that can wake up the system from low power modes. When this counter reaches zero, a flag and an interrupt are generated.
It’s source clock can be RTC clock or prescaler. Time range can be configured through WUCKSEL
Timestamp
The calendar is saved in timestamp registers when timestamp event is detected on the pin which timestamp alternate function is mapped.
Tamper detection
It can be used for edge detection or level detection with filtering according to TAMPFLT
. Set to 00 is edge detection, others arg level detection.
When TAMPTS
set to 1, tamper event trigger timestamp event automatically.
Backup registers
Program can read or write data from or to these registers, which are not reset by system reset or power-on reset. They are reset when tamper detection event occurs.
Alternate function outputs
Two outputs are avalible : RTC_CALIB
and RTC_ALARM
.
RTC_CALIB
output is used to generate a variable-frequency signal. It can use either asynchronous or synchronous prescaler as clock.
besides alarm, RTC_ALARM
can use wakeup timer as source.
Synchronization and Reference clock detection
RTC can be synchronized to remote clock by adding a ‘shift’ to counter continuously to delay, or vice versa. With reference clock detection, RTC shifts misaligned 1 Hz clock to align it with the nearst referenced edge (found in a given time window).
One can adjust time by configuring shift through RTC_SHIFTR
.
When reference clock detection is enabled (REFCKON
), must not write RTC_SHIFTR
and not enable calibration and set prescalers (PREDIV_A
and PREDIV_S
) to default.
Digital calibration
Calibration can be used to compensate inaccuracy of oscillator by adding or substracting clock cycles in each calibration cycle.
There are two calibration methods : coarse and smooth. They should not be used togather. The cycle of the later is smaller than the former. It makes the later is more flexible to adjust clock. A smooth calibration can be performed on the fly so that it can be changed to handle changed envirenment variables.
coarse calibration is provided for capability reasons. It can only be configured in initialization mode and start when INIT bit is cleared. Also it is recommaned using it for static correction only.
Low power modes
The RTC is designed to minimize the power consumption.
The RTC runs as usual in Sleep mode.
In Stop mode and Standby mode, the RTC remains active when clock source is LSE or LSI.
Alarm, tamper event, time stamp event, and wakeup cause the device to exit low power mode.
.. image:: /RTC in low power mode.png
wakeup, effectiveness and voltage in three lowpower modes
.. image:: /embedded/RTC/stm32 low power mode summary.png
Configuration
Register write protection
After system reset, the RTC registers are protected registers are automatically locked to against possible parasitic write accesses.
RTC registers need to disable backup domain protection to update the current calendar time and date.
set ``DBP`` bit in ``PWR_CR``
After power-up reset, the RTC registers are also protected and need to write a key into protection register. RTC_ISR[13:8], RTC_TAFCR, and RTC_BKPxR are except. Write a wrong key will enable protection.
write ``0xCA`` to ``RTC_WPR``
write ``0x53`` to ``RTC_WPR``
Initialization mode
Modifications of RTC_DR
, RTC_TR
, and RTC_PRER
must be done in Initialization mode.
set ``INIT`` bit of ``RTC_ISR`` to enter Initialization mode
wait until ``RTC_ISR`` / ``INITF`` is set then ready to write
reset ``INIT`` bit of ``RTC_ISR`` to exit Initialization mode
Counter does not run in Initialization mode.
Example
initialize RTC
.. code-block:: prettyprint
RTC_InitTypeDef RTC_InitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE); /* Enable the PWR clock */
PWR_BackupAccessCmd(ENABLE); /* Allow access to RTC */
RCC_LSICmd(ENABLE); /* Enable the LSI OSC */
while(RCC_GetFlagStatus(RCC_FLAG_LSIRDY) == RESET); /* Wait till LSI is ready */
RCC_RTCCLKConfig(RCC_RTCCLKSource_LSI); /* Select the RTC Clock Source */
RCC_RTCCLKCmd(ENABLE); /* Enable the RTC Clock */
RTC_WaitForSynchro(); /* Wait for RTC APB registers synchronisation */
/* Configure the RTC data register and RTC prescaler */
RTC_InitStructure.RTC_AsynchPrediv = 0x7F;
RTC_InitStructure.RTC_SynchPrediv = 0xF9;
RTC_InitStructure.RTC_HourFormat = RTC_HourFormat_24;
RTC_Init(&RTC_InitStructure);
setting time
.. code-block:: prettyprint
/* set 8:29:55 */
RTC_TimeTypeDef RTC_TimeStruct;
RTC_TimeStruct.RTC_Hours = 8;
RTC_TimeStruct.RTC_Minutes = 29;
RTC_TimeStruct.RTC_Seconds = 55;
RTC_SetTime(RTC_Format_BIN, &RTC_TimeStruct);
initialize RTC alarm
.. code-block:: prettyprint
EXTI_InitTypeDef EXTI_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
/* EXTI configuration */
EXTI_ClearITPendingBit(EXTI_Line17);
EXTI_InitStructure.EXTI_Line = EXTI_Line17;
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTI_InitStructure);
/* Enable the RTC Alarm Interrupt */
NVIC_InitStructure.NVIC_IRQChannel = RTC_Alarm_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
setting alarm time
.. code-block:: prettyprint
RTC_AlarmTypeDef RTC_AlarmStructure;
RTC_AlarmCmd(RTC_Alarm_A, DISABLE); /* disable before setting or cann't write */
/* set alarm time 8:30:0 everyday */
RTC_AlarmStructure.RTC_AlarmTime.RTC_H12 = 0x00;
RTC_AlarmStructure.RTC_AlarmTime.RTC_Hours = 8;
RTC_AlarmStructure.RTC_AlarmTime.RTC_Minutes = 30;
RTC_AlarmStructure.RTC_AlarmTime.RTC_Seconds = 0;
RTC_AlarmStructure.RTC_AlarmDateWeekDay = 0x31; // Nonspecific
RTC_AlarmStructure.RTC_AlarmDateWeekDaySel = RTC_AlarmDateWeekDaySel_Date;
RTC_AlarmStructure.RTC_AlarmMask = RTC_AlarmMask_DateWeekDay; // Everyday
RTC_SetAlarm(RTC_Format_BIN, RTC_Alarm_A, &RTC_AlarmStructure);
/* Enable Alarm */
RTC_ITConfig(RTC_IT_ALRA, ENABLE);
RTC_AlarmCmd(RTC_Alarm_A, ENABLE);
RTC_ClearFlag(RTC_FLAG_ALRAF);
complete code
.. code-block:: c
git clone git@gitcafe.com:ctc8631/RTC-example.git
cd RTC-example/
make flash
Reference
RTC application note<http://www.st.com/internet/com/TECHNICAL_RESOURCES/TECHNICAL_LITERATURE/APPLICATION_NOTE/DM00025071.pdf>
_