Краткое описание
Я не буду останавливаться на работе шины 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)
AntonSazonov
27.06.2019 06:19Как вы ловко занимаетесь кастингом из uint8_t в int8_t и обратно.
Долго думал в чём там смысл… Пришёл к выводу что его там нет.GarryC
27.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Я согласен, что перемудрил с приведением типов, остальное дело вкуса. Кстати, ваш пример показывает, что даже мэтры делают глупые ошибки.
GarryC
28.06.2019 14:57На мой взгляд, нисколько не перемудрили, всегда лучше сдвигать без-знаковые типы:
1) не будет неопределенного поведения и
2) это часто быстрее на некоторых МК, я по этому поводу пост писал.
А что за глупая ошибка?u_235 Автор
28.06.2019 16:42-1Да, я читал эту статью о сдвигах и багах AVR-GCC и это было одной из причин, по которой я использовал умножение и деление вместо сдвигов. Вторая причина — КМК это в данном случае наглядней.
Ошибка в раскрытии макроса MASK_CALIBR, в котором вы забыли круглые скобки.
Теперь я совсем перестал понимать, в чем корявость программы.assad77
28.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 (сдвигаем биты).
GarryC
29.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.