Real time clock of LPC2148

LPC2000 series of microcontrollers have a built-in Real Time Clock (RTC) unit, which may be used for counting time to maintain a calendar and clock. RTC is designed for low power designs that enable use in battery-powered designs. The real-time clock can count time in Seconds, Minutes, Hours, Days of Month, Months, Years, Days of the week, and Days of Year. The real-time module can be clocked using a distinct 32kHz clock oscillator or internal prescaller from the VPB clock. The real-time clock unit has additional power supply pins (3.3V) that allow the RTC clock to work when the system is off – actually power-down mode operated from the clock battery.


As there are many functions in clocks like time units(seconds, minutes, etc.) and alarms, there are quite some registers to cover clock functionality. There are several groups of registers:

  • Miscellaneous registers like Interrupt Location Register(ILR), Clock Tick Counter(CTC), Alarm Mask Register(AMR);
  • Time Counter register Group which includes registers that contain Time values(Seconds, Minutes,…);
  • Alarm register group – registers that hold alarm settings and that are compared to Time Group registers. When a match occurs, an interrupt is generated;
  • Registers that control Reference Clock Divider – with these registers, it is possible to get 32768Hz from peripheral clock frequency.

Among the Miscellaneous register group, there are three Consolidated Time registers. They have packed time value in one word: CTIME0 register contain Seconds[5:0], Minutes[13:8], Hours[20:16] and Day of Week[26:24]; CTIME1 register contain Day of Month[4:0], Month[11:8], Year[27:16] and CTIME2 contains day of Year[11:0]. So Consolidated registers allow reading all-time information just in three operations instead of eight.

RTC has two interrupt mechanisms.

  • One of them is that you can program an interrupt each time any timer-counter is incremented – this allows generating an interrupt every second and once a year when the Year value is incremented. So this way, you can generate interrupts for each of the eight-time registers increment.
  • The second interrupt mechanism allows generating an interrupt according to alarm register values. When alarm registers match time counter registers, speaking is the alarm register is unmasked. Then an interrupt will occur when all-time registers match. Mask register is used to mask registers that don’t have to be compared like; if you want to set the alarm for each morning, you need to mask off Year, day of the week, day of the month, and so on. Just leave seconds, minutes, and hours.
* WinARM RTC application
* - UART0 send in Interrupt-Mode
* - Sends message every seccond.
* - RTC interupt every second
#include "types.h"
#include "LPC214x.h"
#include "config.h"
#include "armVIC.h"
#include "uart.h"
uint32_t time_toggle=0;
static void rtc0(void) __attribute__ ((interrupt ("IRQ")));
static void sysInit(void)
// set PLL multiplier & divisor.
// values computed from config.h
// enable PLL
PLLFEED = 0xAA; // Two updates
PLLFEED = 0x55; // MUST occur in sequence.
// setup the parallel port pin
IO0CLR = PIO0_ZERO_BITS; // clear the ZEROs output
IO0SET = PIO0_ONE_BITS; // set the ONEs output
IO0DIR = PIO0_OUTPUT_BITS; // set the output bit direction
IO1CLR = PIO1_ZERO_BITS; // clear the ZEROs output
IO1SET = PIO1_ONE_BITS; // set the ONEs output
IO1DIR = PIO1_OUTPUT_BITS; // set the output bit direction
// wait for PLL lock
// enable & connect PLL
PLLFEED = 0xAA; // Two updates
PLLFEED = 0x55; // MUST occur in sequence.
// setup & enable the MAM
// set the peripheral bus speed
// value computed from config.h
VPBDIV = VPBDIV_VALUE; // set the peripheral bus clock speed
// set the interrupt controller defaults
#if defined(RAM_RUN)
MEMMAP = MEMMAP_SRAM; // map interrupt vectors space into SRAM
#elif defined(ROM_RUN)
MEMMAP = MEMMAP_FLASH; // map interrupt vectors space into FLASH
#error RUN_MODE not defined!
VICIntEnClear = 0xFFFFFFFF; // clear all interrupts
VICIntSelect = 0x00000000; // clear all FIQ selections
VICDefVectAddr = (uint32_t)reset; // point unvectored IRQs to reset()
// wdtInit(); // initialize the watchdog timer
initSysTime(); // initialize the system timer
void rtc0(void)
if (time_toggle==0)
uart0Puts("nrTicrn");//Tic Tac output to UART0
ILR |= 1; // Clear interrupt flag
VICVectAddr = 0; // Acknowledge Interrupt
PCON = 1; // IDLE mode
void init_rtc(void)
ILR = 3; // Disable 32'768 interrupt
CCR = 0x11; // Clock enable + 32'767Hz quartz enable
CIIR = 0x01; // Interupt every second
VICVectAddr1 = (unsigned long)rtc0; // set interrupt vector in 1
VICVectCntl1 = 0x0000002D; // use it for RTC Interrupt
VICIntEnable = 0x00002000; // Enable RTC Interrupt
void set_time(void)
YEAR = 2006; // Year
MONTH = 5; // Month
DOM = 23; // Day of month
DOY = 38; // Day of year
DOW = 143; // Day of week
HOUR = 23; // Hours
MIN = 14; // Minutes
SEC = 30; // Seconds
int main(void)
uint32_t startTime;
sysInit(); //system init
#if defined(UART0_TX_INT_MODE) || defined(UART0_RX_INT_MODE)
uart0Puts("nrRTC interupts every secondrn");
//This function returns the current system time in TICs
startTime = getSysTICs();
init_rtc();//init RTC
set_time();//Set initial time
for (;;) {
} // for
return 0;

Download WinARM Project Files.

Leave a Reply