Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: DS1307 и день недели
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > AVR
TarasG
Не получается вытащить номер дня недели из RTC DS1307. Всё остальное вытаскивается нормально, а день недели всё время 2. Вот функция, отвечающая за это:
Код
void rtc_get_time(rtc_type *rtc_var)
{
    i2c_start();
    i2c_write_addr(DS1307_ADDR | WR);
    i2c_write(0x00);
    i2c_start();
    i2c_write_addr(DS1307_ADDR | RD);

    rtc_var->seconds = bcd2dec(i2c_read(ACK) & 0x7F);
    rtc_var->minutes = bcd2dec(i2c_read(ACK));
    rtc_var->hours = bcd2dec(i2c_read(ACK) & 0x3F);

    rtc_var->weekday = i2c_read(ACK) & 0x07;

    rtc_var->day = bcd2dec(i2c_read(ACK));
    rtc_var->month = bcd2dec(i2c_read(ACK));
    rtc_var->year = bcd2dec(i2c_read(NOT_ACK)) + 2002;

    i2c_stop();
    return;
}
Stanislav_S
Вот моя функция все прекрасно читает
void RTC_GET_TIME(TIME_type * TIME_var)
{
I2C_START();
I2C_DATA_WRITE(DS1307_ADR|WR);
I2C_DATA_WRITE(DS1307_SECUNDS);
I2C_START();
I2C_DATA_WRITE(DS1307_ADR|RD);
TIME_var->secunds=I2C_DATA_READ(ACK);
TIME_var->minutes=I2C_DATA_READ(ACK);
if(AM_PM)
{
TIME_var->hours=I2C_DATA_READ(ACK)&0x3F;
}
else
{
TIME_var->hours=I2C_DATA_READ(ACK)&0x1F;
}
TIME_var->day=I2C_DATA_READ(ACK);
TIME_var->date=I2C_DATA_READ(ACK);
TIME_var->month=I2C_DATA_READ(ACK);
TIME_var->year=I2C_DATA_READ(ACK_NOT);
I2C_STOP();
TIME_var->hours2=HOURS(OFSET_H2,AM_PM);
TIME_var->hours3=HOURS(OFSET_H3,AM_PM);
TIME_var->hours4=HOURS(OFSET_H4,AM_PM);
}
TarasG
А правда, что день недели нужно выставлять при инициализации? И как потом быть с переводом часов? Допустим я выставил 5.05.2008 понедельник, а потом мне надо перевести на 6.05.2008, день недели изменится автоматически или надо вручную вторник выставлять? Тогда получается надо в МК записывать календарь.
И ещё одно. ds1307 может работать с годом 0-99. Какие из этих чисел соответствуют високосным годам? 0, 4, 8 и т.д. или другие?
aaarrr
День недели автоматом не ставится, это просто счетчик.

Цитата(TarasG @ May 5 2008, 23:36) *
Какие из этих чисел соответствуют високосным годам? 0, 4, 8 и т.д. или другие?

0, 4, 8 и т.д. Сломается в 2100-м году.
defunct
Цитата(aaarrr @ May 5 2008, 22:50) *
0, 4, 8 и т.д. Сломается в 2100-м году.

Есть на то основания?
100 / 4 = 25 без остатка.

Про проблему 2000 года тоже много разного трещали все кому не лень. Деньги зарабатывали продавая паленые MIO карты как специальные адаптеры устраняющие проблемы Y2K. А на деле - ведь нет никакой проблемы.
aaarrr
Цитата(defunct @ May 6 2008, 00:01) *
Есть на то основания?

2000-й год был високосным (делится на 400), 2100-й не будет. А вышла DS1307 до 2000-го года.
Но вряд ли кого-либо интересует сейчас "проблема 2100" smile.gif
TarasG
Цитата(aaarrr @ May 5 2008, 22:50) *
День недели автоматом не ставится, это просто счетчик.

Очень жаль sad.gif Значит эту функцию придётся возложить на МК...
Цитата(aaarrr @ May 5 2008, 22:50) *
0, 4, 8 и т.д.

Спасибо, я так и думал.
Цитата(aaarrr @ May 5 2008, 23:28) *
2000-й год был високосным (делится на 400), 2100-й не будет. А вышла DS1307 до 2000-го года.
Но вряд ли кого-либо интересует сейчас "проблема 2100" smile.gif

Вообще-то 2100 тоже будет високосным (я имею ввиду не в DS1307, а в жизни). А вот в RTC 2100 года быть не может. Точнее, это зависит от того, какую константу я добавлю к значению года (почему-то принято 2000, но ничего не мешает добавить любой другой, кратный 4). Т.е. после 2099 года будет снова 2000 - високосный год. Или этот регистр не закольцован, как остальные?

А вообще эта проблема меня действительно волнует мало, т.к. я скорей всего до этого не доживу smile.gif
aaarrr
Цитата(TarasG @ May 6 2008, 00:44) *
Вообще-то 2100 тоже будет високосным

Не будет: делится на 100 нацело.
TarasG
Цитата(aaarrr @ May 5 2008, 23:54) *
Не будет: делится на 100 нацело.

2000 тоже делится на 100 нацело. Только он был високосным.

У меня ещё один вопрос по теме. Если день недели всего счётчик, то считает ли он перевод часов? Т.е. если я переведу часы (календарь) на сутки вперёд, добавится ли к дню недели единица? Или это тоже надо реализовывать программно?
aaarrr
Цитата(TarasG @ May 6 2008, 01:02) *
2000 тоже делится на 100 нацело. Только он был високосным.

2000 делится еще и на 400.

Цитата(TarasG @ May 6 2008, 01:02) *
У меня ещё один вопрос по теме. Если день недели всего счётчик, то считает ли он перевод часов? Т.е. если я переведу часы (календарь) на сутки вперёд, добавится ли к дню недели единица? Или это тоже надо реализовывать программно?

Нет, нужно делать программно.
TarasG
Цитата(aaarrr @ May 6 2008, 00:04) *
2000 делится еще и на 400.

Да, простите. Только что прочитал на Википедии. То, о чём я говорю, называется Юлианским календарём. А современный мир живёт по Григорианскому. А я думал, високосный год идёт каждые 4 года 05.gif
aaarrr
Цитата(TarasG @ May 6 2008, 01:10) *
А я думал, високосный год идёт каждые 4 года 05.gif

Ну, почти smile.gif А в нашем с вами случае - уж наверняка smile.gif smile.gif
TarasG
Ещё такой вопрос: зачем в этой микросхеме нужны регистры памяти 0x08-0x3F? Или их просто можно использовать как внешнюю память?
Stanislav_S
Цитата(TarasG @ May 6 2008, 02:33) *
Ещё такой вопрос: зачем в этой микросхеме нужны регистры памяти 0x08-0x3F? Или их просто можно использовать как внешнюю память?

Именно так, я их обычно для этого и использую, очень удобно.
TarasG
Цитата(aaarrr @ May 6 2008, 00:04) *
Нет, нужно делать программно.

Получается, для меня не имеет значения, как RTC считет дни недели - с понедельника или с воскресенья. Я могу присвоить 6 мая 2008 года число 2 (вторник для меня и понедельник для RTC), но об этой разнице никто и не заподозрит, если все мои функции будут 2 обрабатывать как вторник. Правильно я рассуждаю?
aaarrr
Да, все правильно.
ILYAUL
Дополнительный материал.
Таблицы я вставил по текстуНажмите для просмотра прикрепленного файла
TarasG
Цитата(ILYAUL @ May 6 2008, 13:49) *
Дополнительный материал.
Собственно можно взять D/S на микросхему и к приложенному файлу подставлять из D/S рисунки и таблицы

Так это ж другая микросхема. У меня 1307, а это 1337 07.gif
ILYAUL
Цитата(TarasG @ May 6 2008, 15:14) *
Так это ж другая микросхема. У меня 1307, а это 1337 07.gif

Честно говоря особых отличий в части часов я не замеметил , а то что вместо дополнительной памяти используются два будильника... wacko.gif
Поэтому перевел только описание Регистра управления для DS1307 .Биты RS0-RS1 програмируются так же как и DS1337
TarasG
К сожалению, самого главного в 1337 нет (как и в 1307). Я имею ввиду автоматическое вычисление дня недели smile.gif Но этот вопрос я уже решил.
Кстати, ещё интересно, есть ли такая функция в PCF8583 от Philips?
arttab
Извините что не в тему, но по 1307.
если я не делал больших пайз между считыванием данных, то данные косячились. Работал по флагу готовности. А у вас как со считыванием данных? Без проблем?
TarasG
Цитата(arttab @ May 6 2008, 16:42) *
Извините что не в тему, но по 1307.
если я не делал больших пайз между считыванием данных, то данные косячились. Работал по флагу готовности. А у вас как со считыванием данных? Без проблем?

А что Вы называете большими паузами? У меня считывание данных идёт в бесконечном цикле, в котором помимо этого содержится также проверка состояний кнопок (антидребезговая задежка 30ms на 2 кнопки), проверка режима работы устройства и обработка нажатий кнопок (изменение режима работы). Кроме того, примерно 100-150 раз в секунду срабатывает прерывание от таймера (для динамической индикации). Сбоев вроде не было smile.gif
ILYAUL
Я считываю по прерыванию от DS каждую секунду , вроде проблем нет
TarasG
Цитата(ILYAUL @ May 6 2008, 17:45) *
Я считываю по прерыванию от DS каждую секунду , вроде проблем нет

Я тоже изначально думал так сделать, но функции работы с i2c и с DS в частности связаны с ожиданием. Поэтому в момент прерывания у меня на мгновение стала пропадать индикация sad.gif Пришлось сделать так, как я описал smile.gif
kolobok0
Цитата(defunct @ May 6 2008, 00:01) *
.. А на деле - ведь нет никакой проблемы.


+1 бОльшая проблема будет когда будет 2070 год...от тогда проблема будет..а пока...фигня енто всё...


с уважением
(круглый)
ILYAUL
Цитата(TarasG @ May 6 2008, 19:43) *
Я тоже изначально думал так сделать, но функции работы с i2c и с DS в частности связаны с ожиданием. Поэтому в момент прерывания у меня на мгновение стала пропадать индикация sad.gif Пришлось сделать так, как я описал smile.gif

Вот тут же и нашёл , и что интересно ровно год назад . Так сказать все ответы на Ваши вопросы в одной куче
http://electronix.ru/forum/index.php?showt...=23755&st=0
TarasG
Цитата(ILYAUL @ May 6 2008, 19:44) *
Вот тут же и нашёл , и что интересно ровно год назад . Так сказать все ответы на Ваши вопросы в одной куче
http://electronix.ru/forum/index.php?showt...=23755&st=0

Та это и проблемами назвать как-то трудно. Работает то всё нормально...
arttab
я паузу в 9000 нопов на 8MHz ставил после выставления флага, но мне кажеться что я не правильно проверял. вот кусок тестовой проги:

//start
TWCR=(1<<TWINT)|(1<<TWSTA)|(0<<TWSTO)|(1<<TWEN); // on TWE and START
while (TWCR&(1<<TWINT)==1) {;} // wait set START on the TWI
__delay_cycles(9000);
// UDR=TWSR;
//ask device on adres and Write
TWDR=ADRESDS|0x00; // adres and read
TWCR=(1<<TWINT)|(0<<TWSTA)|(0<<TWSTO)|(1<<TWEN); // on TWE and Adres R
while (TWCR&(1<<TWINT)==1) {;} // wait TWI
__delay_cycles(9000);
// UDR=TWSR;
//read and send adres cell
TWDR=0x00; // adres ask cell
TWCR=(1<<TWINT)|(0<<TWSTA)|(0<<TWSTO)|(1<<TWEN); // on TWE
while (TWCR&(1<<TWINT)==1) {;} // wait TWI
__delay_cycles(9000);
// UDR=TWSR;
TarasG
Цитата(arttab)
//start
TWCR=(1<<TWINT)|(1<<TWSTA)|(0<<TWSTO)|(1<<TWEN); // on TWE and START
while (TWCR&(1<<TWINT)==1) {;} // wait set START on the TWI
__delay_cycles(9000);
// UDR=TWSR;
//ask device on adres and Write
TWDR=ADRESDS|0x00; // adres and read
TWCR=(1<<TWINT)|(0<<TWSTA)|(0<<TWSTO)|(1<<TWEN); // on TWE and Adres R
while (TWCR&(1<<TWINT)==1) {;} // wait TWI
__delay_cycles(9000);
// UDR=TWSR;
//read and send adres cell
TWDR=0x00; // adres ask cell
TWCR=(1<<TWINT)|(0<<TWSTA)|(0<<TWSTO)|(1<<TWEN); // on TWE
while (TWCR&(1<<TWINT)==1) {;} // wait TWI
__delay_cycles(9000);
// UDR=TWSR;

У меня сделано немного иначе. Функция не бесконечно ждёт сброса TWINT, а определённое время, по прошествии которого выдаёт сообщение об ошибке.
Код
void i2c_delay(void)
{
    if (i2c_error)
        return;
    for (unsigned char i = 0; i < 100; i++) {
        if (TWCR & (1 << TWINT))
            return;
    _delay_loop_1(0.000001 * F_CLK);
    }
    i2c_error = 1;
}

Вообще, по-моему, так сильно сложнополучается. Работу с TWI лучше разбить на функции, так проще.
arttab
это проба работы с ds1307, а не готовая часть проги.
я вопрос задал по задержки после выставления флага готовности.
Кстати, пока twi не готов его статус 0xff. вот где собачка порылась.
надо
while ( (TWCR&(1<<TWINT)==1) && (TWCR!=0xff) ) {;} // wait set START on the TWI

жаль свой test board на работе оставил, не проверю в ближайшее время
TarasG
Цитата(arttab @ May 9 2008, 07:12) *
Кстати, пока twi не готов его статус 0xff. вот где собачка порылась.
надо
while ( (TWCR&(1<<TWINT)==1) && (TWCR!=0xff) ) {;} // wait set START on the TWI

А зачем? Ведь если TWCR = 0xFF, то и бит TWINT в нём однозначно 1. Т.е. проверки (TWCR & (1 << TWINT) == 1 вполне достаточно.
Или Вы имеете ввиду статус (TWSR) 0xFF? Только я при инициализации этот регистр обнуляю:
Код
void i2c_init(void)
{
    TWSR = 0;
    TWDR = 0;
    TWAR = 0;
    TWBR = TWI_TWBR; //установить скорость шины i2c
    TWCR = ((1 << TWEN) | (1 << TWINT)); //включить модуль i2c
    i2c_error = 0; //первоначально ошибок нет
    return;
}

Вообще-то это не я придумал, а скачал билиотеку с этого форума. Но я её немного переделал smile.gif
GrayCat
Цитата(TarasG @ May 6 2008, 15:24) *
Кстати, ещё интересно, есть ли такая функция в PCF8583 от Philips?

Нету. Там, насколько я помню, еще хуже: под год выделено 2 бита, т.е. только 4-годичный цикл отслеживается.

Цитата(kolobok0 @ May 6 2008, 18:44) *
+1 бОльшая проблема будет когда будет 2070 год...от тогда проблема будет..а пока...фигня енто всё...

А что будет в 2070? Вот в 2038 эпоха UNIX-а закончится.
TarasG
Цитата(GrayCat @ May 9 2008, 22:31) *
Нету. Там, насколько я помню, еще хуже: под год выделено 2 бита, т.е. только 4-годичный цикл отслеживается.

Вообще-то я имел ввиду вычисление дня недели. А 4-годичный цикл хоть и не очень приятно, но терпимо smile.gif
Цитата(GrayCat @ May 9 2008, 22:31) *
Вот в 2038 эпоха UNIX-а закончится.

Ну это спорный вопрос. Ничего не мешает к тому времени перевести время на 64-битное число. Тогда эта дата отодвинется на несколько миллиардов лет smile.gif Не знаю, но в 64-битных система возможно так уже сделано smile.gif
GrayCat
Цитата(TarasG @ May 9 2008, 23:08) *
Вообще-то я имел ввиду вычисление дня недели.

Я тоже. Т.к. PCF8583 микросхема еще более старая чем Даллас 1307, то фичей в ней меньше, а потребление от батарейки больше. Смысла ее использовать вообще нет.

Цитата
Ну это спорный вопрос. Ничего не мешает к тому времени перевести время на 64-битное число. Тогда эта дата отодвинется на несколько миллиардов лет smile.gif Не знаю, но в 64-битных система возможно так уже сделано smile.gif

Так сделано даже в хорошо продуманных изначально 32-бит системах. Например, в QNX есть в документации такая строка: "Внимание! Этот 64-битный счетчик наносекунд переполнится в 2483 году! Если вы планируете использование ваших программ после 2483, обязательно предусмотрите соответствующие проверки!" 1111493779.gif maniac.gif yeah.gif smile3046.gif krapula.gif
TarasG
Цитата(GrayCat @ May 10 2008, 11:18) *
Я тоже. Т.к. PCF8583 микросхема еще более старая чем Даллас 1307, то фичей в ней меньше, а потребление от батарейки больше. Смысла ее использовать вообще нет.

А мне из даташита показалось, что в неё как раз больше функциональность. Например, сотые доли секунды, таймеры и т.д. В моём случае это, конечно, не нужно. Но в других может и понадобится...
Цитата(GrayCat @ May 10 2008, 11:18) *
Так сделано даже в хорошо продуманных изначально 32-бит системах. Например, в QNX есть в документации такая строка: "Внимание! Этот 64-битный счетчик наносекунд переполнится в 2483 году! Если вы планируете использование ваших программ после 2483, обязательно предусмотрите соответствующие проверки!" 1111493779.gif maniac.gif yeah.gif smile3046.gif krapula.gif

Значит проблема разрешима wink.gif Думаю, когда реально припечёт - за пару лет до даты Х - быстро выйдут соответствующие патчи и проблема будет решена smile.gif
arttab
Цитата
А зачем? Ведь если TWCR = 0xFF, то и бит TWINT в нём однозначно 1. Т.е. проверки (TWCR & (1 << TWINT) == 1 вполне достаточно. Или Вы имеете ввиду статус (TWSR) 0xFF? Только я при инициализации этот регистр обнуляю:

Ляпнул, позабыв чего делал в эксперементе.
Мне не понравилось что необходима задержка после выстакления флага готовности прежде чем я могу нормально забрать данные из TWSR.

Цитата
А зачем? Ведь если TWCR = 0xFF, то и бит TWINT внём однозначно 1. Т.е. проверки (TWCR & (1 << TWINT) == 1 вполне достаточно. Или Вы имеете ввиду статус (TWSR) 0xFF? Только я при инициализации этот регистр обнуляю:

Ляпнул, позабыв чего делал в эксперементе.
Мне не понравилось что необходима задержка после выставления флага готовности прежде чем я могу нормально забрать данные из TWSR.
Вот я и спросил про задержку. толи мне бракованные образцы попались
TarasG
По-моему, задержка там нужна не после выставления флага, а пока он ещё не установлен. Другими словами, чтоб выполнить действие (например, что-то отправить) нужно установить этот флаг в 1. На отправку данных уходит какое-то время, поэтому TWI некоторое время занят. По завершении действия флаг TWINT автоматически установтся в 0. Но пока он 1 - надо ждать, для чего и вводится задержка. Ещё раз привожу рабочий код:
Код
unsigned char i2c_error;
void i2c_start(void)
{
    if (i2c_error)
        return;
    TWCR = ((1 << TWEN) | (1 << TWINT) | (1 << TWSTA));
    i2c_delay();
    if ((TWSR != START) && (TWSR != REP_START))
        i2c_error = 1;
    return;
}
void i2c_delay(void)
{
    if (i2c_error)
        return;
    for (unsigned char i = 0; i < 100; i++) {
        if (TWCR & (1 << TWINT))
            return;
        _delay_loop_1(0.000001 * F_CLK);
    }
    i2c_error = 1;
    return;
}
arttab
про что и речь. надо ждать готовности twi. о готовности его говорит выставленный флаг TWINT.
но у меня чтобы получить корректные данные нужно ждать после выставления флага. где то ляп. у меня или в микрухе.
ILYAUL
Цитата(TarasG @ May 11 2008, 13:07) *
По-моему, задержка там нужна не после выставления флага, а пока он ещё не установлен. Другими словами, чтоб выполнить действие (например, что-то отправить) нужно установить этот флаг в 1. На отправку данных уходит какое-то время, поэтому TWI некоторое время занят. По завершении действия флаг TWINT автоматически установтся в 0. Но пока он 1 - надо ждать, для чего и вводится задержка.

Ну , не совсем так

При формировании какого либо действия на шине TWI Вы дожны TWCR записать , что Вы собственно хотите от TWI ,
Код
  ldi      temp, (1<<TWINT)|(1<<TWSTA)|(1<<TWEN); формирование сигнала START
          sts      TWCR, temp

Как только выполниться команда STS - дальнейшее от Вас не зависит ибо , TWINT сбросится в 0 , сформируется Start , а вот дальше придётся ждать когда TWINT снова станет 1 и в регистре TWSR появиться код выполнения операции ( в данном случае старт) .
Лучше просто проверять TWINT на 1 - просмотреть код возврата , и принять решение, что делать дальше


Код
;*************************************************
;*                                               *
;*       Подпрограмма Init TWI_START             *
;*     Формирование START и проверка ответа.     *
;*                                               *
;*                                               *
;*************************************************

TWI_START:
        
           ldi      temp, (1<<TWINT)|(1<<TWSTA)|(1<<TWEN); формирование сигнала START
       sts      TWCR, temp
        
waitST:
        lds      temp,TWCR   ; Проверка бита TWINT
        sbrs     temp,TWINT
        rjmp     waitST                                    ; Не получен -цикл
        lds    temp,TWSR; Проверка кода ответа
        andi    temp,$F8    ;
        cpi    temp,START                            ;code=08
        breq    RETURN     ; Правильный код -выход из подпрограммы
        brne    TWI_START                             ; Нет - повтор.
RETURN:    ret


И код 0xFF я в TWI не нашёл? есть F8 - не сформирован START (STOP) - вообще-то просто промежуточный код и есть 00- ошибка на шине
Остальные коды есть в DS на каждый проц , но они стандартны для всех

В такой режиме Вы не пропустите данные и всегда знаете , что делать с шиной.
zheka
Господа, пытаюсь прочесть день недели - все время выдает 0.
Работаю в CodeVision, там функции чтения дня недели нет, поэтому я использую отрытую на просторах интернета функцию day=rtc_read(0x03); Возвращает все время ноль. А вообще микросхема сама расчитывает день недели, или его нужно раз выставить, а потом мироксхема просто будет считать до 7 и обнуляться?
rx3apf
Цитата(zheka @ Apr 9 2011, 00:12) *
А вообще микросхема сама расчитывает день недели, или его нужно раз выставить, а потом мироксхема просто будет считать до 7 и обнуляться?

Надо выставить, про календарь она ничего не знает.
aaarrr
Не рассчитывает - это просто счетчик.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.