Четверг, 02.05.2024, 03:40
Главная
Приветствую Вас, Гость
Статистика



Онлайн лист

Онлайн всего: 1
Гостей: 1
Пользователей: 0



Реклама



Главная » Статьи » Микроконтроллеры

Наверх


Часы на DS1307
Наконец то и в мои руки попала микросхема часов реального времени DS1307. Это маленькая микросхема, требующая минимум обвязки, с которой очень просто работать. Ниже я покажу на примере как сделать часы на основе этой микросхемы, микроконтроллера Atmega16 и среды программирования CodeVisionAVR.
Сначала немного о самой микросхеме часов:

Назначение выводов:
X1,X2 - Входы для подключения часового кварца (32,768кГц)
VBat - подключения "+" батарейки 3В (например CR2032)
GND - общий
SDA - линия данных I2C
SCL - тактовая линия I2C
SQW/OUT - выход для тактирования внешних устройств
Vcc - +5В

Схема часов приведена ниже:
схема часов на atmega16, DS1307 и LCDHD44780

Мозгом часов является микроконтроллер atmega16, к которому подключена микросхема часов, дисплей с контроллером HD44780, и три кнопки для настройки часов.

Теперь надо заставить все это работать.
Для того чтобы наша atmega смогла работать с микросхемой часов, нам нужно настроить шину I2C, для этого в генераторе кода нужно перейти на вкладку I2C, выбрать порт к которому будем подключать часы,в моем варианте это PORTB, указать на какие пины будут подключены линии SDA и SCL, и выбрать микросхему часов, для этого перейти на внутреннюю вкладку DS1307 и поставить галочку Enable:





В CodeVisionAVR есть готовая библиотека для работы с часами DS1307, что сильно упрощает жизнь. И так что мы можем:

void rtc_write(unsigned char address,unsigned char data); - запись данных в микросхему часов, например выбрать 12 или 24 часовой формат времени, выбрать частоту импульсов на выходе OUT и т.д.;

void rtc_init(unsigned char rs,unsigned char sqwe,unsigned char out); - инициализация микросхемы часов;

void rtc_get_time(unsigned char *hour,unsigned char *min,unsigned char *sec); - получение времени от микросхемы часов;

void rtc_set_time(unsigned char hour,unsigned char min,unsigned char sec); - установка значения времени в часы;

void rtc_get_date(unsigned char *date,unsigned char *month,unsigned char *year); - получение даты;

void rtc_set_date(unsigned char date,unsigned char month,unsigned char year); - настройка даты.

Этих функций нам вполне хватит для того чтобы наши часики заработали. Чтобы несколько раз не писать одно и тоже, привожу исходный код с подробными комментариями:


 
#include <mega16.h>
#include <stdio.h>
#include <delay.h>
// I2C Bus functions
#asm
.equ __i2c_port=0x18 ;PORTB
.equ __sda_bit=1
.equ __scl_bit=0
#endasm
#include <i2c.h>

// DS1307 Real Time Clock functions
#include <ds1307.h>
#define pause delay_ms(200)

#asm
.equ __lcd_port=0x1B ;PORTA
#endasm
#include <lcd.h>
unsigned char hour, min, sec;
unsigned char set;
unsigned char lcd_buffer[33];
void main(void)
{
PORTA=0x00;
DDRA=0x00;
PORTB=0x00;
DDRB=0x00;
PORTC=0xFF;
DDRC=0xFF;
PORTD=0x00;
DDRD=0x00;
TCCR0=0x00;
TCNT0=0x00;
OCR0=0x00;
TCCR1A=0x00;
TCCR1B=0x00;
TCNT1H=0x00;
TCNT1L=0x00;
ICR1H=0x00;
ICR1L=0x00;
OCR1AH=0x00;
OCR1AL=0x00;
OCR1BH=0x00;
OCR1BL=0x00;
ASSR=0x00;
TCCR2=0x00;
TCNT2=0x00;
OCR2=0x00;
MCUCR=0x00;
MCUCSR=0x00;
TIMSK=0x00;
ACSR=0x80;
SFIOR=0x00;

i2c_init(); //Инициализация шины I2C
rtc_init(3,1,0); //Инициализация микросхемы часов
rtc_write(0,0); //Запуск часов
lcd_init(16); //Инициализация экрана
lcd_clear(); //Очистка экрана
while (1) //Основный цикл программы
{
set=0; //Обнуление переменной, необходимой для работы с кнопками
if(PINC.0==0) // Если нажата кнопка "Set" переходим к настройке часов
{
set=1;
while(set==1)
{
pause;
switch (PINC) { // Отслеживаем нажатие кнопок
case 0xFD: hour++; if (hour>23){hour=0;}; break; //Если нажата кнопка ">" то увеличиваем колчество часов на 1
case 0xFB: hour--; if (hour==255){hour=23;}; break; //Если нажата кнопка "<" то уменьшаем колчество часов на 1
case 0xFE: set=2; break; //Если нажата кнопка "Set", переходим к настройкам минут
};
lcd_clear(); // Очистка экрана
sprintf(lcd_buffer,"Hour: %u%u",hour/10,hour%10); //Запись в буфер значения параметра час
lcd_puts(lcd_buffer); // Вывод на экран текущее значение параметра час
};
while(set==2)
{
pause;
switch (PINC) { // Отслеживаем нажатие кнопок
case 0xFD: min++; if (min>59){min=0;}; break; //Если нажата кнопка ">" то увеличиваем колчество минут на 1
case 0xFB: min--; if (min==255){min=59;}; break; //Если нажата кнопка "<" то уменьшаем колчество минут на 1
case 0xFE: set=0;rtc_set_time(hour,min,sec); break; //Если нажата кнопка "Set", отправляем в микросхему часов новые значения времени
};

lcd_clear(); // Очистка экрана
sprintf(lcd_buffer,"Min: %u%u",min/10,min%10); //Запись в буфер значение минут
lcd_puts(lcd_buffer); // Вывод на экран текущее количество минут
};
};

rtc_get_time(&hour,&min,&sec); //считать время
sprintf(lcd_buffer,"Time: %u%u:%u%u:%u%u",hour/10,hour%10,min/10,min%10,sec/10,sec%10); // Запись в буфер значение времени
lcd_clear(); //очистка экрана
lcd_puts(lcd_buffer); Выводим на экран текущее время
pause;
};
}




Свои часы я собрал на плате переходнике soic8-DIP. Меленькая компактная плата, на которой спокойно размещаются все детали:

часы реального времени DS1307часы реального времени DS1307


Нравится
Категория: Микроконтроллеры | Добавил: Naprisar (18.10.2012)
Просмотров: 15285 | Комментарии: 10 | Теги: ATmega16, часы реального времени, RTC, микроконтроллер, DS1307
Всего комментариев: 10
10 iEugene0x7CA  
0
Хм, странно... Видать меня действительно никто не банил...
Похоже это был баг сайта... Ладно, покорно извиняюсь.
:D

Если не произведена инициализация, то секунда с 1307 читаются, как "80", у меня банально стояла проверка при старте, читались секунды, и если их там 80, то выполнялась строка rtc_write(0,0), в противном случае секунд было от 0 до 59 и условие не срабатывало.

9 Art  
0
TO iEugene0x7CA the second one
Хорошо, а как запустить rtc_write(0,0), только 1 раз если, к примеру питание, выключается и включается на протяжении дня?

7 iEugene0x7CA the second one  
0
За что забанил то, ваше превосходительство?
Даже некрасиво как-то вышло, без ответа, даже ошибку в проше не поправил. Вот же, блин, радиолюбители пошли...
>:-/

P.S.
Кто еще будет собирать, там есть еще ошибки:

Для начала rtc_write(0,0) при старте обнуляет секунды, что приводит не только к баттхерту и недоумению со стороны радиолюбителя, но и к жутким погрешностям выставленного времени.
Прописывать эту штуку нужно только раз.

Во вторых что-то не так с заданием времени, в Протеусе работает, а в железе нет, переписал код с нуля, теперь все норм.

P.P.S.
Автор, не будь казявкой.

8 Naprisar  
0
Приветствую! Я никого не банил, да как бы и не за что, критика по делу это всегда хорошо. У меня все работало и ничего не вылетело, но я все же перепроверю все замечания в ближайшее время.

6 iEugene0x7CA  
0
Автор, черт вас побери!
С какого фаллоса порт C сконфигурирован в качестве выхода?!
Это вроде как серьезная ошибка, в результате которой у любого собравшего сию чудесную схему вылетят первые 3 ножки порта, если не весь микроконтроллер...
Хорошо хоть у меня на БП стояла токовая защита на 100 мА, так бы пополнилась моя коробочка с подорванными ништяками еще одним трупиком...

Короче говоря, очень необходимо поправить код.
Никакого DDRC=0xFF чтобы там не было...

P.S.
И рас уж я сюда заглянул, можно еще узнать, каким образом мне считать и установить дату?
Требую продолжения урока!
:D

4 volver  
0
день добрый! спасибо за статейку всё понятно кроме вот это строки
case 0xFB: hour--; if (hour==255){hour=23;}; break;
ну и примерно такой же с минутами , а именно почему  hour==255?

5 Naprisar  
0
Приветствую, рад)) Суть в том что переменные hour и min обозначены как unsigned char, а это целочисленная переменная с диапазоном значений 0...255. Вот и получается что если на часах 00:XX и при уменьшении значения часа мы попадем на значение 255, а условие if (hour==255){hour=23;}; пропускает все ненужные значения и присваивает сразу значение 23, аналогично с минутами. Т.е. принудительно ограничиваем диапазон значений для часа 00 - 23, и для минут 00 - 59. Надеюсь так понятней)

2 Дмитрий  
0
Как вывести время на 2 строчку?

3 Naprisar  
0
Для отображения часов на второй строчке, надо в основном цикле while после каждой строчки с lcd_clear(); добавить строчку lcd_gotoxy(0,1);. Получится 3 вставки такие.

1 ZigleR  
0
Спасибо за часы, возможно повторю.
Может это я отстал от жизни со своим 10 Мбит-ным DSL, но по-моему несколько фоток по пол-метра это слишком. У меня в мозилле полностью загружалось минуту наверное. Хотя, может проблема в юкозе - с хостера картинок было бы быстрее. В любом случае намного демократичнеепо отношению к пользователям было бы загружать превьюшки с линками на полные фоты.

Добавлять комментарии могут только зарегистрированные пользователи.
[ Регистрация | Вход ]

Наверх