DS1302 Побеждаем время. ds1302.c для WinAVR (GCC)


18.08.2011

DS1302 - это микросхема реального времени. Она обеспечивает ход времени, даже когда основное устройство отключено от питания.

Основные характеристики:

  • - простота подключения к микроконтроллеру по трехпроводному интерфейсу.
  • - питание от 2 до 5.5 В.
  • - из внешних элементов часовой кварц 32768 Гц и батарейка резервного питания 3В (я использую RC2032). Батарейки хватает надолго, микросхема потребляет около 300 нА (наноампер)!
  • - считает секунды, минуты, часы, день месяца, месяц, год, день недели. Учитываются високосные года. Микросхема сможет работать до 2100года. Дальше не хватит счетчика лет. Это, несомненно, опечалило меня. :)
  • - отображение времени в 12 или 24 часовом режимах с отображением AM или PM

Нюансы

Иногда пишут "в микросхеме есть встроенный календарь до 2100 года". Не спешите удивляться, это всего лишь означает, что подсчет времени ведется с учетом високосных лет. И все! На самом деле даже день недели надо устанавливать. Т.е. день недели не определяется по установленной дате. День недели работает как простой счетчик и переключается в полночь. Но с другой стороны, это очень удобно. Ведь в Восточной Европе принято считать первый день недели понедельник, а на западе первый день недели - воскресенье. В данном случае микросхеме абсолютно все равно. Устанавливаем текущий день недели по собственному исчислению, а дальше он будет изменяться каждую полночь.

Подключение к МК

Распиновка микросхемы:

Подключение к микроконтроллеру:

взяты с документации, которую можно скачать здесь: DS1302.pdf

Для тестов я взял свою отладочную плату и подключил микросхему к ней, припаяв кварц и держатель батарейке RC2032 прямо к ногам микросхемы. Для отображения времени использовал символьный LCD.

Библиотека для GCC WinAVR

Честно говоря, сразу я хотел не заморачиваться и использовать уже готовую библиотеку. Так и сделал, скачал даже две. Одну написал русский программист, а вторую иностранец. Обе не работали должным образом. В первом случае почему-то не выставлялся день больше магического 7 дня месяца, ну конечно, о 12 часовом режиме в России никогда не слышали, а буковки AM PM, для нас славян, чужды и не понятны. Во втором случае... уже догадались? Да! Иностранцы не учли, что где то на планете коварные нации исчисляют время до 24 часов!!! Вдобавок, год записывал (соответственно и считывал) не правильно. Т.е. оно конечно как то работает, но в следующем году вылезут все баги. Плюнул, написал свою простую библиотеку.

Перед тем как использовать библиотеку, откроем файл ds1302.h В нем правим только эти параметры:


#define DS1302_E 0
#define DS1302_SCLK 1
#define DS1302_IO 2

#define DS1302_DDR_RTC DDRC
#define DS1302_PORT_RTC PORTC
#define DS1302_PIN_RTC PINC

Т.е. описываем к каким ногам и к какому порту подключена наша ds1302.

Обратите внимание, что в этом же файле описана структура:


typedef    struct
{
uint8_t        Sec;
uint8_t        Min;
uint8_t        Hour;
uint8_t        Month;
uint8_t        Day;
uint8_t        Year;
uint8_t        WeekDay;
uint8_t        AMPM;
uint8_t        H12_24;
} tpDateTime;

tpDateTime    DateTime;

Через нее и будет выполняться взаимосвязь (запись и чтение) с DS1302.

В библиотеке всего две функции: void DS1302_ReadDateTime(); void DS1302_WriteDateTime();

Для установки времени в микросхеме необходимо 1. В структуру DateTime задать время и режим (12 или 24 часовой) 2. Вызвать функцию DS1302_WriteDateTime();

Для чтения времени из микросхемы: 1. Вызвать функцию DS1302_ReadDateTime(); 2. Читать время и режим из структуры DateTime.

Обратите внимание, что DateTime.AMPM и DateTime.H12_24 задаются следующим образом:

DateTime.AMPM = AM; или DateTime.AMPM = PM;

DateTime.H12_24 = H12; или DateTime.H12_24 = H24;

Пример использования:


#include <avr/io.h>
#include <util/delay.h>
#include "lcd_lib.h"

#include "ds1302.h"

char buffer[16]="";

int main()
{

// Задаем время и параметры (AM/PM следует задавать только при H12)
DateTime.Sec = 57;
DateTime.Min = 59;
DateTime.Hour = 11;
DateTime.Month = 8;
DateTime.Day = 16;
DateTime.Year = 11;
DateTime.WeekDay = 2;
DateTime.AMPM = AM;   //AM/PM
DateTime.H12_24 = H12;  //H12/H24

// Записываем время в микросхему ds1302
DS1302_WriteDateTime();

// Инициализация дисплея
LCDinit();
LCDcursorOFF();
LCDclr();

while(1)
{
// Читаем время с микросхемы ds1302
DS1302_ReadDateTime();

// Выводим время и дату на дисплей
sprintf(buffer, "%02i:%02i:%02i", DateTime.Hour, DateTime.Min, DateTime.Sec);
LCDGotoXY(0,0);
LCDstring(buffer, 8);

if (DateTime.H12_24 == H12) {
if (DateTime.AMPM == AM){
LCDsendChar(`A`);
}
else {
LCDsendChar(`P`);
}
LCDsendChar(`M`);
}

sprintf(buffer, "%02i-%02i-%02i,%i", DateTime.Day, DateTime.Month, DateTime.Year, DateTime.WeekDay);
LCDGotoXY(0,1);
LCDstring(buffer, 10);

_delay_ms(100);
}
}

Внимание! В примере в следующих строках устанавливается заранее указанное время при старте микроконтроллера.


DateTime.Sec = 57;
DateTime.Min = 59;
DateTime.Hour = 11;
DateTime.Month = 8;
DateTime.Day = 16;
DateTime.Year = 11;
DateTime.WeekDay = 2;
DateTime.AMPM = AM;   //AM/PM
DateTime.H12_24 = H12;  //H12/H24
// Записываем время в микросхему ds1302
DS1302_WriteDateTime();

Т.е. при каждом включении питания микроконтроллер будет устанавливать одно и то же время. Если в микросхеме уже установлено время (разумеется, при подключенной батарейки), можно закомментировать функцию DS1302_WriteDateTime(); скомпилировать и прошить микроконтроллер новой прошивкой. После чего он будет только читать время из микросхемы.

Скачать пример Atmega8 + DS1302

Схеми і прошивки
Коментарі:
admin говорить:
07.11.2011 16:15
Библиотека DS1302 обновлена. Исправлен баг при работе в 24 часовом режиме.

Сергей говорить:
04.04.2012 12:54
...ds1302.c для WinAVR (CGG)... А компилятор не GCC (GNU Compiler Collection)?

admin говорить:
04.04.2012 13:00
:) Спасибо! Смешная опечатка получилась. Исправил.

Сергей говорить:
05.04.2012 07:43
Это, правда, не так важно, но Столман бы обиделся не на шутку :)

Андрей говорить:
26.07.2012 21:37
Печалька, у меня не тикают. Данные записываются, читаются а не тикают.
(батарейка стоит).

Андрей говорить:
29.07.2012 03:31
Получилось, оказалось кварц не заводился поменял и всё гуд.
Спасибо за статью.

Андрей говорить:
06.12.2012 22:17
Автор вот подскажите дураку.. 
При компиляции вашего проекта получаю следуещее... 
avr-gcc -mmcu=atmega8 -I. -gdwarf-2 -DF_CPU=4000000UL -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -Wall -Wstrict-prototypes -Wa,-adhlns=test1302.o  -std=gnu99 -MMD -MP -MF .dep/test1302.elf.d test1302.o lcd_lib.o --output test1302.elf -Wl,-Map=test1302.map,--cref     -lm
test1302.o: In function `main`:
C:\\ds1302/test1302.c:23: undefined reference to `DS1302_WriteDateTime`
C:\\ds1302/test1302.c:33: undefined reference to `DS1302_ReadDateTime`
make.exe: *** [test1302.elf] Error 1

что прикажите делать ?

admin говорить:
10.12.2012 09:01
Судя по ошибке файл ds1302.c НЕ включен в проект.

<img src="http://www.avislab.com/blog/wp-content/uploads/2011/08/DS1302_WriteDateTime.png" alt="" />

Юрий говорить:
15.12.2012 12:23
ДД!
Попробовал вашу библиотеку - ошибка при считывании дня, а встроенная в CVAVRe работает без ошибки, но там нет дня недели. Жаль.
P.S. ДД - это добрый день! :-)

admin говорить:
17.12.2012 08:42
А в чем выражается ошибка? Считывается всегда 0, либо конкретное число?

Юрий говорить:
01.01.2013 13:56
Число, но не соответсвующее дню (похоже день недели). В CVAVRе прикрутил день недели, там есть функция unsigned char ds1302_read(unsigned char addr);

Додати коментар
Code
* - обов'язкові поля

Архіви