Oct-23rd-2009

Interfacing DS1307 RTC Chip with AVR Microcontroller

Real Time Clocks, as the name suggests are clock modules. They are available as integrated circuits (ICs) and manages timing like a clock. Some RTC ICs also manages date like a calendar. The main advantage is that they have a system of battery backup which keeps the clock/ca lender running even in case of power failure. A very small current is required for keeping the RTC alive. This in most case is provided by a miniature 3v lithium coin cell. So even if the embedded system with RTC is powered off the RTC module is up and running by the backup cell. This same technique is used in PC timing also. If you have opened your computer case you will notice a small coin cell in the mother board.

In this tutorial we will learn to use a very famous RTC IC named DS1307. The DS1307 is described in the datasheet as follows

The DS1307 is a low-power clock/calendar with 56 bytes of battery-backed SRAM. The clock/calendar provides seconds, minutes, hours, day, date, month, and year information. The date at the end of the month is automatically adjusted for months with fewer than 31 days, including corrections for leap year. The DS1307 operates as a slave device on the I2C bus.

So the aim of the project will be to access the DS1307 registers, read time

  • Access the DS1307 registers i.e. read/write data to/from the DS1307 IC
  • Format the read data and display in LCD
  • Ability to get time from user and store it to DS1307. This provide means to setup the RTC module with correct time.

DS1307 Internal Registers

From software point of view the DS1307 is just a collection of some 8 bit registers. You can read these register to obtain the current time and date. You can also modify them to hold the correct time. After that the DS1307 keeps then updated with current date and time. The following registers are there.

ADDRESS BIT7 BIT6 BIT5 BIT4 BIT3 BIT2 BIT1 BIT0 FUNCTION RANGE
00H CH
10 SECONDS
SECOND
SECOND
00-59
01H
0
10 MINUTES
MINUTES
MINUTES
00-59
02H
0
12
10HR
10HR
HOUR
HOUR

1-12+AM/PM OR
00-23

24
am/pm
03H
0
0
0
0
0
DAY
DAY
01-07
04H
0
0
10 DATE
DATE
DATE
01-31
05H
0
0
0
10MONTH
MONTH
MONTH
01-12
06H
10 YEAR
YEAR
YEAR
00-99
07H

TO KEEP THINGS SIMPLE I HAVE SKIPPED THE CONTROL REGISTER

THIS IS USED FOR SQUARE WAVE GENERATION ON PIN7

08-3FH                 56 BYTE RAM 00h-FFh

The register uses BCD (Binary Coded Decimal) for storing the values. For example take register at address 01h, it stores the MINUTES. Say it is 37 minutes. Then it will be stored as follows.

DS1307 Register format is BCD

Fig. : BCD Format in DS1307 Registers.

The DS1307.c and DS1307.h provide easy access to the registers. I have provided just two functions that allows you to read and write the DS1307 registers.

/***************************************************

Function To Read Internal Registers of DS1307
---------------------------------------------

address : Address of the register
data: value of register is copied to this.


Returns:
0= Failure
1= Success
***************************************************/

uint8_t DS1307Read(uint8_t address,uint8_t *data)


/*************************************************** Function To Write Internal Registers of DS1307 --------------------------------------------- address : Address of the register data: value to write. Returns: 0= Failure 1= Success ***************************************************/ uint8_t DS1307Write(uint8_t address,uint8_t data)

These functions depends on the I2C library. The I2C (Inter IC Communication) is a popular communication protocol between ICs. The DS1307 and our AVR ATmega8 communicates using the I2C bus. I will give more details on I2C in a separate tutorial.

A Simple RTC Module

The DS1307 require an 32.768KHz crystal, a 3v lithium battery and 2 pull up registers to function. So I will make a small PCB that will hold all these. The image of module is shown below. The module can be connected to development boards using female-female burg wires.

DS1307 RCT Module with lithium cell

Fig. : A Simple DS1307 RTC Module.

 

DS1307 RTC Module Schematic for interface with PIC/AVR MCUs

Fig. :DS1307 RTC Module Circuit Diagram.

Once you have the RTC Module ready you can connect it with your favorite MCU like PIC or AVR or any other MCU. In this tutorial I will connect it with AVR ATmega8 MCU, I will also interface it with PIC MCUs latter on.

AVR ATmega8, DS1307 RTC Interface Example with LCD Module

To make a complete usable example we will connect a 16x2 LCD Module, and 3 push buttons. The detailed circuit diagram is given below.

AVR ATmega8 interface with DS1307 RTC

Fig. :AVR ATmega8 RTC Interface Circuit Diagram.

avr-gcc software

The full software for the example is written in C language and compiled with avr-gcc. The whole software is very modular. Following software modules are used.

  • LCD Interface modules for handling the display device. More detail is given on these pages.
  • Low Level I2C Interface Library. This handles the data communication using the hardware I2C module present inside AVR/PIC MCUs.
    • For Atmel AVR MCUs (Yet to be written)
    • For PIC16 MCUs.(Yet to be written)
    • For PIC18 MCUs.(Yet to be written)
  • DS1307 Module : This module built on top of above I2C module help in reading/writing data to and from the DS1307 chip. Functions are very simple and documented inside the .c and .h files itself.
  • The main application module RTC.c is the application software that uses the above modules to communicate with both the LCD and DS1307 chip. It also manages the handling of UI (User Interface) by the help of 3 push buttons.

Fabrication Instructions

Assemble the circuits according to the circuit diagrams shown above. Burn the hex file (download link given at the end of article) to an ATmega8 using a suitable programmer. Set the fuse byte as follows LOW=21 HEX HIGH=D9 HEX . Apply power to the circuit and adjust the LCD Contrast Pot until the display is clear. The initial time should be shown as 00:00:00. Now press the "menu" key to enter the main menu. Use the LEFT and RIGHT Key to move between options and ENTER to select an item. The main menu has the following options.

  • Set Time
  • Set On Time (NOT IMPLEMENTED YET)
  • Set Off Time (NOT IMPLEMENTED YET)
  • Quit
avr rtc main menu

Fig. : The Main Menu.

Go to the "Set Time" option, the following UI will be displayed.

Fig. : Setting the time.

Use the "Move Sel" key to move between Hour,Minute,Second,AM/PM, and <OK>. Use the "Increase"/"Decrease" buttons to adjust value. Finally go to <OK> and press any key. A message will be shown, "Main Time Set". The main menu will return. Select "Quit" from the main menu and the main screen showing the current time will be displayed. Now the RTC is setup, it will keep the time even if you switch off the circuit. Next the you power up the circuit it will still show the REAL time!

DS1307 rtc example main screen

Fig. : DS1307 RTC Example Main Screen.

Downloads

A Request From Readers

If you find this article useful or have any doubts or want to share your valuable suggestions, please leave a comment or two ! I would be glad to hear from you.

-The Author

Avinash Gupta

Videos

The ATmega8 DS1307 RTC Interface example in action.


28 Responses to “Interfacing DS1307 RTC Chip with AVR Microcontroller”

  1. 1
    Kenneth Finnegan Says:

    I just finished my first project using the DS1307, and I appreciate your idea of building the complete module on perf board. I think I might go back and do that… :-)

    There is a way around needing the pull-up resistors on the clock module (at least with an ATMEGA168): Set the SCL and SDA lines high, which enables pull-up resistors inside the controller. I only know how to do this in the Arduino environment, but I do know that it’s possible.

    I also used the SRAM, which was super convenient for when I wanted to be able to reset the atmega, but be able to pick up from where I left off.

    http://kennethfinnegan.blogspot.com/2009/10/arduino-temperature-logger.html

  2. 2
    foxit Says:

    I can not simulate this circuit in Proteus. It does not work.
    I don`t understand why. Please? help.

  3. 3
    AVR Micro Says:

    This is an excellent article! Detailed description suitable also for beginners. I will not build this project but I enjoyed a lot reading it.

  4. 4
    Anthony Says:

    Hi Avinash
    This is my favourite Chip (DS1307)
    I know it pretty Good

    I give a Lib for my friend
    for BCD->BIN
    *sec = ((*sec & 0xF0) >> 4)*10 + (*sec & 0×0F);
    *mnt = ((*mnt & 0xF0) >> 4)*10 + (*mnt & 0×0F);
    *hr = ((*hr & 0xF0) >> 4)*10 + (*hr & 0×0F);
    *day = ((*day & 0xF0) >> 4)*10 + (*day & 0×0F);
    *year = ((*year & 0xF0) >> 4)*10 + (*year & 0×0F);
    *date = ((*date & 0xF0) >> 4)*10 + (*date & 0×0F);
    *mn = ((*mn & 0xF0) >> 4)*10 + (*mn & 0×0F);

    for BIN->BCD
    _I2C_write(((sec/10)<<4) + (sec%10));
    _I2C_write(((min/10)<<4) + (min%10));
    _I2C_write(((hour/10)<<4) + (hour%10));

    ///////////////////////////////////////////////////////////

    ////Read Ram
    unsigned char rtc_read(unsigned char address_)
    {
    unsigned char data_;
    _i2c_start();
    _i2c_write(0xd0);
    _i2c_write(address_);
    _i2c_start();
    _i2c_write(0xd1);
    data=_i2c_read(0);
    _i2c_stop();
    return data_;
    }

    ///
    void rtc_write(unsigned char address,unsigned char data)
    {
    _i2c_start();
    _i2c_write(0xd0);
    _i2c_write(address);
    _i2c_write(data);
    _i2c_stop();
    }

    void rtc_init(unsigned char rs,unsigned char sqwe,unsigned char out)
    {
    rs&=3;
    if (sqwe) rs|=0×10;
    if (out) rs|=0×80;
    _i2c_start();
    _i2c_write(0xd0);
    _i2c_write(7);
    _i2c_write(rs);
    _i2c_stop();
    }

    void rtc_get_time(unsigned char *hour,unsigned char *min,unsigned char *sec)
    {
    _i2c_start();
    _i2c_write(0xd0);
    _i2c_write(0);
    _i2c_start();
    _i2c_write(0xd1);
    *sec=bcd2bin(_i2c_read(1));
    *min=bcd2bin(_i2c_read(1));
    *hour=bcd2bin(_i2c_read(0));
    _i2c_stop();
    }

    void rtc_set_time(unsigned char hour,unsigned char min,unsigned char sec)
    {
    _i2c_start();
    _i2c_write(0xd0);
    _i2c_write(0);
    _i2c_write(bin2bcd(sec));
    _i2c_write(bin2bcd(min));
    _i2c_write(bin2bcd(hour));
    _i2c_stop();
    }

    void rtc_get_date(unsigned char *date,unsigned char *month,unsigned char *year)
    {
    _i2c_start();
    _i2c_write(0xd0);
    _i2c_write(4);
    _i2c_start();
    _i2c_write(0xd1);
    *date=bcd2bin(_i2c_read(1));
    *month=bcd2bin(_i2c_read(1));
    *year=bcd2bin(_i2c_read(0));
    _i2c_stop();
    }

    void rtc_set_date(unsigned char date,unsigned char month,unsigned char year)
    {
    _i2c_start();
    _i2c_write(0xd0);
    _i2c_write(4);
    _i2c_write(bin2bcd(date));
    _i2c_write(bin2bcd(month));
    _i2c_write(bin2bcd(year));
    _i2c_stop();
    }

  5. 5
    myway Says:

    anyone using SW I2C on other pins like scl and sda, i need simple function for i2c_write, i2c_start, i2c_read??
    thanks for help

  6. 6
    Praful Says:

    Dear Sir,
    I made a clock as per your design and used a hex file given by you but it just shows a cursor blinking on lcd and nothing else .
    I like this project and i want to do this but ………..
    Please help to solve this ……………
    Thanking You……………
    Praful
    09881303008

  7. 7
    Avinash Says:

    @Praful

    When I published this project (or any other) I took GREAT CARE and try to give as much information as possible to SUCCESSFULLY make the project. I feel really pity at you that u could not make it :( May be some people are really too low on patience to ask at once that the thing is not working. The project is already a kind of like SPOON FEEDING a baby. I can’t do more than this.

    • Check the fuse bits
    • Check pull up resistor on SDA and SCL pins

  8. 8
    gaurav roy Says:

    dude.please complete the rf communication between microcontrollers.still waiting for that………….

  9. 9
    Mathivanan Says:

    Great!!! Thanks…. Fully Explained ….Very nice Comments…

  10. 10
    kashif ali Says:

    quiet brief stuff, nicely explained..!!

  11. 11
    kunal Says:

    hi avinash, can you help me in interfacing atmega8 with PT2258. basicaly it’s a hometheatre project.
    thanks in advance.

  12. 12
    Ravi Kiran Says:

    Hi Avinash,

    I feel that there is a bug in the circuit that you have given.
    In the first image(in DS1307 Circuit), it is given that the SCL pin to be connected to the SDA pin of the MCU and SDA to SCL of the MCU. But the SCL pin of an I2C device should be connected to the SCL pin of any other I2C Device. I think this is a bug and please verify the same…
    Awaiting reply…..

    Thank You

  13. 13
    nazat shaikh Says:

    hi,
    I made a project only to read DS1307 after every 1sec and for that i took your code as a reference. I checked the hardware & everything is OK, but the RTC update the time only once.Please reply…..
    thank you

  14. 14
    alex Says:

    I made this circuit and code in proteus for simulate it, but I can not do it. I shall apreciate if someone can send me a file in proteus. and other question is why there are many code windows when I opened in avrStudio 4?, it can simulate or I need to add every code windows? please help me, sorry I’m novice, but I’ll try to do it. thanks a lot

  15. 15
    Manas Paul Says:

    Dear Avinash Sir,
    This program is too good.This is my first AVR success program and LCD display program.Sir how I develop the 128×64 LCD display.Give the circuit diagram with program.I am also a customer of AVR kit.Thanks again.

  16. 16
    parag Says:

    hello sir,
    i am working on a project using PIC 16F877. can u help me for writing code for interfacing DS1307 with PIC using instructions only and not in c-language.
    please reply…
    thank u.

  17. 17
    Tifany Wiebusch Says:

    I go along with you actually, I believe! Might this become doable for you to have your blog translated directly into Russian? English is actually my own 2nd language.

  18. 18
    kunal Says:

    i’ve completed programmable timer using above program by avinash. It can be useful for someone.

    #include
    #include
    #include
    #include “I2C.h”
    #include “lcd.h”
    #include “ds1307.h”

    void ShowMainMenu();
    void SetTime();
    void SetOnTime();
    void SetOffTime();
    void Alarm_on_off();
    void check_alrm();
    #define load = PB3

    uint8_t hr_,hr_set,min_,min_set,sec_,AMPM,AMPM_set,hr_clr,min_clr,AMPM_clr,alarm=0,temp1;
    char Mem[7];
    void Wait()
    {
    uint8_t i;
    for(i=0;i<20;i++)
    _delay_loop_2(0);
    }

    uint8_t PREV_PINB=0xFF;
    /*

    Function to test the current status of keys(0 to 2)

    returns
    0 if NOT pressed
    1 if Pressed

    */
    uint8_t GetKeyStatus(uint8_t key)
    {
    return (!(PINB & (1<<key)));
    }

    /*

    Function to test the previous status of keys(0 to 2)

    returns
    0 if NOT pressed
    1 if Pressed

    */
    uint8_t GetPrevKeyStatus(uint8_t key)
    {
    return (!(PREV_PINB & (1<<key)));
    }
    //——————————————————————-

    int main(void)
    {

    //Wait Util Other device startup
    _delay_loop_2(0);
    _delay_loop_2(0);

    //Initialize the LCD Module
    LCDInit(LS_ULINE);

    //Initialize I2C Bus
    I2CInit();

    //Enable Pull ups on keys
    DDRB = 0b00001000; // PB3 Load OutPut.
    PORTB|=((1<<PB2)|(1<<PB1)|(1<<PB0));

    //Clear CH bit of RTC
    #define CH 7

    uint8_t temp;
    DS1307Read(0×00,&temp);

    //Clear CH Bit
    temp&=(~(1<>4)*10)+(temp1 & 0b00001111); //BDC to HEX
    Time[8]=”;
    Time[7]=48+(temp1 & 0b00001111);
    Time[6]=48+((temp1 & 0b01110000)>>4);
    Time[5]=’:';

    DS1307Read(0×01,&temp1);
    min_=(((temp1 & 0b01110000)>>4)*10)+(temp1 & 0b00001111); //BDC to HEX
    Time[4]=48+(temp1 & 0b00001111);
    Time[3]=48+((temp1 & 0b01110000)>>4);
    Time[2]=’:';

    DS1307Read(0×02,&temp1);
    hr_=(((temp1 & 0b00010000)>>4)*10)+(temp1 & 0b00001111); //BDC to HEX
    Time[1]=48+(temp1 & 0b00001111);
    Time[0]=48+((temp1 & 0b00010000)>>4);

    //———————————-
    if(temp1 & 0b00100000)
    {
    AMPM = 0×01;
    } //PM

    else
    {
    AMPM = 0;
    } //AM
    //———————————-
    if(alarm == 0×01)
    {

    if(AMPM == AMPM_set)
    {
    if((hr_ & 0b00011111) == hr_set)
    {
    if(min_ == min_set)
    {
    PORTB |= (1<<PB3);
    LCDClear();
    LCDWriteString("**** Load ON ***");
    _delay_ms(500);

    }
    }
    }

    if(AMPM == AMPM_clr)
    {
    if((hr_ & 0b00011111) == hr_clr)
    {
    if(min_ == min_clr)
    {
    PORTB &= ~(1<<PB3);
    LCDClear();
    LCDWriteString("*** Load OFF ***");
    _delay_ms(500);
    alarm =0 ;
    }
    }
    }

    LCDClear();
    LCDWriteString("UNI-TIMER [ALRM]");
    LCDWriteStringXY(2,1,Time);

    }
    //////////////////—————————————————————————————-

    else {
    LCDClear();

    LCDWriteString(" UNI-TIMER ");

    LCDWriteStringXY(2,1,Time);
    }

    //AM/PM
    if(AMPM)
    {
    LCDWriteStringXY(11,1,"PM");
    }
    else
    {
    LCDWriteStringXY(11,1,"AM");
    }

    //Wait Some time and keep testing key input
    uint8_t i;
    for(i=0;i<20;i++)
    {

    if(GetKeyStatus(2))
    {
    //Go To Main Menu
    ShowMainMenu();

    _delay_loop_2(0);
    _delay_loop_2(0);
    _delay_loop_2(0);

    }
    _delay_loop_2(5000);
    }
    }

    }

    void ShowMainMenu()
    {
    //The Main Menu
    char *menu_items[]={ "Set Time",
    "Set On Time",
    "Set Off Time",
    "Alarm ON/OFF",
    "Quit"
    };
    uint8_t menu_count=5;
    uint8_t selected=0;

    _delay_loop_2(0);
    _delay_loop_2(0);

    while(1)
    {
    LCDClear();
    LCDWriteString(" Main Menu ");

    LCDWriteStringXY(2,1,menu_items[selected]);

    LCDWriteStringXY(0,1,"”);

    if(GetKeyStatus(1))
    {
    //Left Key(No 1) is pressed
    //Check that it was not pressed previously
    if(!GetPrevKeyStatus(1))
    {
    if(selected !=0)
    selected–;
    }
    }

    if(GetKeyStatus(0))
    {
    //Right Key(No 0) is pressed
    //Check that it was not pressed previously
    if(!GetPrevKeyStatus(0))
    {
    if(selected !=(menu_count-1))
    selected++;
    }
    }

    if(GetKeyStatus(2))
    {
    //Enter Key Pressed
    //Check that it was not pressed previously
    if(!GetPrevKeyStatus(2))
    {
    //Call Appropriate Function
    switch (selected)
    {
    case 0:
    SetTime();
    break;
    case 1:
    SetOnTime();
    break;

    case 2:
    SetOffTime();
    break;

    case 3:
    Alarm_on_off();
    break;

    case 4:
    return;//Quit
    }

    }
    }

    PREV_PINB=PINB;

    _delay_loop_2(5000);
    }
    }

    void SetTime()
    {

    uint8_t hr,min,sec,am_pm,temp;

    //Read the Second Register
    DS1307Read(0×00,&temp);
    sec=(((temp & 0b01110000)>>4)*10)+(temp & 0b00001111);

    //Read the Minute Register
    DS1307Read(0×01,&temp);
    min=(((temp & 0b01110000)>>4)*10)+(temp & 0b00001111);

    //Read the Hour Register
    DS1307Read(0×02,&temp);
    hr=(((temp & 0b00010000)>>4)*10)+(temp & 0b00001111);

    am_pm=(temp & 0b00100000)>>4;

    //If Hour Register is 0 make it 12, as 00:00:00 invalid time
    if(hr==0) hr=12;

    uint8_t sel=0;

    while(1)
    {
    LCDClear();

    LCDWriteString(“00:00:00 DONE”);

    LCDWriteIntXY(0,0,hr,2);
    LCDWriteIntXY(3,0,min,2);
    LCDWriteIntXY(6,0,sec,2);

    if(am_pm)
    {
    LCDWriteStringXY(9,0,”PM”);
    }
    else
    {
    LCDWriteStringXY(9,0,”AM”);
    }

    //Draw Pointer
    LCDWriteStringXY(sel*3,1,”^^”);

    //Input Up key
    if(GetKeyStatus(1))
    {
    if(!GetPrevKeyStatus(1))
    {
    if(sel==0)
    {
    //Hour
    if(hr==12)
    {
    hr=1;
    }
    else
    {
    hr++;
    }
    }

    if(sel==1)
    {
    //Min
    if(min==59)
    {
    min=0;
    }
    else
    {
    min++;
    }
    }

    if(sel==2)
    {
    //Sec
    if(sec==59)
    {
    sec=0;
    }
    else
    {
    sec++;
    }
    }

    if(sel==3)
    {
    //AM-PM
    if(am_pm==0)
    {
    am_pm=1;
    }
    else
    {
    am_pm=0;
    }
    }
    if(sel == 4)
    {
    //OK
    break;
    }
    }
    }

    //Input Down
    if(GetKeyStatus(0))
    {
    if(!GetPrevKeyStatus(0))
    {
    if(sel==0)
    {
    //Hour
    if(hr==1)
    {
    hr=12;
    }
    else
    {
    hr–;
    }
    }

    if(sel==1)
    {
    //Min
    if(min==0)
    {
    min=59;
    }
    else
    {
    min–;
    }
    }

    if(sel==2)
    {
    //Sec
    if(sec==0)
    {
    sec=59;
    }
    else
    {
    sec–;
    }
    }

    if(sel==3)
    {
    //AM-PM
    if(am_pm==0)
    {
    am_pm=1;
    }
    else
    {
    am_pm=0;
    }
    }
    if(sel == 4)
    {
    //OK
    break;
    }
    }
    }

    if(GetKeyStatus(2))
    {
    if(!GetPrevKeyStatus(2))
    {
    //Change Selection
    if(sel==4)
    sel=0;
    else
    sel++;
    }
    }

    PREV_PINB=PINB;

    _delay_loop_2(30000);

    }

    //Now write time back to RTC Module
    temp=((sec/10)<<4)|(sec%10);
    DS1307Write(0×00,temp);

    temp=((min/10)<<4)|(min%10);
    DS1307Write(0×01,temp);

    temp=((hr/10)<<4)|(hr%10);
    temp|=0b01000000; //12 Hr Mode
    if(am_pm)
    {
    temp|=0b00100000;
    }
    DS1307Write(0×02,temp);

    LCDClear();
    LCDWriteString("Message !");
    LCDWriteStringXY(0,1,"Main Time Set");

    uint8_t i;
    for(i=0;i<10;i++)
    _delay_loop_2(0);

    }
    //————————————–ON TIME————————————————————
    void SetOnTime()
    {
    uint8_t sel=0;
    // read time from EEPROM
    while(1)
    {
    LCDClear();

    LCDWriteString("00:00 DONE");

    LCDWriteIntXY(0,0,hr_set,2);
    LCDWriteIntXY(3,0,min_set,2);

    if(AMPM_set)
    {
    LCDWriteStringXY(6,0,"PM");
    }
    else
    {
    LCDWriteStringXY(6,0,"AM");
    }

    //Draw Pointer
    LCDWriteStringXY(sel*3,1,"^^");

    //Input Up key
    if(GetKeyStatus(1))
    {
    if(!GetPrevKeyStatus(1))
    {
    if(sel==0)
    {
    //Hour
    if(hr_set==12)
    {
    hr_set=1;
    }
    else
    {
    hr_set++;
    }
    }

    if(sel==1)
    {
    //Min
    if(min_set==59)
    {
    min_set=0;
    }
    else
    {
    min_set++;
    }
    }

    if(sel==2)
    {
    //AM-PM
    if(AMPM_set==0)
    {
    AMPM_set=0×01;
    }
    else
    {
    AMPM_set=0;
    }
    }
    if(sel == 3)
    {
    //OK
    break;
    }
    }
    }

    //Input Down
    if(GetKeyStatus(0))
    {
    if(!GetPrevKeyStatus(0))
    {
    if(sel==0)
    {
    //Hour
    if(hr_set==1)
    {
    hr_set=12;
    }
    else
    {
    hr_set–;
    }
    }

    if(sel==1)
    {
    //Min
    if(min_set==0)
    {
    min_set=59;
    }
    else
    {
    min_set–;
    }
    }

    if(sel==2)
    {
    //AM-PM
    if(AMPM_set==0)
    {
    AMPM_set=0×01;
    }
    else
    {
    AMPM_set=0;
    }
    }
    if(sel == 3)
    {
    //OK
    break;
    }
    }
    }

    if(GetKeyStatus(2))
    {
    if(!GetPrevKeyStatus(2))
    {
    //Change Selection
    if(sel==3)
    sel=0;
    else
    sel++;
    }
    }

    PREV_PINB=PINB;

    _delay_loop_2(30000);

    }
    //——————-EEPROM——————————-
    Mem[0] = hr_set;
    Mem[1] = min_set;
    Mem[2] = AMPM_set;
    eeprom_write_block ((const void*)&Mem, (void *)1, 7);
    //——————————————————–
    LCDClear();
    LCDWriteString(" Message !");
    LCDWriteStringXY(0,1,"ON Time Set");

    uint8_t i;
    for(i=0;i<10;i++)
    _delay_loop_2(0);

    }
    //————————————— OFF TIME———————————————
    void SetOffTime()
    {
    uint8_t sel=0;
    // read from EEPROM
    while(1)
    {
    LCDClear();

    LCDWriteString("00:00 DONE");

    LCDWriteIntXY(0,0,hr_clr,2);
    LCDWriteIntXY(3,0,min_clr,2);

    if(AMPM_clr)
    {
    LCDWriteStringXY(6,0,"PM");
    }
    else
    {
    LCDWriteStringXY(6,0,"AM");
    }

    //Draw Pointer
    LCDWriteStringXY(sel*3,1,"^^");

    //Input Up key
    if(GetKeyStatus(1))
    {
    if(!GetPrevKeyStatus(1))
    {
    if(sel==0)
    {
    //Hour
    if(hr_clr==12)
    {
    hr_clr=1;
    }
    else
    {
    hr_clr++;
    }
    }

    if(sel==1)
    {
    //Min
    if(min_clr==59)
    {
    min_clr=0;
    }
    else
    {
    min_clr++;
    }
    }

    if(sel==2)
    {
    //AM-PM
    if(AMPM_clr==0)
    {
    AMPM_clr=0×01;
    }
    else
    {
    AMPM_clr=0;
    }
    }
    if(sel == 3)
    {
    //OK
    break;
    }
    }
    }

    //Input Down
    if(GetKeyStatus(0))
    {
    if(!GetPrevKeyStatus(0))
    {
    if(sel==0)
    {
    //Hour
    if(hr_clr==1)
    {
    hr_clr=12;
    }
    else
    {
    hr_clr–;
    }
    }

    if(sel==1)
    {
    //Min
    if(min_clr==0)
    {
    min_clr=59;
    }
    else
    {
    min_clr–;
    }
    }

    if(sel==2)
    {
    //AM-PM
    if(AMPM_clr==0)
    {
    AMPM_clr=0×01;
    }
    else
    {
    AMPM_clr=0;
    }
    }
    if(sel == 3)
    {
    //OK
    break;
    }
    }
    }

    if(GetKeyStatus(2))
    {
    if(!GetPrevKeyStatus(2))
    {
    //Change Selection
    if(sel==3)
    sel=0;
    else
    sel++;
    }
    }

    PREV_PINB=PINB;

    _delay_loop_2(30000);

    }

    //Now save time to EEPROM——————————————————————
    Mem[3] = hr_clr;
    Mem[4] = min_clr;
    Mem[5] = AMPM_clr;
    eeprom_write_block ((const void*)&Mem, (void *)1, 7);
    //—————————————————————————————–

    LCDClear();
    LCDWriteString(" Message !");
    LCDWriteStringXY(0,1,"OFF Time Set");

    uint8_t i;
    for(i=0;i<10;i++)
    _delay_loop_2(0);

    }
    //————————————————alram on and off——————

    void Alarm_on_off()
    {
    uint8_t sel=0;
    // read from EEPROM
    while(1)
    {
    LCDClear();

    LCDWriteString("— DONE");

    LCDWriteIntXY(0,0,alarm,2);

    if(alarm)
    {
    LCDWriteStringXY(0,0,"ACT");
    }
    else
    {
    LCDWriteStringXY(0,0,"DEC");
    }

    //Draw Pointer
    LCDWriteStringXY(sel*6,1,"^^");

    //Input Up key
    if(GetKeyStatus(1))
    {
    if(!GetPrevKeyStatus(1))
    {

    if(sel==0)
    {

    if(alarm==0)
    {
    alarm=1;
    }
    else
    {
    alarm=0;
    }
    }
    if(sel == 1)
    {
    //OK
    break;
    }
    }
    }

    //Input Down
    if(GetKeyStatus(0))
    {
    if(!GetPrevKeyStatus(0))
    {

    if(sel==0)
    {

    if(alarm==0)
    {
    alarm=1;
    }
    else
    {
    alarm=0;
    }
    }
    if(sel == 1)
    {
    //OK
    break;
    }
    }
    }

    if(GetKeyStatus(2))
    {
    if(!GetPrevKeyStatus(2))
    {
    //Change Selection
    if(sel==1)
    sel=0;
    else
    sel++;
    }
    }

    PREV_PINB=PINB;

    _delay_loop_2(30000);

    }

    //Now save time to EEPROM——————————————————————
    Mem[6] = alarm;
    eeprom_write_block ((const void*)&Mem, (void *)1, 7);

    //—————————————————————————————–

    LCDClear();
    LCDWriteString(" Message !");
    LCDWriteStringXY(0,1,"Alarm Set");

    uint8_t i;
    for(i=0;i<10;i++)
    _delay_loop_2(0);

    }

  19. 19
    debbie Says:

    hello avinash

    I have a doubt… does the line
    Time[0]=48+((temp1 & 0b00010000)>>4);
    perform the function of converting bcd value to binary? how does it work exactly? (esp addind 48)

    Awaiting a reply

    Thanks n regards
    Debbie

  20. 20
    Avinash Says:

    Hello Debbie,

    You could easily get that line if you know C well! The time is a string. So Time[0] is actually the 10th part of the hour. So if time is 11:00:00 AM then Time[0] is ‘1′ and if time is 03:15:24 PM then Time[0] is ‘0′ note that as Time[] is a string each element of this array is in ASCII. If you consult the ASCII Table you will note that numbers starts after 48 in ASCII table so ASCII code of ‘0′ is 48 and ‘1′ is 49 and so on. So 48 is added to it.

    If you look at DS1307 register table given above you will find out that 10th position of hour is stored in 5th BIT HOUR register. And since we are running in 12hour mode the 10th position can only be 0 or 1. It is 0 when time is from 1 to 9 and 1 when time is from 10 to 12. So just one bit is required. And since hour reg holds other values too, so to extract only the tenth part we are ANDING it with binary 00010000 (written as 0b00010000 so the compiler can get its binary number). so now all BITs are set to 0 execpt the fifth bit. Which is either 0 or 1 as in original REG. Now we shift this value to 4 places to left. This bring this bit to the 0th position. Now we add 48 to it to get an ASCII equivalent.

    All this were just requires knowledge of basic computing and C programming nothing special. Before you delve into embedded be a good programmer first.

    I have been coding since my childhood with Logo and Basic languages!

  21. 21
    Kenneth Finnegan Says:

    Using the number 48 is generally bad form when doing this kind of conversion. If you really knew C well, you would be using ‘0′ instead of the literal 48. Then it becomes pretty obvious that you’re adding an offset to the ASCII 0 character.

  22. 22
    Avinash Says:

    @Kenneth,

    Great Advice! Thanks!

  23. 23
    Amir Says:

    hi kunel
    thank u very much for your program
    but i have problem with that
    i use this version of cv avr:2.03.4 standard
    when i compile your program,i see this error

    Error: D:\documents … : MISSING ‘(‘

    and this error comes back to this line;

    uint8_t hr_,hr_set,min_,min_set,sec_,AMPM,AMPM_set,hr_clr,min_clr,AMPM_clr,alarm=0,temp1;

    what shoud i do about this?

    this is my email:
    lithium.amir@yahoo.com

    please help me
    as soon as posible…

  24. 24
    Nagaraj Says:

    Great job Avinash.
    Keep doing it…

  25. 25
    chris Says:

    Well done,

    it’s an easy job to get it run with your good description.

  26. 26
    abbOody Says:

    very good explanation
    I’ll start making this project
    thanks alot

  27. 27
    André Says:

    Wow, congratulations on projects are great!
    I’ve learned a lot from them.
    Thanks
    Ja mounted the relay and the timer clock, very good!

    Att

    André

  28. 28
    André Says:

    ah, another thing, by any chance you come to complete the items
    menu?
    if anything, could post? I would like to mount the clock
    with alarm, to turn something! interesting

    thanks

    André

Leave a Reply

Comments

    • Akhila: thank you sir.
    • kiran: Thank you Avinash..i didn’t read the user manual thats the problem ..any how thank you.....
    • Akhila: Sir, I’m working on my final yr proj which is based on “Swarmbots”.I would...
    • Uttam Dutta: RGB LED are expected from long before, now easily avilabe, thank you, may be breadboard...
    • Sayantan: sir,can u please upload the custom characters tutorial for a 16×2 lcd (4-wire)module.I have...
    • kiran: Good tutorial ..In last tutorial you created library for Progfx with extension of .lib file...
    • Abraham: Awesome tutorials….I have gone through most of them…and they are so simple and...

Video

  • Comments

    • Akhila: thank you sir.
    • kiran: Thank you Avinash..i didn’t read the user manual thats the problem ..any how thank you.....
    • Akhila: Sir, I’m working on my final yr proj which is based on “Swarmbots”.I would...
    • Uttam Dutta: RGB LED are expected from long before, now easily avilabe, thank you, may be breadboard...
    • Sayantan: sir,can u please upload the custom characters tutorial for a 16×2 lcd (4-wire)module.I have...
    • kiran: Good tutorial ..In last tutorial you created library for Progfx with extension of .lib file...
    • Abraham: Awesome tutorials….I have gone through most of them…and they are so simple and...