AN108 - Silicon Labs

AN108
IMPLEMENTING A REALTIME CLOCK
Relevant Devices
This application note describes how to implement
the function of a real-time clock inexpensively by
This application note applies to the following using a C8051Fxxx device, a small 32 kHz watch
devices:
crystal, and a few passive components.
C8051F000, C8051F001, C8051F002,
C8051F005, C8051F006, C8051F007,
C8051F010, C8051F011, and C8051F012.
Introduction
The purpose of this note is to provide an example
of how to add a real-time clock (RTC) feature to a
C8051F00x or C8051F01x device. Example software is included at the end of this note.
Key Points
•
•
•
•
The external oscillator can be used to drive a
crystal for the RTC while the system clock uses
the high-frequency internal oscillator.
The system clock can be derived from the internal or external oscillator, and can change
sources without compromising the accuracy of
the RTC.
The RTC uses Timer 2, which is configured to
increment on falling edges of an external input.
Comparator 0 is used to convert the crystal
waveform to a square wave.
Because the CPU overhead and resource requirements of the RTC are very small, this functionality
can easily be added to an existing 8051-based system.
In this design, a 32 kHz watch crystal is connected
to the external oscillator of the C8051 device. The
output signal from the crystal oscillator is conditioned by one of the internal analog comparators
and fed into a timer input. The timer is configured
in auto-reload mode to generate an interrupt at a
periodic rate, one-tenth second in this example.
The interrupt service routine for the timer updates a
series of counters for seconds, minutes, hours, and
days.
Overview
Real-time clocks are used in many embedded
applications to record the time at which an event
occured, a pressure sensor was activated, or an
ADC reading was taken, for example. Currently
there are off-the-shelf components that contain a
small crystal time base coupled with simple logic
that have standardized interfaces for connecting to
the I2C, SPI, or parallel port of a microcontroller.
Rev. 1.2 12/03
Copyright © 2003 by Silicon Laboratories
AN108-DS12
AN108
Hardware Description
The output of the on-chip comparator is routed to
an external GPIO pin (CP0, determined by the
crossbar) and connected to the input signal of
Timer 2 (T2, also determined by the crossbar).
Timer 2 increments once for each falling edge
detected at the T2 input.
A schematic of the hardware is shown in Figure 1.
This design uses an external 32kHz watch crystal
as the time base for the RTC. This crystal is connected between the XTAL1 and XTAL2 pins of the
device. Note that the external oscillator’s crystal
driver can be enabled while the CPU core is operat- Timer 2 is configured in 16-bit auto-reload mode to
ing from the internal oscillator.
generate an interrupt every 3200 counts, or once
every tenth of a second. The interrupt handler for
The XTAL2 output is fed into the (+) input of an Timer 2 updates a series of counters for tenths of
on-chip analog comparator (Comparator 0). A low- seconds, seconds, minutes, hours, and days.
pass filtered version of the XTAL2 signal is fed to
the (-) input of the comparator to provide the DC The default mode of the RTC implementation
bias level at which to detect the transitions of the assumes that the CPU system clock (SYSCLK) is
oscillating signal. The corner frequency of this fil- derived from the high-speed internal oscillator.
ter, where R = 1 MΩ and C = 0.022 µF, is substan- When the system clock is changed to use the extertially below the frequency of oscillation.
nal 32kHz source, for example to save power,
Timer 2 is switched by the software to use
SYSCLK as its time base. Synchronizing the clock
CRYSTAL
XTAL1
Input
Circuit
XTAL2
OSC
CP0+
R
CP0
CP0-
XTAL2
C
LPF
Digital
Crossbar
P0.0
P0.1
Timer 2
Figure 1. Connection Diagram
2
Rev. 1.2
AN108
switching inside the RTC interrupt handler ensures
no loss of accuracy.
Crossbar Configuration
The connection between internal digital peripherals
and the GPIO pins is handled by the crossbar. In
this design, the crossbar routes the CP0 output and
T2 input to GPIO pins P0.0 and P0.1, respectively.
It is important to note that the specific port pins
used will change if peripherals with a higher crossbar priority are enabled (see AN001). Crossbar
setup is accomplished with the following statements:
; enable CP0 outpput
mov XBR0, #80h
; enable T2 input
mov XBR1, #20h
; enable crossbar and weak pull; ups
mov XBR2, #40h
Oscillator Configuration
Comparator Configuration
The Comparator 0 setup involves setting the positive and negative hysteresis and enabling the comparator.
The comparator hysteresis can be
configured in the comparator control register
CPT0CN. Since the voltage of the XTAL2 signal
will be fairly large (500 mV to 3 V), the CP0 hysteresis can be set high to provide noise immunity.
The hysteresis is set and the comparator is enabled
with the following statements:
; set CP0 hysteresis 10mV/10mV
mov CPT0CN, #0Ah
; enable CP0
orl CPT0CN, #80h
Timer Configuration
When the CPU system clock (SYSCLK) is derived
from the high-frequency internal oscillator, Timer 2
is configured in auto-reload mode to count falling
edges on the external signal T2. Timer 2 is configured with the following statement:
Refer to AN002 for details on configuring external
oscillator. The following statement configures and
mov T2CON, #02h
enables the external oscillator for use with a
We must also set the initial and reload values for
32 kHz crystal.
Timer 2. The initial value is the value loaded into
Timer 2 before it is enabled, and the reload value,
; enable external oscillator
; in ‘crystal’ mode; XFCN = 001
held in RCAP2H (high byte) and RCAP2L (low
; for a 32kHz crystal
byte), is loaded into Timer 2 after an overflow. The
mov OSCXCN, #61h
initial and reload values, which are identical, are
Once configuration is complete, the external oscil- determined by the precision required of the reallator must be checked for stability before enabling time clock. This design implements precision of a
the timer. The XTLVLD bit (OSCXN.7) is set tenth of a second; therefore, Timer 2 is set to overwhen the crystal is running and stable. Software flow every tenth of a second, or every 3200 counts
of the 32 kHz time base. We set the COUNT value
polls the XTLVLD bit before enabling Timer 2:
to 3,200, and set the reload values in the RCAP2
registers with the following commands:
; wait until the external osc.
; is stable
WAIT:
mov ACC, OSCXCN
jnb ACC.7, WAIT
;set T2 reload high byte
mov RCAP2H, #HIGH(-COUNT)
;set T2 reload low byte
mov RCAP2L, #LOW(-COUNT)
; enable Timer 2
setb TR2
Rev. 1.2
3
AN108
When Timer 2 overflows, it will be reloaded to
overflow in another 3200 counts, and it will generate an interrupt. The program will vector to the
Timer 2 interrupt service routine every tenth of a
second to increment the counters. Because the
interrupt service routine is short and is only called
once every tenth of a second, CPU utilization is
remarkably low.
In order to guarantee that no external clock edges
are missed, the SYSCLK should be updated in the
RTC’s interrupt service routine.
The system clock can be changed by setting either
SET_EXT_OSC (to change to the external oscillator) or SET_INT_OSC (to change to the internal
oscillator) to ‘1’. These bits are used as flags in the
Timer 2 ISR to permit changing of the system
Once Timer 2 is configured, its interrupt must be clock without sacrificing RTC accuracy. Details are
enabled with the following statement:
given in the software description at the end of this
report.
; enable Timer 2 interrupt
setb ET2
Software Description
Timer 2 is enabled after all other timer configuraThis section contains a description of the software
tion is complete by setting its run bit:
flow. The program listing begins on page 6.
; start Timer 2
setb TR2
Main Function
The MAIN function is used to configure the crossbar, external oscillator, comparator, and timer.
The default configuration of this RTC example First we setup the external crystal by enabling the
assumes that the CPU system clock (SYSCLK) is external oscillator and setting the power factor bits.
derived from the high-speed internal oscillator. If
SYSCLK is derived instead from the external oscil- The crossbar setup and CP0 setup values described
lator, for power savings, the configuration for above are then loaded, and then each are enabled.
Timer 2 must be changed to use SYSCLK as the The crystal must be settled before Timer 2 is
time base because signals at T2 can have a maxi- enabled. When the crystal is settled, the XTLVLD
mum frequency of SYSCLK / 4 in order to be bit is set by hardware, and the program moves past
the WAIT loop. At the end of the MAIN function
properly detected.
the RTC_INIT function is called, Timer 2 is
The process for changing the system clock is as fol- enabled, and global interrupts enabled.
lows:
System Clock Switching
1. Stop the timer (TR2 = ‘0’).
2. Change timer time base.
3. Change SYSCLK time base.
4. Add correction factor to timer’s counter.
5. Start the timer (TR2 = ‘1’).
4
RTC Initialization Function
The RTC_INIT function is used to reset the counter
values and to configure Timer 2. This function can
be used as a reset for the RTC. After clearing the
counter values, the initial value for Timer 2 is set to
the COUNT value as described in the configuration
section. The COUNT value is also loaded into the
reload registers (RCAP2H & RCAP2L). Timer 2 is
then set to increment on external input edges, and
the Timer 2 interrupt is enabled.
Rev. 1.2
AN108
Timer Interrupt Service Routine
The Timer 2 ISR is called each time Timer 2 overflows (once every tenth of a second). When the
ISR is called, it first clears the Timer 2 interrupt
flag (TF2). The ISR then checks for overflows in
all of the counters, starting with the tenths counter.
If the tenths counter is at 9, it is reset to 0 and the
seconds are checked for an overflow. Similarly, if
the seconds are at 59, they are reset to 0, and the
minutes are checked. The hours and days are
checked in the same fashion. The counter is incremented, and then the oscillator selection bits
(SET_EXT_OSC and SET_INT_OSC) are
checked.
enabled. The ISR then exits to wait for another
overflow.
Counter Access
The tenths/seconds/minutes/etc counters can be
accessed by calling the SAVE routine. The SAVE
routine first saves the current state of the Timer 2
interrupt flag in the Carry bit and then disables the
Timer 2 interrupt so that no interrupts occur during
the save. Disabling the interrupt does no harm here
because the interrupt will be enabled again at the
end of the SAVE routine. If an interrupt is generated during the SAVE routine, it will be serviced as
soon as the Timer 2 interrupt is enabled again.
After ET2 is cleared, each counter is saved
(TENTHS into STORE_T, SECONDS into
Oscillator Selection
STORE_S, etc). The interrupt flag is restored, and
If the SET_EXT_OSC bit is set, the bit is cleared, the function returns to its caller.
and the program jumps to the EXT_OSC label.
First, OSCICN is checked--if the system clock is
already using the external oscillator, the ISR exits.
If not, Timer 2 is disabled to avoid any miscounts
during the system clock switch. CKCON is setup
so that the Timer 2 input clock is the system clock
divided by one. Timer 2 is then set to increment on
the system clock, and the Timer 2 counter register
is updated to compensate for missed ticks during
the SYSCLK transition. Between the system clock
switch and the Timer 2 re-enable, Timer 2 misses 5
ticks. The correction value, EXT_COR, is set to 5;
this value is added to the Timer 2 register before
the system clock is switched to the external oscillator. After the switch, Timer 2 is enabled again, and
the ISR exits.
If the SET_INT_OSC bit is set, the bit is cleared
and the program jumps to the INT_OSC label.
OSCICN is checked first to make sure the system
clock is not already using the internal oscillator. If
it is not, Timer 2 is disabled for the clock switch.
The internal oscillator is selected as the system
clock, and then the correction value, COR_INT is
added to the Timer 2 register. In this case, 3 ticks
are missed during the switch. COR_INT, which is
set to 3, is added to Timer 2. The external input pin
is selected as the Timer 2 input, and Timer 2 is
Rev. 1.2
5
AN108
Software Example
;---------------------------------------------------------------------------------; CYGNAL, INC.
;
;
; FILE NAME
: RTC_1.asm
; TARGET DEVICE
: C8051F0xx
; DESCRIPTION
: Software implementation of a real-time clock
;
; AUTHOR
: JS
;
; Software implementation of a real-time clock using a 32KHz crystal oscillator.
; This program uses the crystal driver, XTAL2 to drive Comparator 0. The positive
; comparator input is from XTAL2, and the negative input is an averaged version of
; XTAL2. The averaging is done by a low pass filter. The output of Comparator 0
; is routed to the Timer 2 input (T2).
;
; Timer 2 is configured in auto-reload mode, and is set to trigger on
; the external input pin connected to the Comparator 0 output.
;
; This code assumes the following:
;
; (1)
An external oscillator is connected between XTAL1 and XTAL2
; (2)
A low pass averaging filter is connected bewteen XTAL2 and CP0; (3)
XTAL2 is routed to CP0+
; (4)
CP0 output is routed to Timer 2 input through the port pins assigned
;
by the crossbar
;
; For a 32KHz crystal, the low pass filter consists of a 0.022uF capacitor and a
; 1 Mohm resistor.
;---------------------------------------------------------------------------------;---------------------------------------------------------------------------------; EQUATES
;---------------------------------------------------------------------------------$MOD8F000
;
;
;
;
Count value: This value is used to define what is loaded into timer 2 after each
overflow.The count value is 3200, meaning the timer will count 3200 ticks before an
overflow. Used with the 32KHz crystal, this means the timer will overflow every
tenth of a second.
COUNT
EQU
3200d
; count value
; Compensation factors for system clock switching used to update Timer 2 after a
; system clock change
EXT_COMP
INT_COMP
EQU
EQU
5d
3d
;---------------------------------------------------------------------------------; VARIABLES
;---------------------------------------------------------------------------------DSEG
6
Rev. 1.2
AN108
org 30h
TENTHS:
SECONDS:
MINUTES:
HOURS:
DAYS:
DS
DS
DS
DS
DS
1
1
1
1
1
;
;
;
;
;
counts
counts
counts
counts
counts
tenths of seconds
seconds
minutes
hours
days
STORE_T:
DS
1
STORE_S:
STORE_M:
STORE_H:
STORE_D:
DS
DS
DS
DS
1
1
1
1
;
;
;
;
;
;
storage byte for tenths,
used by SAVE routine
storage byte for seconds
minutes
hours
days
;
;
;
;
flag to change system clock
to external osc
flag to change system clock
to internal osc
BSEG
org
00h
SET_EXT_OSC: DBIT
1
SET_INT_OSC: DBIT
1
;---------------------------------------------------------------------------------; RESET and INTERRUPT VECTORS
;---------------------------------------------------------------------------------CSEG
; Reset Vector
org
00h
ljmp
MAIN
; Timer 2 ISR Vector
org
2Bh
ljmp
T2_ISR
; Timer 2 ISR
;---------------------------------------------------------------------------------; MAIN PROGRAM
;---------------------------------------------------------------------------------org
0B3h
MAIN:
mov
OSCXCN, #61h
; enable external oscillator
; in ‘crystal’ mode for a
; 32kHz watch crystal
mov
mov
WDTCN, #0DEh
WDTCN, #0ADh
; disable watchdog timer
; Setup Crossbar
mov
XBR0, #80h
mov
XBR1, #20h
mov
XBR2, #40h
; enable CP0 output
; enable T2 input
; enable crossbar
; Setup Comparator 0
Rev. 1.2
7
AN108
mov
orl
orl
CPT0CN, #08h
CPT0CN, #02h
CPT0CN, #80h
; set positive hysteresis to 10mV
; set negative hysteresis to 10mV
; enable CP0
acall
RTC_INIT
; Initialize RTC and Timer 2
mov
ACC, OSCXCN
jnb
ACC.7, Wait
;
;
;
;
setb
TR2
; turn on Timer 2 (starts RTC)
setb
EA
; enable global interrupts
jmp
$
; spin forever
WAIT:
wait until the external
oscillator is steady
by checking the XTLVLD bit
in OSCXCN
;----------------------------------------------------------------------------------; Initialization Subroutine
;----------------------------------------------------------------------------------RTC_INIT:
; Clear all counters
mov
TENTHS, #0
mov
SECONDS, #0
mov
MINUTES, #0
mov
HOURS, #0
mov
DAYS, #0
; Setup Timer2 in auto-reload mode to count falling edges on external T2
mov
mov
TH2, #HIGH(-COUNT)
TL2, #LOW(-COUNT)
; set initial value for timer 2
mov
mov
RCAP2H, #HIGH(-COUNT)
RCAP2L, #LOW(-COUNT)
; set reload value for timer 2
mov
setb
ret
T2CON, #02h
ET2
; configure Timer 2 to increment
; falling edges on T2
; enable Timer 2 interrupt
;----------------------------------------------------------------------------------; Timer 2 ISR
;----------------------------------------------------------------------------------T2_ISR:
clr
push
push
TF2
PSW
ACC
; Check for overflows
mov
A, TENTHS
cjne
A, #9d, INC_TEN
mov
8
TENTHS, #0
; clear overflow interrupt flag
; preserve PSW (carry flag)
; preserve ACC
; if tenths less than 9, jump
; to increment
; if tenths = 9, reset to zero,
Rev. 1.2
AN108
; and check seconds
mov
cjne
A, SECONDS
A, #59d, INC_SEC
mov
SECONDS, #0
mov
cjne
A, MINUTES
A, #59d, INC_MIN
mov
MINUTES, #0
mov
cjne
A, HOURS
A, #23d, INC_HOUR
mov
HOURS, #0
inc
DAYS
; DAYS will roll over after 255
jmp
CHECK_OSC
; jump to check for oscillator
; change request
;
;
;
;
if seconds less than 59, jump
to increment
if seconds = 59, reset to zero,
and check minutes
;
;
;
;
if minutes less than 59, jump
to increment
if minutes = 59, reset to zero,
and check hours
;
;
;
;
if hours less than 23, jump
to increment
if hours = 23, reset to zero,
and check days
;Increment counters---------------------------------------------------------------INC_TEN:
inc
jmp
TENTHS
CHECK_OSC
; increment tenths counter
; jump to check for oscillator
; change request
INC_SEC:
inc
jmp
SECONDS
CHECK_OSC
; increment seconds counter
; jump to check for oscillator
; change request
INC_MIN:
inc
jmp
MINUTES
CHECK_OSC
; increment minutes counter
; jump to check for oscillator
; change request
INC_HOUR:
inc
HOURS
jmp
CHECK_OSC
; increment hours counter
; jump to check for oscillator
; change request
;Oscillator changes---------------------------------------------------------------CHECK_OSC:
jbc
SET_EXT_OSC, EXT_OSC
jbc
SET_INT_OSC, INT_OSC
jmp
END_ISR
;
;
;
;
;
ACC, OSCICN
; switch system clock to
; external oscillator
; check current system clock
EXT_OSC:
mov
check for external oscillator
select
check for internal oscillator
select
exit
Rev. 1.2
9
AN108
jb
ACC.3, END_ISR
; exit if already using external
; oscillator
orl
CKCON, #20h
clr
clr
TR2
CT2
;
;
;
;
select system clock (divide by 1)
for Timer 2
disable Timer 2 during clock change
select SYSCLK as Timer 2 input
mov
A, #LOW(EXT_COR)
add
A, TL2
mov
TL2, A
;
;
;
;
;
load correction value into
accumulator
add correction value to Timer 2
counter register
store updated Timer 2 value
orl
OSCICN, #08h
setb
TR2
; select external oscillator as
; system clock
; enable Timer 2 after clock change
jmp
END_ISR
; exit
INT_OSC:
; switch system clock to internal
; oscillator
mov
jnb
ACC, OSCICN
ACC.3, END_ISR
; check current system clock
; exit if already using internal
; oscillator
clr
anl
TR2
OSCICN, #0f7h
; disable Timer 2 during clock change
; select internal oscillator as
; system clock
mov
A, #LOW(INT_COR)
add
A, TL2
mov
TL2, A
;
;
;
;
;
setb
setb
CT2
TR2
; select external Timer 2 input
; enable Timer 2 after clock change
jmp
END_ISR
; exit
ACC
PSW
; restore ACC
; restore PSW
load correction value into
accumulator
add correction value to Timer 2
register
store updated Timer 2 value
END_ISR:
pop
pop
reti
;----------------------------------------------------------------------------------; Counter Save Routine
;----------------------------------------------------------------------------------SAVE:
10
mov
C, ET2
; preserve ET2 in Carry
clr
ET2
; disable Timer 2 interrupt
; during copy
Rev. 1.2
AN108
mov
mov
mov
mov
mov
STORE_T,
STORE_S,
STORE_M,
STORE_H,
STORE_D,
mov
ret
ET2, C
TENTHS
SECONDS
MINUTES
HOURS
DAYS
; copy all counters
; restore ET2
;--------------------------------------------------------------------------------END
Rev. 1.2
11
AN108
Contact Information
Silicon Laboratories Inc.
4635 Boston Lane
Austin, TX 78735
Tel: 1+(512) 416-8500
Fax: 1+(512) 416-9669
Toll Free: 1+(877) 444-3032
Email: [email protected]
Internet: www.silabs.com
The information in this document is believed to be accurate in all respects at the time of publication but is subject to change without notice.
Silicon Laboratories assumes no responsibility for errors and omissions, and disclaims responsibility for any consequences resulting from
the use of information included herein. Additionally, Silicon Laboratories assumes no responsibility for the functioning of undescribed features
or parameters. Silicon Laboratories reserves the right to make changes without further notice. Silicon Laboratories makes no warranty, representation or guarantee regarding the suitability of its products for any particular purpose, nor does Silicon Laboratories assume any liability
arising out of the application or use of any product or circuit, and specifically disclaims any and all liability, including without limitation consequential or incidental damages. Silicon Laboratories products are not designed, intended, or authorized for use in applications intended to
support or sustain life, or for any other application in which the failure of the Silicon Laboratories product could create a situation where personal injury or death may occur. Should Buyer purchase or use Silicon Laboratories products for any such unintended or unauthorized application, Buyer shall indemnify and hold Silicon Laboratories harmless against all claims and damages.
Silicon Laboratories and Silicon Labs are trademarks of Silicon Laboratories Inc.
Other products or brandnames mentioned herein are trademarks or registered trademarks of their respective holders.
12
Rev. 1.2