Пример работы с часами реального времени DS1307 на AVR

Нашёл у себя на компьютере экспериментальный проектик на часах DS1307. Сам проект не планировалось собирать, а делался чисто для проверки… поэтому здесь нет никаких наворотов, а просто микроконтроллер+дисплей nokia 3310 + 4 кнопки. Собственно вот схема в Proteus.DS1307+ATMEGA8

На схеме нет кварца — к меге 16мгц, а к часикам часовой кварц желательно с канденсаторами по 22пф. Вообщем чтоб небыло неясностей привожу схему со всеми элементами( схема выше — чисто для симулятора).

DS1307+ATMEGA8_rewrite

 

Фьюзы — нужно настроить на внешний кварц.

Не забудьте про батарейку для часов.

Исходник написан в CVAVR:

Chip type               : ATmega8
Program type            : Application
AVR Core Clock frequency: 16,000000 MHz
Memory model            : Small
External RAM size       : 0
Data Stack size         : 256
*****************************************************/

#include <mega8.h>
#include <delay.h>
#include <stdio.h>
#include <stdlib.h> // библиотека преобразоания чисел в символьную строку
#include <ctype.h> // библиотека преобразования символов в число
#include <string.h> //библиотека работы со строками
#include "NokiaLCD.h"
#include "lcd_3310.c"
// I2C Bus functions
#asm
.equ __i2c_port=0x15 ;PORTC
.equ __sda_bit=4
.equ __scl_bit=5
#endasm
#include <i2c.h>

// DS1307 Real Time Clock functions
#include <ds1307.h>
#define btn_m PIND.0
#define btn_minus PIND.2
#define btn_plus PIND.1
#define btn_b PIND.3
unsigned char buff [99];  //буфер дисплея
unsigned char hour,minut,sek; //часы, минуты, секунды
unsigned char m,h,s; //часы, минуты, секунды
unsigned char day,month,year; //день, месяц, год
unsigned char d,mo,y; //день, месяц, год
unsigned char flag,menu;

void read_time()
{
rtc_get_time(&hour,&minut,&sek); //считать время
h=hour;
m=minut;
s=sek;
}

void read_date()
{
rtc_get_date(&day,&month,&year); //считать дату
d=day;
mo=month;
y=year;
}

void btn()
{
if(btn_m==0&&menu==0){menu=1;ClearLcd();}
if(menu==1){if(btn_m!=0){menu=2;ClearLcd();}}
if(btn_m==0&&menu!=0&&menu!=1){delay_ms(100);menu++;flag=0;ClearLcd();}
if(btn_b==0&&menu!=0&&menu!=1){delay_ms(100);menu--;flag=0;ClearLcd();}
if(menu>=8){menu=0;}

if(menu==2)
{
if(flag==0){ read_time(); flag=1;}
if(btn_plus==0){delay_ms(100);hour++;}
if(btn_minus==0){delay_ms(100);hour--;}
}
if(menu==3)
{
if(flag==0){ read_time(); flag=1;}
if(btn_plus==0){delay_ms(100);minut++;}
if(btn_minus==0){delay_ms(100);minut--;}
}
if(menu==4)
{
if(flag==0){ read_time(); flag=1;}
if(btn_plus==0){delay_ms(100);sek++;}
if(btn_minus==0){delay_ms(100);sek--;}

}
if(hour>=24){hour=0;}
if(minut<1){minut=59;hour--;}
if(minut>=60){minut=0;hour++;}
if(sek<1){sek=59;minut--;}
if(sek>=60){sek=0;minut++;}
if(menu>1){  rtc_set_time(hour,minut,sek);} //установить время: часы, минуты, секунды

if(menu==5)
{
if(flag==0){ read_date(); flag=1;}
if(btn_plus==0){delay_ms(100);day++;}
if(btn_minus==0){delay_ms(100);day--;}
}
if(menu==6)
{
if(flag==0){ read_date(); flag=1;}
if(btn_plus==0){delay_ms(100);month++;}
if(btn_minus==0){delay_ms(100);month--;}
}
if(menu==7)
{
if(flag==0){ read_date(); flag=1;}
if(btn_plus==0){delay_ms(100);year++;}
if(btn_minus==0){delay_ms(100);year--;}
}
if(day>=32){day=1;month++;}
if(day<1){day=31;month--;}
if(month>=13){month=1;year++;}
if(month<1){month=12;year--;}
if(year>=255){year=0;}
if(menu>1){ rtc_set_date(day,month,year);} //установить date
}

void lcd()
{
if(menu==0)
{
LcdPutLine("Сегодня:", 2, 1);   // вывели текст
sprintf( buff,"%i.%i.%i г  ", d,mo,y+2000 );
LcdPutLine(buff, 2, 2);
LcdPutLine("Время:", 2, 3);   // вывели текст
sprintf( buff,"%i:%i%i:%i%i  ", h,m/10,m%10,s/10,s%10 );
LcdPutLine(buff, 2, 4);
}
if(menu==1)
{

LcdPutLine("    Режим", 2, 3);   // вывели текст
LcdPutLine("   Настроек", 2, 4);   // вывели текст
delay_ms(500);
}
if(menu==2)
{
LcdPutLine("Сегодня:", 2, 1);   // вывели текст
sprintf( buff,"%i.%i.%i г  ", d,mo,y+2000 );
LcdPutLine(buff, 2, 2);
LcdPutLine("Время:", 2, 3);   // вывели текст
sprintf( buff,"%i<%i%i:%i%i ", h,m/10,m%10,s/10,s%10 );
LcdPutLine(buff, 2, 4);
}
if(menu==3)
{
LcdPutLine("Сегодня:", 2, 1);   // вывели текст
sprintf( buff,"%i.%i.%i г  ", d,mo,y+2000 );
LcdPutLine(buff, 2, 2);
LcdPutLine("Время:", 2, 3);   // вывели текст
sprintf( buff,"%i:%i%i<%i%i ", h,m/10,m%10,s/10,s%10 );
LcdPutLine(buff, 2, 4);
}
if(menu==4)
{
LcdPutLine("Сегодня:", 2, 1);   // вывели текст
sprintf( buff,"%i.%i.%i г  ", d,mo,y+2000 );
LcdPutLine(buff, 2, 2);
LcdPutLine("Время:", 2, 3);   // вывели текст
sprintf( buff,"%i:%i%i:%i%i< ", h,m/10,m%10,s/10,s%10 );
LcdPutLine(buff, 2, 4);
}
if(menu==5)
{
LcdPutLine("Сегодня:", 2, 1);   // вывели текст
sprintf( buff,"%i<%i.%i г  ", d,mo,y+2000 );
LcdPutLine(buff, 2, 2);
LcdPutLine("Время:", 2, 3);   // вывели текст
sprintf( buff,"%i:%i%i:%i%i ", h,m/10,m%10,s/10,s%10 );
LcdPutLine(buff, 2, 4);
}
if(menu==6)
{
LcdPutLine("Сегодня:", 2, 1);   // вывели текст
sprintf( buff,"%i.%i<%i г  ", d,mo,y+2000 );
LcdPutLine(buff, 2, 2);
LcdPutLine("Время:", 2, 3);   // вывели текст
sprintf( buff,"%i:%i%i:%i%i ", h,m/10,m%10,s/10,s%10 );
LcdPutLine(buff, 2, 4);
}
if(menu==7)
{
LcdPutLine("Сегодня:", 2, 1);   // вывели текст
sprintf( buff,"%i.%i.%i<  ", d,mo,y+2000 );
LcdPutLine(buff, 2, 2);
LcdPutLine("Время:", 2, 3);   // вывели текст
sprintf( buff,"%i:%i%i:%i%i ", h,m/10,m%10,s/10,s%10 );
LcdPutLine(buff, 2, 4);
}
}

void main(void)
{
// Port B initialization
PORTB=0x00;
DDRB=0x3F;
// Port C initialization
PORTC=0x70;
DDRC=0x00;
// Port D initialization
PORTD=0x00;
DDRD=0xF0;
PORTD.0=1;
PORTD.1=1;
PORTD.2=1;
PORTD.3=1;
// I2C Bus initialization
i2c_init();

// DS1307 Real Time Clock initialization
// Square wave output on pin SQW/OUT: Off
// SQW/OUT pin state: 0
rtc_init(0,0,0);

LcdInit();
ClearLcd();
LcdContrast (40);
while (1)
{
read_time();
read_date();
lcd();
btn();

}
}

При включени сразуже отображается дата и время. Если нажать кнопку «MENU» то на экране кратковременно появится надпись «Режим настроек» — после этого на дисплее появится стрелка указывающая на изменяемый параметр. Навигация осуществляется той же кнопкой + кнопка «DOWN» для возврата на предыдущий параметр.

Думаю в пояснении схема больше не нуждается, если что то не понятно спрашивайте на форуме или в коментариях.

ВНИМАНИЕ!

Если у вас не работают часы — проверьте питание! — оно должно быть не менее 4,5В! При меньшем напряжении микросхема работает нестабильно, а то и вообще никак!

Скачать проект Часы DS1307 Скачали 5756 раз

 

Пример работы с часами реального времени DS1307 на AVR: 30 комментариев

  1. А можно попросить схему подключению к какому нибудь другому LCD? к той же NOKIA7110. Спасибо

  2. написал на форуме, еще в пятницу, до сих пор модерацию не прошел мой пост(((

    1. Возможно Ваш пост не прошёл анти-спам проверку… Что бы писать без модерации нужно быть зарегистрированным пользователем — вы зарегистрированы?

  3. Собрал в кодевизе 3.19, часы идут(единственно переписал немного под библиотеку LPH9157-2, ну нету у меня 3310:-), работает часы идут, но только стоит нажать на меню, вечно крутит «меню настроек» и на этом все(((
    вот код:

    #include 
    #include 
    #include 
    #include  // библиотека преобразоания чисел в символьную строку
    #include  // библиотека преобразования символов в число
    #include  //библиотека работы со строками
    #include 
    //#include "NokiaLCD.h"
    //#include "lcd_3310.c"
    // I2C Bus functions
    #asm
       .equ __i2c_port=0x15 ;PORTC
       .equ __sda_bit=4
       .equ __scl_bit=5
    #endasm
    #include 
    
    // DS1307 Real Time Clock functions
    #include 
    #define btn_m PINC.2
    #define btn_minus PINC.1
    #define btn_plus PINC.0
    #define btn_b PIND.3
    unsigned char buff [99];  //буфер дисплея
    unsigned char hour,minut,sek; //часы, минуты, секунды
    unsigned char m,h,s; //часы, минуты, секунды
    unsigned char week_day,day,month,year; //день, месяц, год
    unsigned char d,mo,y; //день, месяц, год
    unsigned char flag,menu; 
    flash char char_2[] = {"Сегодня"};
    flash char char_4[] = {"Меню настройки"};
    flash char char_1[] = {"Время"};
    
    void read_time()
     {
       rtc_get_time(&hour,&minut,&sek); //считать время
       h=hour;
       m=minut;
       s=sek;
     }
    
    void read_date()
     {
       rtc_get_date(&week_day,&day,&month,&year); //считать дату
       //w=week_day;
       d=day;
       mo=month;
       y=year;
     }
    
    
    void btn()
     {
        if(btn_m==0&&menu==0){menu=1;LCD_FillScreen (0);}
      if(menu==1){if(btn_m!=0){menu=2;LCD_FillScreen (0);}}
      if(btn_m==0&&menu!=0&&menu!=1){delay_ms(100);menu++;flag=0;LCD_FillScreen (0);}
      if(btn_b==0&&menu!=0&&menu!=1){delay_ms(100);menu--;flag=0;LCD_FillScreen (0);}
      if(menu>=8){menu=0;}
    
        if(menu==2)
        {
          if(flag==0){ read_time(); flag=1;}
          if(btn_plus==0){delay_ms(100);hour++;}
          if(btn_minus==0){delay_ms(100);hour--;}
        }
        if(menu==3)
        {
          if(flag==0){ read_time(); flag=1;}
         if(btn_plus==0){delay_ms(100);minut++;}
         if(btn_minus==0){delay_ms(100);minut--;}
        }
        if(menu==4)
        {
          if(flag==0){ read_time(); flag=1;}
          if(btn_plus==0){delay_ms(100);sek++;}
          if(btn_minus==0){delay_ms(100);sek--;}
    
        }
        if(hour>=24){hour=0;}
        if(minut=60){minut=0;hour++;}
        if(sek=60){sek=0;minut++;}
        if(menu>1){  rtc_set_time(hour,minut,sek);} //установить время: часы, минуты, секунды
    
         if(menu==5)
       {
       if(flag==0){ read_date(); flag=1;}
        if(btn_plus==0){delay_ms(100);day++;}
        if(btn_minus==0){delay_ms(100);day--;}
       }
          if(menu==6)
       {
         if(flag==0){ read_date(); flag=1;}
        if(btn_plus==0){delay_ms(100);month++;}
        if(btn_minus==0){delay_ms(100);month--;}
       }
           if(menu==7)
       {
         if(flag==0){ read_date(); flag=1;}
        if(btn_plus==0){delay_ms(100);year++;}
        if(btn_minus==0){delay_ms(100);year--;}
       }
        if(day>=32){day=1;month++;}
        if(day=13){month=1;year++;}
        if(month=255){year=0;}
      if(menu>1){ rtc_set_date(week_day,day,month,year);} //установить date
     }
    
    void lcd()
     {
        if(menu==0)
        {
         LCD_Putsf (char_2, 68, 6, RED, 0,0,0);   // вывели текст
         sprintf( buff,"%i.%i.%iг  ", d,mo,y+2000 );
         LCD_Puts (buff, 40, 20, BLUE, 0,2,2);
         LCD_Putsf (char_1, 76, 40, YELLOW, 0,0,0);
         sprintf( buff,"%i:%i%i:%i%i ", h,m/10,m%10,s/10,s%10 ); 
         LCD_Puts (buff, 40, 54, GREEN, 0,2,2);
          delay_ms(20);
         }
             if(menu==1)
        {
    
         LCD_Putsf (char_4, 50, 15, NAVY, 0,1,1);
         //LcdPutLine("   Настроек", 2, 4);   // вывели текст
          delay_ms(100);
         }
             if(menu==2)
        {
         LCD_Putsf (char_2, 68, 6, RED, 0,0,0);   // вывели текст
         sprintf( buff,"%i.%i.%iг", d,mo,y+2000 );
         LCD_Puts (buff, 40, 20, BLUE, 0,2,2);
         LCD_Putsf (char_1, 76, 40, YELLOW, 0,0,0);   // вывели текст
         sprintf( buff,"%i:%i%i:%i%i", h,m/10,m%10,s/10,s%10 );
         LCD_Puts (buff, 40, 54, GREEN, 0,2,2);
         }
                  if(menu==3)
        {
         LCD_Putsf (char_2, 68, 6, RED, 0,0,0);   // вывели текст
         sprintf( buff,"%i.%i.%iг", d,mo,y+2000 );
         LCD_Puts (buff, 40, 20, BLUE, 0,2,2);
         LCD_Putsf (char_1, 76, 40, YELLOW, 0,0,0);   // вывели текст
         sprintf( buff,"%i:%i%i:%i%i", h,m/10,m%10,s/10,s%10 );
         LCD_Puts (buff, 40, 54, GREEN, 0,2,2);
         }
                  if(menu==4)
        {
         LCD_Putsf (char_2, 68, 6, RED, 0,0,0);   // вывели текст
         sprintf( buff,"%i.%i.%iг", d,mo,y+2000 );
         LCD_Puts (buff, 40, 20, BLUE, 0,2,2);
         LCD_Putsf (char_1, 76, 40, YELLOW, 0,0,0);   // вывели текст
         sprintf( buff,"%i:%i%i:%i%i", h,m/10,m%10,s/10,s%10 );
         LCD_Puts (buff, 40, 54, GREEN, 0,2,2);
         }
                  if(menu==5)
        {
         LCD_Putsf (char_2, 68, 6, RED, 0,0,0);   // вывели текст
         sprintf( buff,"%i.%i.%iг", d,mo,y+2000 );
         LCD_Puts (buff, 40, 20, BLUE, 0,2,2);
         LCD_Putsf (char_1, 76, 40, YELLOW, 0,0,0);   // вывели текст
         sprintf( buff,"%i:%i%i:%i%i", h,m/10,m%10,s/10,s%10 );
         LCD_Puts (buff, 40, 54, GREEN, 0,2,2);
         }
                  if(menu==6)
        {
         LCD_Putsf (char_2, 68, 6, RED, 0,0,0);   // вывели текст
         sprintf( buff,"%i.%i.%iг", d,mo,y+2000 );
         LCD_Puts (buff, 40, 20, BLUE, 0,2,2);
         LCD_Putsf (char_1, 76, 40, YELLOW, 0,0,0);   // вывели текст
         sprintf( buff,"%i:%i%i:%i%i", h,m/10,m%10,s/10,s%10 );
         LCD_Puts (buff, 40, 54, GREEN, 0,2,2);
         }
                       if(menu==7)
        {
         LCD_Putsf (char_2, 68, 6, RED, 0,0,0);   // вывели текст
         sprintf( buff,"%i.%i.%iг", d,mo,y+2000 );
         LCD_Puts (buff, 40, 20, BLUE, 0,2,2);
         LCD_Putsf (char_1, 76, 40, YELLOW, 0,0,0);   // вывели текст
         sprintf( buff,"%i:%i%i:%i%i", h,m/10,m%10,s/10,s%10 );
         LCD_Puts (buff, 40, 54, GREEN, 0,2,2);
         }
     }
    
    void main(void)
    {
    // Declare your local variables here
    
    // Input/Output Ports initialization
    // Port B initialization
    // Func7=In Func6=In Func5=Out Func4=Out Func3=Out Func2=Out Func1=Out Func0=Out
    // State7=T State6=T State5=0 State4=0 State3=0 State2=0 State1=0 State0=0
    //PORTB=0x00;
    //DDRB=0x3F;
    
    // Port C initialization
    // Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In
    // State6=P State5=P State4=P State3=T State2=T State1=T State0=T
    //PORTC=0x70;
    //DDRC=0x00;
    
    // Port D initialization
    // Func7=Out Func6=Out Func5=Out Func4=Out Func3=In Func2=In Func1=In Func0=In
    // State7=0 State6=0 State5=0 State4=0 State3=T State2=T State1=T State0=T
    PORTD=0x00;
    DDRD=0xF0;
    PORTC.0=1;
    PORTC.1=1;
    PORTC.2=1;
    PORTC.3=1;
    
    // I2C Bus initialization
    i2c_init();
    
    // DS1307 Real Time Clock initialization
    // Square wave output on pin SQW/OUT: Off
    // SQW/OUT pin state: 0
    rtc_init(0,0,0);
    
       LCD_init(); 
       SetArea (0,176,0,132); 
       SetRotation(270);
       LCD_FillScreen (0);
     //LcdContrast (40);
    while (1)
          {
          read_time();
          read_date();
          lcd();
          btn();
    
          }
    }
    
    1. в декларации порта С исправил ошибку, но результата нет, если принудительно отправляю в программе на меню2 т.е. установку hour +- кнопки работают, но дальше не переключается, т.е я так понимаю при нажатии не добавляется отнимается menu вопрос почему?

      1. Смотрите Ваш код — очевидно что ошибка в обработке функции кнопок… Подтяжка включена? Проверьте все те изменения которые вносили. И исходник лучше из архива возьмите. В комментариях Ваш код неправильно отображается — пишите или на почту или на форуме.

  4. Артем, вы не могли бы скинуть готовый *.hex? С CVAVR 2.05.0 вылезло еще больше ошибок( Заранее спасибо.

    1. скобочки нет, потому что копировал часть кода ))) странно, распаковал проект снова, те же ошибки:
      if(menu==7)
      {
      if(flag==0){ read_date(); flag=1;}
      if(btn_plus==0){delay_ms(100);year++;}
      if(btn_minus==0){delay_ms(100);year—;}
      }
      if(day>=32){day=1;month++;}
      if(day=13){month=1;year++;}
      if(month=255){year=0;}
      if(menu>1){ rtc_set_date(day,month,year);} //установить date
      }

      127 строка

      void read_date()
      {
      rtc_get_date(&day,&month,&year); //считать дату
      d=day;
      mo=month;
      y=year;
      }
      63 строка

      1. Странный какой то глюк…только что скачал и проверил у себя — всё компилируется… Может изза версии компилятора — у меня стоит версия CVAVR 2.05.0

  5. При компиляции исходников, выдает ошибку :
    C:\DS1307\h.c(127): too few arguments in function call
    ( if(menu>1){ rtc_set_date(day,month,year); )

    C:\DS1307\h.c(63): too few arguments in function call
    ( rtc_get_date(&day,&month,&year); //считать дату )

    1. А вы исходник со статьи брали или с проекта под статьёй? — скачайте весь проект и там уже редактируйте…всё должно работать.
      там где строка 127 у вас незакрыта фигурная скобка условия IF — }.

    2. Столкнулся с подобной проблемой при компиляции проекта под Атмега64.
      Ошибка говорит о том что не достаточно переменных для функции.
      Вот так ошибку не выдает:

      ( if(menu>1){ rtc_set_date(week_day,day,month,year); )

      ( rtc_get_date(&week_day,&day,&month,&year); //считать дату )

  6. Артем понимаю что вы уже наигрались 🙂 но вот хочу подкинуть такую задачу у меня не получается:) может вы натолкнёте на идею. Проблема вот в чем камень будет реализоывать не только часы поэтому нужно его как то разгрузить а часики его грузят основательно 🙂 поэтому решил я сделать индикацию 1 раз в секунду с помощью внешнего прерывания по INT0 от выходного такта 1307 SOUT настроенного на 1Hz так вот отдельно все работает и часы и прерывание но когда все это сединяю в протеусе выдает крик души ято в дисплее была попытка чтения после записи полубайта не могу раскусить что делать вызов показа времени идёт прямо из обработчика прерывания может здесь проблема?

    1. Этот выход слаботочный — возможно из-за этого…ну и плюс ко всему протеус не всегда корректно моделирует — поэтому лучше в макете проверить. А вообще по вызову прерывания всё должно работать.

    2. Ещё можно вообще отказаться от внешней микросхемы и использовать асинхронный режим таймера с длительностью 1 секунда (+немного строк кода для реализации часиков) — может это займет меньше ресурсов, но не факт))

    1. Не за что, пользуйтесь на здоровье 😉 Может в будущем будет модификация, но маловероятно — так как разрабатывалось чисто для примера и заодно с DS-кой поиграться 🙂

  7. Скачал новые прошивки.Часы заработали.БОЛЬШОЕ спасибо.
    правда не понял в чем была проблема.

    1. Я поменял некоторые типы переменных, но дело в том что в в других моих проектах работает и по старому, правда дисплеи там от winstar — возможно из-за этого.

  8. Проверил.Все подключено правильно.Попробовал в протеусе
    время не меняется.Точно так же как и у меня на платe.

    1. В протеусе они "тикают" медленно — проверил у себя работают. на всякий случай перезалил файлы — попробуйте скачать новые файлы прошивки.

  9. кварц , батарейку поставил. фьюзы выстовил. экран работает но часы не запускаются

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *