Code: Select all
//--------- Адреса регистров DS3231
#define clkadrSEC 0x00 //Адрес счетчика секунд
#define clkadrMINUTE 0x01 //Минуты
#define clkadrHOUR 0x02 //часы
#define clkadrDAY 0x03 //День
#define clkadrDATA 0x04 //Дата
#define clkadrMONTH 0x05 //Месяц
#define clkadrYEAR 0x06 //Год
#define alrm1adrSEC 0x07 //Будильник 1 секунды
#define alrm1adrMINUTE 0x08 //минуты
#define alrm1adrHOURE 0x09 //часы
#define alrm1adrDATA 0x0a //день или дата
#define alrm2adrMINUTE 0x0b //Будильник 2 минуты
#define alrm2adrHOUR 0x0c //часы
#define alrm2adrDATA 0x0d //день или дата
#define ctradrCTRL 0x0e //Регистр контроля. Управление выводами и генератором
#define ctradrSTATUS 0x0f //Регистр статуса и контроля. Статус блоков RTC
#define ctradrAGGIN 0x10 //Значение коэффициента температурной коррекции
#define ctradrMSB_TPR 0x11 //Целая часть температуры в прямом дополнительном коде.
#define ctradrLSB_TPR 0x12 //Биты 7 и 8 это дробная часть температуры с точностью
//0,25 градуса. Т.е. 0 - это 0b00000000,
//0b01000000 - 0.25, 0b10000000 - 0.5, 0b11000000 -0.75
в DS1307 по адресу 0x07 расположен регистр управления, а с 0x08 начинается память (питаемая от батарейки).
Code: Select all
static unsigned char _ds1307 = false;
static unsigned char _ds3231 = false;
unsigned char ds3231(void) { return _ds3231; }
void rtc_Autodetect(void) // Autodetection
{
unsigned char temp1;
unsigned char temp2;
temp1 = rtc_read(0x11); // сохранение ячеек
temp2 = rtc_read(0x12); // 0x11 и 0x12 ds1307
rtc_write(0x11, 0xAA); // пишем AAh
rtc_write(0x12, 0x55); // пишем 55h
// Регистры температуры ds3231 работают только на чтение (read-only), записать их нельзя.
if (rtc_read(0x11) == 0xAA && rtc_read(0x12) == 0x55)
{
_ds1307 = true; // это ds1307
rtc_write(0x11, temp1); // restore
rtc_write(0x12, temp2);
}
else
{
_ds3231 = true; // это ds3231
}
}
void run_clock(void) // запуск ds1307
{
unsigned char b;
//Куда подключено прерывание
#define INT_PORT PORTD
#define INT_DDR DDRD
#define INT_PIN PIND
#define INT_INPUT 3 //номер вывода
// INT0 PD2
// INT1 PD3
//настроим INT1 на вход и подтянем к плюсу
INT_DDR &= ~(1<<INT_INPUT);
INT_PORT |= (1<<INT_INPUT);
if (ds3231()) // 3231
{
rtc_write(0x0E, 0x20); // регистр управления 1Гц на SQW
// 00100000
// 7 - ~EOSC разрешение работы генератора. при = 0, запускается генератор.
// 6 - BBSQW Battery-Backed Square-Wave Enable
// 5 - CONV лог. 1 принудительно запускает оцифровку значения датчика температуры.
// 4, 3 - (RS2 и RS1) Частота на выходе SQW, 00 - 1 Гц
// 2 - INTCN установлен в лог. 0, сигнал выводится на ножку ~INT/SQW микросхемы.
// 1 - A2IE Когда этот бит установлен в лог. 1,
// 0 - A1IE он разрешает активацию ~INT/SQW будильника (1, 2)
rtc_write(0x0F, 0x08); // разрешим выход 32кГц
// 00001000
// 7 - Oscillator Stop Flag (OSF). Лог. 1 - генератор остановлен
// 3 - Enable 32kHz в лог. 1, работа выхода 32kHz разрешена
// 2 - Busy (BSY). Этот бит показывает, что микросхема занята выполнением функции коррекции частоты генератора
// 1 - Alarm 2 Flag (A2F). Лог. 1 в этом бите показывает совпадение регистров будильника 2
// 0 - Alarm 1 Flag (A1F) для будильника 2
// rtc_write(0x0A, 0x81); // срабатывание будильника 1, каждый день
// val = rtc_read(0x0E);
// val |= ((1 << 2) | (1 << 0)); // INTCN = 1, A1IE = 1,
// rtc_write(0x0E, val); // активация будильника 1 на INT/SQW
}
else
{
b = rtc_read(0x0); // читать секунды
// бит 7 (CH) регистра секунд DS1307 останавливает или запускает генератор 0 - запущен, 1 - остановлен)
b &= 0b01111111; // принудительная установка 7-го бита в "0"
rtc_write(0x00, b); // записать секунды
rtc_write(0x07, 0x90); // меандр с частотой 1Гц на SQW
// 7 - OUT (Output control - управление выходом) SQW/OUT равен 1 если OUT = 1, и 0 если OUT = 0.
// 4 - SQWE (Square Wave Enable - включение сигнала с прямоугольными импульсами) 1, включается генерация прямоугольных импульсов
// 1, 0 - (RS1 и RS0) Частота на выходе SQW, 00 - 1 Гц ,
}
}
Вариант работы с часами.
Если не используете будильники, то замена DS3231 на DS1307 возможна без напильника в ПО.
Для DS1307 нужен сброс 7-го бита секунд, при первом запуске.