Path: Home => AVR overview => Applications => DCF77 receivers => Sync clock m48   Diese Seite in Deutsch: Flag DE
DCF77 receiver logo Applications of
AVR single chip controllers AT90S, ATtiny, ATmega and ATxmega
LCD clock with DCF77 sync serial receiver on an ATmega48
This project is experimental. I don't know if it really works as planned here.

10 DCF77 AM receivers

10.5 Crystal clock with sync serial receiver and LC display with ATmega48

If so desired and programmed, the DCF77 direct receivers with the tn25 controller issue on pins 3 and 7 of the controller a synchronous serial signal. This project uses this signal to synchronize a clock with an LCD to that. Display of the clock, time, date, receiver errors and status messages are displayed on an LCD of configurable size (from 1-by-8 over 2-by-8 over 1-by-16 over 2-by-16 to 4-by-20).

As the ATmega48 controller is clocked by a crystal the device can function as clock without DCF77 synchronization, as well. The time and date can be adjusted by two keys and a potentiometer. An alarm function works as well and uses a speaker to play programmable melodies. The backlight of the LCD can be regulated with an opto sensor.

0 Index

  1. Hardware
  2. Mounting
  3. Software

10.5.1 The hardware

Synchronous DCF77-LCD display with ATmega48 This stand-alone watch with a ATmega48 ticks with crystal. With two keys (Forward, PB0, and Backward, PB3) and by a potentiometer of 100 kΩ on the ADC0 input the clock can be adjusted manually. Additionally a serial synchronous interface receives signals (via the data and clock input) from the controller tn25 and synchronizes time and date with this controller.

The serial signals are collected from the PC4 pin, where they are clocked in on positive edges on the PCINT13 clock pin. Received bytes are stored in the SRAM. If a line feed character is received, it is checked whether a time/date string (starting with "T"), a DCF77 reception report (starting with "E") or a controller status message (starting with "S") has been received. If the LCD is large enough this all is displayed.

The LCD is connected to the ATmega84's port D, the pins PC3 (E), PC2 (R/W) and PB5 (RS) serve the LCD's control lines. Any desired LCD can be attached, just change the number of lines and columns of the LCD in the source code.

The backlight of the LCD is regulated by a PWM signal from the OC1A pin (PB1). The controller measures the background intensity via the foto transaistor collector voltage on ADC1. Please note that the frequency of the backlight PWM is varying if a melody is played. If not it is at 110 Hz.

Clocking of the ATmega48 is done with a 2.4576-MHz crystal. Accuracy of the clock therefore is high enough.

Calculations for this project are available as Libre-Office-Calc file

Top Index Hardware Mounting Software

10.5.2 Mounting

Mounting of the hardware This shows how I mounted the clock's hardware on a small PCB (dotted area). The 4-by-20 LCD is larger than the PCB, the 16-pin plug connects these two components. Red are resistors, blue are capacitors and green is the coil for the analog operating voltage.

In order to be able to disconnect external components such as keys, the opto transistor, etc., I designed a male/female 20-pin connector. The unequal 10 pins are all GND, the equal 10s connect the components.

The male ISP6 connector can be used to program the ATtiny48.

PCB from above PCB from below This is the soldered PCB, as seen from above and below. Wiring is a bit fuzzy, but works wonderful.

The plugs The LCD at work On the left picture the angled plugs can be see, on the extreme left the 16-pin LCD plug can be seen where the PCB can be plugged to the LCD.

On the right sie the clock is at work.

Top Index Hardware Mounting Software

10.5.3 Software

The software for this project is written in assembler, of course, and fits well into the flash memory of ATmega48. Download

The software is available in asm format here. It uses .if directives to a large extend, so use a more modern assembler such as gavrasm (my own one) or the Studio's assembler2.

On top of the software several debug switches are defined. Those have to be set to zero to yield the correct software.

Also, check all constants in the section Adjustable constants if they fit to your hardware.

To assemble, this software uses the routines to comunicate with the LCD. This include file has to be in the same path during assembling.

If you want to use debug switches (by turning switches to one), you'll need the include source code as well.

Fuses of the ATmega48 When writing the hex file to the flash memory, do not forget to change the fuses (if your device already has a crystal attached). The CLKDIV8 fuse has to be cleared and the crystal oscillator option has to be enabled. Otherwise the clock runs too slow.

Top Index Hardware Mounting Software Funktioning of the software The clock's second pulse
As DCF77 delivers the complete time and date information once per minute, the 59 seconds in between have to be generated by a seconds pulse. This is also necessary for operating the clock without DCF77 signal.

The clock signal of the ATmega48 stems from a 2.4576 MHz crystal. TC0 divides this with its prescaler by 1,024, so the TC0 counter is clocked with 2,400 Hz. As this, divided by 256 by the counter, does not deliver an integer but a fraction, the timer TC0 is dividing by 24 in CTC mode. Its compare A register port is therefore written to 23. Within the compare A match interrupt a further division by 100 in the register rSecDiv brings down the one-second-pulse. The TC0 interrupt also decreases the toggle counter rKeyTgl if this is larger than zero.

The Oc0AIsr then sets the flag bit bSec, because the treatment of the second pulse is lengthy and therefore performed outside the Interrupt-Service-Routine.

When the controller wakes up, he checks whether bSec is set. If yes, the routine Secnd is executed. This routine takes over the complete time and date update, so works stand-alone.

Secnd first reads the ones of the seconds from SRAM. This is done with the indirect access to Y+dSecO: Y is pointing to sTime: in the SRAM, dSecO is set to 7 (see the SRAM section of the source code). Therefore ldd rmp,Y+dSecO reads the ASCII-coded number located at sTime+7.

The ones are increased and it is checked whether it reached the character after '9'. If not: the increased ones are written to SRAM and the seconds are written to and displayed on the LCD. If '9'+1 has been reached, the ones are restarted with '0' and the tens are read and increased. If those are smaller than '6', the increased tens are written to SRAM and the seconds are written to and displayed on the LCD.

The same is done with the minutes and the hours of the time in SRAM. If the minutes are increased, the minutes are written to SRAM and the minutes and the seconds are written to the LCD. If the minutes exceed 59 and if the hours exceed 23, the next higher level is increased and the LCD display is updated from this level down to the seconds. This ensures that only the really necessary write operations to the LCD are performed.

When the hours exceed 23, the next day starts. First, the weekday is increased. That means, that the routine NextDay: is jumped to. This does the following:
  1. The routine GetWeekday: is called. This uses the two weekday characters in Y+dWd1 and Y+dWd2 and seeks those in the table Weekdays2:. If found, the register rmp returns its position (0 to 6), if not found it returns 7. When returning, the register pair Z points already to the next weekday (on Sundays to the start of the table, Mo).
  2. The two characters that Z points to are written to the weekdays in SRAM. The new weekday is the displayed, which uses the following algorithm:
    1. The LCD cursor is placed to the weekday position of the LCD.
    2. The two characters are read by the routine GetWeekday: and register rmp has the weekday in binary form (0..7).
    3. If the display has 16 columns, the seven-character weekday table in Weekdays7: is used, if it has 10 characters the table Weekdays10: is used.
    4. rmp is then multiplied by either 7 or 10 and added to the table address in Z. Z now points to the correct weekday string.
    5. Either seven or ten characters are read from the table that Z is pointing to and written to the LCD.
Then the day ones are increased. Again, overflows of the '9' are treated by increasing the tens. But then a calculation of the days in the current month is made in CalcDayPerMonth. This reads the current month (and in case of the February the current year) and returns a binary number between 28 and 31, the numbers of days in that month. The NextDay subroutine uses this to determine whether the month is over or not.

If the month is over, the month is increased. If that reaches 13 the monthes are restarted with "01" and the years are increased.

Note that the current changed category (days, monthes, years) and all subsequent categories are all updated on LCD, so, beginning with the year, all update routines below (and down to the seconds) are following. All those routines start with Display... in the source code. Make sure that the row of these routines remains correct. Key input and manual adjustment
The two keys are attached to the PB0 and PB3 input pins. Any level change on these two pins trigger the PCI0 interrupt and start the respective ISR.

The following stages of an input are ran through:
  1. If the register rKeyTgl is not zero, no reaction results. one
  2. If both the flags bKeyAct and bKeyTgl are zero and the key on PB0 is closed, the three flags bKeyAct, and bKeyTrg are set to initiate input mode.
  3. low, the flag bKeyTrg Conversion of adjusted dates to weekdays

Weekday calculation from date If you adjust the date with the keys and the potentiometer to a certain day, we would have to adjust the weekday, too. To relieve the user from this task, software is on board that converts any date to its correct weekday. As you will see: that isn't too complicated for a small microcontroller.

The flow diagram on the right shows how this is done. The flow diagram is available as LibreOffice-Draw file here.

The starting point for the calculation is the day 12/31/1999, which was a Thursday, so starts with four (Monday=0 to Sunday=6). As both the British (fEn=1) as well as the German (fEn=0) notation shall be usable, both tables differ a little bit. fEn affects the weekday's abbreviations as well as the position in the date string.

First the days of the date are added to the base point. The day-ones and day-tens are read from SRAM, are converted from ASCII to binary and then 10s are added to the ones as long as necessary to yield the complete binary of days. This number is added to the base in the subroutine AddWd. As long as the result is larger than 6 seven are subtracted. As this routine is called from several locations it is formulated as a subroutine.

In the same manner the month is read and converted. The shifting of the weekdays by the monthes are layed down in the table MoTab. In January zero is added, in February three, etc. After adding this displacement, it is checked whether the month is larger than two and if one extra day has to added in a leap year.

Then the years are treated. As the years are needed more often, this is done in the routine ReadYr. In a first step these years are added because each normal (non-leap) year adds one to the weekdays. Then the years are divided by four to get the number of leap years. If the year is not zero, a one is added for the year 2000. This number is also added.

The weekday is now as binary in register rmp. By multiplying this by two and adding this to the base of the table Weekday2 the two characters of the weekday can be read from flash memory and written to SRAM at the weekday location.

Top Index Hardware Mounting Software

©2021 by