Краткое описание
Я не буду останавливаться на работе шины IIC, отмечу только что обе микросхемы имеет адрес 0xd0. Для работы с временем микросхемы содержат семь регистров счета и регистр управления. Регистры счета содержат числа в двоично-десятичном формате, однако некоторые биты имеют особое значение.
Регистры
xxx — значение бита не определено.
| функция | индекс | биты | возможные значения | |||||||
|---|---|---|---|---|---|---|---|---|---|---|
| 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | |||
| секунды | 0x00 | ST | десятки секунд | единицы секунд | 0 — 59 | |||||
| минуты | 0x01 | xxx | десятки минут | единицы минут | 0 — 59 | |||||
| часы | 0x02 | SEB | SB | десятки часов | единицы часов | 0 — 23 | ||||
| день | 0x03 | xxx | xxx | xxx | xxx | xxx | день недели | 1 — 7 | ||
| день месяца | 0x04 | xxx | xxx | десятки дня | единицы дня | 1 — (28|29|30|31) | ||||
| месяц | 0x05 | xxx | xxx | xxx | дес | единицы месяца | 1 — 12 | |||
| год | 0x06 | десятки года | единицы года | 0 — 99 | ||||||
| регистр управления | 0x07 | OUT | FT | S | величина коррекции | - | ||||
Биты
x — после включения состояние бита может быть любым.
| бит | после сброса | описание | 
|---|---|---|
| ST | x | При записи 1 в этот бит генератор останавливается | 
| CEB | x | Когда бит CEB (Century Enable Bit) установлен, то при достижении нового века бит CB (Century Bit) поменяет значение на противоположное. | 
| CB | x | |
| OUT | 1 | Когда биты OUT (OUTput level) и FT (Frequency Test) равны нулю, вывод FT/OUT прижимается к земле. При FT=1 на выводе FT/OUT 512 Гц и бит OUT не имеет значения. | 
| FT | 0 | |
| S | x | Знак калибровки хода RTC. | 
Различия начинаются в назначении битов 7, 6 и 5 регистра часов. В M41T56 биты 7 и 6 используются для индикации перехода в новое столетие, а биты 5 и 4 используются для счета десятков часов. Причем счет часов возможен только в режиме 24, режим AM/PM недоступен. В DS1307 бит 7 не используется, ноль в бите 6 указывает, что используется режим счета 24 и этом случае биты 5 и 4 содержат десятки часов. Если в бите 6 единица, то бит 5 становится флагом AM/PM, а бит 4 содержит десятки часов.
Существенные отличия есть в регистре управления, которой содержит слово коррекции хода.
Коррекция хода
M41T56 позволяет компенсировать погрешность кварцевого резонатора в диапазоне от -62 до +124 ppm, что дает отклонение не более чем ±5 секунд за месяц. За компенсацию отвечают шесть младших битов управляющего регистра. Биты 4-0 содержат целое число без знака величины коррекции, а бит 5 задает направление коррекции. Если бит 5 содержит ноль, то ход замедляется с шагом 2.034 ppm, в противном случае RTC ускоряется с шагом 4.068 ppm. Это неудобно, поэтому я набросал пару простых функций для преобразования из ppm в слово коррекции и обратно.
/* Маска для получения только значения калибровки без знака. */
#define MASK_CALIBR             ((1 << 4) | (1 << 3) | (1 << 2) | (1 << 1) | (1 << 0))
/* Маска для получения только значения калибровки без знака. */
#define MASK_CALIBR_SIGN        (1 << 5)
/**
 * Получение значения коррекции хода.
 * @param caliber Калибровочное слово из RTC.
 * @return Коррекция хода в ppm.
 */
int8_t caliber_to_ppm(uint8_t caliber)
{
        int8_t result = caliber & MASK_CALIBR;
        result = (uint8_t) result * 2;
        if ((caliber & MASK_CALIBR_SIGN) != 0) {
                result = -result;
        } else {
                result = (uint8_t) result * 2;
        }
        return result;
}
/**
 * Получение калибровочного слова.
 * @param ppm Коррекция хода в ppm.
 * @return Калибровочное слово для RTC.
 */
uint8_t ppm_to_caliber(int8_t ppm)
{
        uint8_t result;
        if (ppm < 0) {
                result = (uint8_t) (-ppm + 1) / 2;
                result |= MASK_CALIBR_SIGN;
        } else {
                result = (uint8_t) (ppm + 2) / 4;
        }
        return result;
}
Детектирование сбоев
Ни DS1307, но M41T56 не умеют детектировать сбои генерации, но гарантируют, что при включении питания некоторые биты будут в определенном состоянии. M41T56 при включении в управляющем регистре будет 10xxxxxx. Для отслеживания сбоев в программе можно придерживаться следующего алгоритма. Если при включении микроконтроллера регистр управления RTC содержит 10xxxxxx, значит был сбой питания и в регистр нужно записать значение, старшие биты которого не равны 10. Самое простое — записать слово коррекции с битами 7 и 6 равными нулю.
Литература
Комментарии (14)
 - AntonSazonov27.06.2019 06:19- Как вы ловко занимаетесь кастингом из uint8_t в int8_t и обратно. 
 Долго думал в чём там смысл… Пришёл к выводу что его там нет. - GarryC27.06.2019 14:08- Ну некоторый смысл есть, просто его очень трудно уловить в коряво написанной программе. 
 Автор упорно пляшет по граблям, несмотря на расставленные повсюду таблички. Попробуем привести этот фрагмент в приемлемый вид
 - // для начала - битовые константы связаны и это надо подчеркнуть /* Маска для получения знака калибровки */ #define MASK_CALIBR_SIGN (1 << 5) /* Маска для получения значения калибровки без знака. */ #define MASK_CALIBR MASK_CALIBR_SIGN-1 int8_t caliber_to_ppm(uint8_t caliber) { // если египет, то повсюду египет int8_t result = caliber & MASK_CALIBR; // здесь можно обойтись без преобразования типов, но лучше его оставить result = ((uint8_t) result) << 1; // мы делаем именно сдвиг if (caliber & MASK_CALIBR_SIGN) {/* лучше избегать не равенства*/ result = ((uint8_t) result) << 1; // опять сдвиг } else { result = 0 - result; //вычитание лучше унарного минуса } return result; } - u_235 Автор27.06.2019 20:03- Я согласен, что перемудрил с приведением типов, остальное дело вкуса. Кстати, ваш пример показывает, что даже мэтры делают глупые ошибки.  - GarryC28.06.2019 14:57- На мой взгляд, нисколько не перемудрили, всегда лучше сдвигать без-знаковые типы: 
 1) не будет неопределенного поведения и
 2) это часто быстрее на некоторых МК, я по этому поводу пост писал.
 А что за глупая ошибка? - u_235 Автор28.06.2019 16:42-1- Да, я читал эту статью о сдвигах и багах AVR-GCC и это было одной из причин, по которой я использовал умножение и деление вместо сдвигов. Вторая причина — КМК это в данном случае наглядней. 
 Ошибка в раскрытии макроса MASK_CALIBR, в котором вы забыли круглые скобки.
 
 Теперь я совсем перестал понимать, в чем корявость программы. - assad7728.06.2019 18:04- Да нет корявости никакой. 
 В таких по размеру программах вообще об этом бессмысленно говорить.
 Работает, понятно в общих чертах с первого взгляда и ладно.
 Ктото другой конечно бы написал по другому, но на это не стоит внимание обращать.
 По поводу размера: ну как кая разница больше ли прошивка на 6 байт или нет, если она помещается в память.
 Вот если не помещается, или например не хватает оперативки для переменных, или скорости не хватало бы или надо было энергию экономить, вот тогда и надо было бы чтото улучшать.
 Я б тоже по другому написал эту функцию, но это не делает Вашу программу корявой.
 - int8_t caliber_to_ppm(uint8_t caliber) { int8_t result = caliber & MASK_CALIBR; return (caliber & MASK_CALIBR_SIGN) ? -(result*2):(result*4); }
 Просто потому, что так сразу видно:
 Если знак есть то умножаем на 2 (сдвигаем биты) и ставим знак минус, если нет то умножаем на 4 (сдвигаем биты).
  - GarryC29.06.2019 01:04- Простите, если обидел, я как раз имел в виду умножения вместо сдвига. Всегда следует ясно указывать, что мы делаем, а тут мы сдвигаем. Да и умножением не все так просто, лучше его здесь не использовать. Речь только об этом шла, не сердитесь. 
 
 
 
 
 
 
           
 
FDA847
Получается, что отличие от DS'ки только в наличии возможности подстройки хода? Есть ещё классая микросхема DS3231. Там встроенный калиброванный генератор! Но стоит она почти на порядок дороже DS1307.
u_235 Автор
Подстройка хода — это самое существенное отличие, ради которого и стоит применять M41T56.
А у DS3231еще и температурная компенсация есть.
assad77
сейчас ds3231 использую только эту микросхему. ds1307 вообще никакая. за день на полминуты может уходить. а с этой микросхемой как?
moviq
Я использовал 1302, наверное это такая же только с другим интерфейсом. И припаивал 2 кондюка к выводам для подключения кварца. Один из них подстроечный. В итоге получалось также где-то «отклонение не более чем ±5 секунд за месяц». Но скорее всего тут ещё влияет температура и один раз скорректировав подстроечником уход может смениться
u_235 Автор
RTC с внешним кварцем чувствительны к разводке дорожек и к подключению земли, в мануалах этому уделено особое внимание. Мне попадались кварцы с уходом в пару минут за месяц, но ошибка в минуту за сутки — это слишком много и либо компоненты негодные, либо ошибки разводки.
assad77
так я ардуино модулям пользовался и DIY конструктором, когда сравнивал и выбирал для своей самоделки таймеры.
DS3231 таких проблем не имел и уже в готовом решении я использовал DS3231.