A simple AVR RTC using built-in Timers
In my current project I am implementing a simple data logger. When the hardware was designed we did not implement a nice RTC module, such as the chip used in Sparkfun’s clock module here:
http://www.sparkfun.com/commerce/product_info.php?products_id=99. In lieu of such a nice solution I have opted to implement a basic, semi-accurate clock using an 8-bit timer in the AVR. Here’s the steps:
- Calculate from the clockspeed the interval and width that timer needs to fire at to record a 1Hz measurement
- Enable timer interrupts
- Capture the timer interrupt and increment a 4-byte integer
In my case the microcontroller is running off of a 8Mhz crystal. Setting the timer prescaler to clk/256 produces 31,250 clock pulses. Setting OCRA to 250 and counting up to 124 before incrementing the second produces 31,250/250/124 = 1 pulse per second.
For this project I have decided to store the time as the number of seconds elapsed since January 1st, 2001. This is convenient because the host system can handle all the nasty stuff such as leap-years and other oddities in the calendar while the microcontroller just stores a number.
And without further ado I shall present some code!
AVR timer.c
volatile char counter = 0;
volatile long seconds = 0;
ISR(TIMER0_COMPA_vect)
{
counter++;
if (counter==124)
{
seconds+=1;
counter=0;
}
}
void timer_init()
{
TIMSK0 = 0b00000010; // Enaled Timer CompA interupt
TCCR0B = 0b00000100; // Set speed to clk/256
TCCR0A = 0b00000010; // Set timer to CTC mode
OCR0A = 250; // Set timer period
}
In addition to this AVR code some host-side code is needed to set and
read the time from the AVR accurately. For this I have used VB.Net.
Generating appropriate times
Public Sub TestRoutines()
' Setting the time
Dim StartTime As DateTime = New DateTime(2000, 1, 1, 1, 0, 0)
Dim SecTimeSpan As TimeSpan
SecTimeSpan = Now() - StartTime
Dim _bytes() As Byte = BitConverter.GetBytes(CType(SecTimeSpan.TotalSeconds, UInt32))
' Converting received time into Date obj
Dim deviceDate as New Date(2000, 1, 1, 1, 0, 0).AddSeconds(BitConverter.ToUInt32(_bytes, 0))
End Sub
Testing has shown this clock to drag a millisecond or two for every
minute of operation. Not the greatest performance but for a data
logger it is adequate.
I think this is among the most significant information for me. And i’m glad reading your article. But want to remark on some general things, The website style is wonderful, the articles is really great : D. Good job, cheers
frostwire
5 Feb 11 at 7:34 am