RTC на STM8L_discovery

Сделал небольшой проект с использованием модуля RTC на 8L_Discovery. Написано на экологичном асме, но вроде более-менее понятно. Надеюсь, кому-то пригодится

Часы реального времени (RTC) представляют собой независимый таймер/счетчик BCD. Имеется часы времени, календарь и ассоциативный программируемый будильник. Также включают в себя возможность авто пробуждения для использования в режимах низкого энергопотребления.
Блок-схема из RM0031:

8-битные регистры содержат секунды, минуты, часы (12- или 24-часовой формат), день(день недели), число (день месяца), месяц, год в формате BCD. Поддержка 28-, 29- (високосный год), 30- и 31-дней месяца производится автоматически.
Соответствующие 8-битные регистры содержат секунды, минуты, часы, день и дату программируемого будильника.

Источник тактирования

В качестве источника тактирования может быть выбран: HSE, LSE, HSI, LSI. Выбираем LSE, благо он есть на плате Discovery. После выбора источника необходимо подождать, пока он войдет в стационарный режим, а затем включить собственно тактирование RTC:

Wait_RTC_CLK
    btjt     CLK_CRTCR,#RTCSWBSY,Wait_RTC_CLK
    bset     CLK_PCKENR2,#PCKEN22  ; Тактирование RTC включено
    ret
 

Частота системного источника тактирования fSYSCLK должна быть равна или больше fRTCCLK.
Если частота системного тактирования SYSCLK равна частоте низкоскоростного источника тактирования (LSE или LSI), пользователь должен использовать тот же источник как RTCCLK и должен установить бит RATIO регистра RTC_CR1 для дезактивации механизма синхронизации. В таких условиях флаг синхронизации RSF не используется.
Удобно, что при выборе LSE как источника тактирования RTC этот генератор стартует автоматически, включать его не надо.
После установки источника тактирования можем настроить предделители. Их тут два: синхронный и асинхронный.Асинхронный предделитель по умолчанию установлен на коеф. 128, а синхронный предделитель на 256, для получения внутреннего тактового сигнала ck_spre = 1Гц при генераторе LSE с частотой 32768Гц. Я так понимаю, путем установки ck_spre>1Гц можно разогнать часы:)
Но! Дело в том, что по умолчанию регистры RTC защищены от записи (за исключением RTC_ISR2, который содержит флаги будильника таймера авто пробуждения). Запись в регистры RTC разрешается после записи ключа в регистр RTC_WPR:

    mov      RTC_WPR,#$CA
    mov      RTC_WPR,#$53

Разблокируем регистры один раз, в дальнейшем они доступны и без ключа.

Процедура инициализации

Для инициализации значений времени и даты, а также предделителей, должна быть выполнена следующая последовательность действий:
1. Установить бит INIT регистра RTC_ISR для входа в режим инициализации. В этом режиме календарь останавливается и его значение может быть обновлено.
2. Проверка бита INITF регистра RTC_ISR. При выполнении входа в режим инициализации этот бит устанавливается в 1. Это занимает около двух циклов RTCCLK.
3. Установка значения предделителя RTC_PRER для генерации сигнала частотой 1Гц
4. Загрузка значений времени и даты в теневые регистры RTC_TR и RTC_DR, и конфигурация временного формата (12- или 24-часовой) битом FMT регистра RTC_CR.
5. Выход из режима инициализации путем записи '0' в бит INIT регистра RTCCLK. Данные будут автоматически загружены, а счет перезапущен после 4 циклов RTCCLK.
Я все это реализовал следующим образом:

RTC_Init
    ; Разблокировка регистров RTC
    mov      RTC_WPR,#$CA
    mov      RTC_WPR,#$53
    ; Инициализация RTC
    bset     RTC_ISR1,#INIT
; Ожидание входа в режим инициализации
Wait_Init_mode
    btjf     RTC_ISR1,#INITF,Wait_Init_mode
    ; Установка асинхронного предделителя (128 по умолчанию, RTCCLK=LSE)
    mov      RTC_APRER,#$7F
    ; Установка синхронного предделителя  (256 по умолчанию, RTCCLK=LSE)
    mov      RTC_SPRERH,#$00
    mov      RTC_SPRERL,#$FF
    ; Настройка таймера автопробуждения
    bres     RTC_CR2,#WUTE
; Ожидание входа в режим настройки таймера автопробуждения
Wait_AW
    btjf     RTC_ISR1,#WUTWF,Wait_AW
    mov      RTC_WUTRH,#%00000000 
    mov      RTC_WUTRL,#%00101001 ; Период - примерно 5мс (RTC_WUTR=41)
    mov      RTC_CR1,#%00000010   ; Источник тактирования таймера - RTCCLK/4=LSE/4=8192Гц
    bset     RTC_CR2,#WUTE  ; Включение таймера автопробуждения
    bset     RTC_CR2,#WUTIE ; Включение прерываний по таймеру автопробуждения
    ; Установка секунд
    mov      RTC_TR1,RTC_seconds
    ; Установка минут
    mov      RTC_TR2,RTC_minutes
    ; Установка часа
    mov      RTC_TR3,RTC_hours
    ; Установка числа
    mov      RTC_DR1,#%00100000
    ; Установка дня недели и месяца
    mov      RTC_DR2,#%00100000
    ; Установка года
    mov      RTC_DR3,#%00010010
    ; Выход из режима инициализации
    bres     RTC_ISR1,#INIT
    ret


Тут также надо следить, чтобы день недели и число месяца не были нулевыми, хотя и в таком случае часы запускаются.

Таймер автопробуждения

В этом же куске кода настраивается таймер автопробуждения, у которого есть прервание. Таймер декрементный, по достижению нуля устанавливается флажок WUTF в регистре RTC_ISR2. Флажок этот надо чистить ручками.
Для настройки этого таймера его вначале надо отключить(RTC_CR2,#WUTE=>0), потом подождать, пока он войдет в режим инициализации (RTC_ISR1,#WUTWF=>1), и только затем устанавливать предделители. Источником тактирования этого таймера может быть как ck_spre = 1Гц, так и RTCCLK (тут также можно задействовать предделитель, в регистре RTC_CR1). Первый вариант можно использовать, если необходимо просто обновлять время каждую секунду. Во втором случае в прерывание по этому таймеру можно накидать кучу полезных программных счетчиков, например для опроса клавиатуры.
Включается таймер установкой бита WUTE регистра RTC_CR2, прерывание разрешается битом WUTIE. Значение регистров WUTRH:WUTRL перезагружается автоматически.

Чтение/запись регистров календаря

Для чтения теневых регистров календаря необходимо удостоверится, что бит RSF регистра RTC_ISR установлен, а устанавливается он каждый раз после копирования регистров календаря в теневые регистры.
Чтение теневых регистров следует производить начиная от RTC_TR1 и заканчивая RTC_DR3. Надо прочитать ВСЕ регистры, так как на время процедуры чтения копирование обновление теневых регистров замораживается! Если например, прочитать только минуты и часы, RTC фактически зависнет.
Для изменения значения времени и даты «по ходу дела» можно использовать короткую подпрограммку:

RTC_Set_Calendar
    bset     RTC_ISR1,#INIT
; Ожидание входа в режим инициализации
Wait_Init_mode_2
    btjf     RTC_ISR1,#INITF,Wait_Init_mode_2
    ; Установка секунд
    mov      RTC_TR1,RTC_seconds
    ; Установка минут
    mov      RTC_TR2,RTC_minutes
    ; Установка часа
    mov      RTC_TR3,RTC_hours
    bres     RTC_ISR1,#INIT
    ret


Рабочий проект на асме прилагается в архиве. Удержание клавиши user дольше 1 секунды переводит часы в режим установки, кратковременное нажатие инкременирует значение времени. Автоповтор не допилил:)
Файлы в топике: RTC_work_2.tar

Комментарии (64)

RSS свернуть / развернуть
Да, асм — он такой асм :) Ничего не хотел сказать плохого. Но осилить его для чего-то более-меннее сложного я себя заставить так и не могу :)

Brunnen-G , любите Lexx? ;)
+1
LEXX, да! Адовая штука из детства!
0
Я вроде понимаю, что проект не оч. сложный и большой. Но почему именно АСМ? Интереса ради, не во благо спора спрашиваю-)
+1
Спасибо за статью. Думаю и в публичный блог можно скинуть.

Вопрос, как снять блокировку записи вы описали, а как её потом обратно установить? Ведь не просто так она ставится, а во избежание искажения данных во время сбоя. А если кто считает/запишет не по своему адресу, на удивление попавшему на область РТЦ — и всё, часы у нас стали. Хотя да, защита от записи не защитит от кривого чтения…
0
Собственно, кроме снятия защиты надо еще войти в режим инициализации, что тоже своего рода защита. А вообще, в даташите есть примечание: запись неверного ключа перезапускает защиту от записи. То есть, если записать в RTC_WPR левое значение, защита должна включится, но я не проверял
0
Защита отключается насовсем, или только до выключения режима инициализации?
0
Насовсем
0
Я с асма начинал программировать (PIC16, между прочем), поэтому он мне ближе. Собственно, на си я тоже пишу, по работе. Но меня постоянно терзает мысль, что сишный компилер че-то туда кидает, а я не знаю что именно
0
Си библиотеки он туда кидает :) Стартап код (инициализация переменных, вызов основной функции), обработчики прерываний по умолчанию, работу с длинными числами/флоэтами.
В целом вы можете написать и свою библиотеку на асме и подключить её вместо стндартной. А увидеть что закинул компилер можете в дизасме/листинге.
0
Ну, рано или поздно все равно перейду на сишку, а пока изучаю, буду писать на асме.
0
Кто-то пробовал заливать на STM8L-Discovery? Интересуюсь, потому как у меня вроде спешат. Смущает кварц в пластике
0
Ага, за 6 минут работы на 30 секунд вперед ускакали.
ЗЫ:
1.Знакогенерация у единички не оч вышла, имхо: хвостик весь вид портит, в глазах все мерещится. Просто палкой было бы привычней
2. Выпадение меню по долгому нажатию кнопки обычно (и я в т.ч) не по отпусканию делают, а по просто по истечению времени. А то не знаешь уже пора отпускать тебе или еще рано — на дисплее ничего не меняется. Не настаиваю, просто пожелание
3.
Автоповтор не допилил:)

А как бы он работал на единственной кнопке, где уже задействована функция по долгому нажатию?
0
1. Может и так, все равно подпрограмму работы с LCD надо на корню переделать, слишком топорная
2. ок, дельное примечание
3. Ну, например после еще более длительного удержания, например 2сек (тем более, если исправить пункт 2), изменить состояние автомата на автоповтор, и все. Хотя это все таки танцы с бубном, я эти часы планирую сделать в виде реального устройства, и кнопок приделать сколько надо
0
После устранения ошибки (mov RTC_APRER,#$F7=>mov RTC_APRER,#$7F ) вроде стали нормально тикать, так что это моя обшибка
0
Асм — не лучшая штука для подобных статей. Хотя, невелика разница. Но если уж ты освоил асм — напиши статейку про то, как устроено ядро STM8. А то до сих пор никто не удосужился, на этом ресурсе, по крайней мере.

А как эти RTC дружат с бэкап-батарейкой?
0
  • avatar
  • Vga
  • 06 марта 2012, 10:43
Регистры инициализировать что на асме, что на сишке. А батарейки конкретно для RTC нету, да и зачем? В STM8l полно энергосберегающих режимов
0
отдельный вывод для батарейки куда удобнее развязки питания на переферию и мк. Переферия то не всегда имеет режим энергосбережения, да и переклюение в данный режим может потребовать некоторое количество времени, в тчение которого вполне возмоджно что работа будет идти от батареи.
Вообщем ясно, что для таких ситуаций лучше использовать отдельные часы с бекап батарейкой.
+1
Ситуация такая: есть контроллер с встроенным RTC. И сдается мне, что прикручивать к такому контроллеру внешний RTC далеко не лучше:)
0
Ну а если я на нем часы собрать хочу с таким индикатором, который резервную батарейку высадит в ноль прежде чем МК поймет что внешнее питание кончилось? Потребуется всякие развязки вне МК городить и вообще, что мне тогда RTC дает? Время и программно посчитать несложно.
+1
Собственно, что вы хотите от меня? У меня отладочная плата с ЖК дисплеем, встроенный RTC, и бэкап совершенно не нужен. Если у вас какие-то свои нъюансы, вам возможно и нужен внешний RTC. Ну а я то тут при чем?
0
Я проясняю интересующие меня вопросы — в частности, зачем этот RTC вообще нужен и как присобачить к нему резервную батарейку.
Я так понимаю, примерно такого рода вопросы и ожидаются в обсуждении, нэ?
0
Зачем этот RTC вообще нужен? Полагаю, человек, решивший почитать «RTC на STM8L_discovery» изначально осведомлен, зачем нужен RTC. Я то здесь попытался показать пример, как завести этот самый RTC на конкретной отладочной плате
0
Ну, в таком случае у меня вопросов больше нет.
P.S. Статью стоит перекинуть в блог STM8.
0
Не нервничайте, статья нормальная, но вопрос Vga в тему. В реальности RTC без отдельного питания не имеет смысла вообще, так как программно делается на раз. Сам сталкивался с проблемами бэкапа (правда на AVR), когда не получается развязать МК по питанию, особенно если задействован АЦП и AVCC. Такие танцы с бубнами выходят, что в итоге удалось решить только двумя внешними полевиками с обвязом.

Ни что не мешает открыть даташит и прочитать, как там с этим дело обстоит, но рас уж вы разбирались с RTC, логично предположить, что знаете это, а возможно и испытывали. Если нет — так и скажите, «не знаю, не в курсе»…
+2
Именно это я и хотел сказать.
Кстати, STM32 имеют отдельное питание RTC, AFAIK. Учитывая некоторую родственность по периферии между этими семействами — логично было спросить и про его наличие в STM8.
0
Да, у RTC в STM32 есть отдельное питание и проблем с развязкой, вобщем, нет.
0
Не совсем. У STM32L1xx серии тоже нет возможности подключения батарейки. Они (32L и 8L) даже на сайте выделены в общую группу (Ultra-low-power MCUs) в разделе Microcontrolles.

L-серия рассчитана на то, что она всегда будет запитана от этой самой батарейки и вторая батарейка для РТС и SRAM попросту будет лишней.

Во время отладки только не удобно будет постоянно забивать заново время при включении устройства, лучше будет довесить батарейку через диод.
0
В таком случае:
1) Есть RTC в STM8S?
2) Если да, то бэкап-батарейка поддерживается?
P.S. Вот и причина не лепить 8L везде, как предлагает dcoder, а только туда, где действительно нужны их фишки (потребление, ЖК, etc).
0
Не понял, кому адресован вопрос, отвечаю потому как до понедельника я в оффлайне
1)Не знаю, 8L — мое первое знакомство с ST
2)
P.S.:) Все-таки, RTC — даже без бэк-апа, тоже фишка, но для друхих задач(не для ваших, видимо)
0
Например, для себя: хочу сделать часы на STM8L+SHT21;
, по работе: контроллер с RTC, LCD сегментный, причем RTC синхронизируются с UTC от GPS модуля, бэкап есть в этом самом модуле. Так-что, для таких задач, я думаю, бэкап не особо то и нужен
0
И, конечно, время можно считать программно, но если есть контроллер со встроенным модулем RTC (тем более, такой перспективный как STM), то было бы глупо его не использовать. Тут некая аналогия с бипером на том же STM — вроде и без него не проблема, но когда он есть, это приятно и даже забавно:)
0
Есть RTC в STM8S?
нет
Вот и причина не лепить 8L везде, как предлагает dcoder, а только туда, где действительно нужны их фишки
только из-за того, что нельзя запитаться альтернативно от батарейки? )))
0
В том числе и поэтому)
0
Кстати, раз уж так интересует RTC, могу написать о ИМС от Интерсила (по Даласовским RTC инфы полно), мне они RTC прислали сэмплом. Если интересно, отпишитесь
0
Я, вобщем-то, ответил выше: бэкапа для RTC нету
0
Збавно, когда писал эту статью, руководствовался только тем, что подобных нету. А тут вылезло насчет бэкапа:) Век живи, век учись
0
Ну не скажите. Работа с переферией сводится в основном работе с её регистрами. а что, как ни асм, способно это отобразить?
Как устроено ядро найболее интересно для асма, для си оно практически скрыто. А на мой взгляд, тот кто считает себя джедаем (ну или падаваном) асма, способен изучить и по английской доке. Ну а если не способен, так и нехрена выпендриваться — пишите на си :)
0
Совершенно с вами согласен. Мне кажется, осваивать архитектуру лучше всего на асме, это позволяет максимально прочуствовать ньюансы. А именно работать, писать сложные проекты — тут уже си незаменим
0
Архитектуру ядра — да. Для периферии это неважно, но, как я уже сказал, в куске кода Wait_Init_mode..Wait_AW я лишь интуитивно понимаю, что происходит. Тогда как на С это понятно всем, кто его знает в объемах «С за полчаса».
0
Ну не скажите. Работа с переферией сводится в основном работе с её регистрами. а что, как ни асм, способно это отобразить?
Практически без разницы, но на С чуть меньше не относящегося к делу кода. К тому же, вооон там нечто между метками Wait_Init_mode и Wait_AW. Как ты думаешь, насколько мне понятен код между ними, если об ассемблере STM8 я знаю только то, что он существует? Тогда как С более-менее общий для всех платформ и легко изучается в минимальном объеме.
Как устроено ядро найболее интересно для асма, для си оно практически скрыто.
Именно поэтому я и предлагаю ассемблерщикам о нем написать.
А на мой взгляд, тот кто считает себя джедаем (ну или падаваном) асма, способен изучить и по английской доке.
Это не взаимосвязано. Ассемблер не сложнее С, скорее наоборот.
0
btjf RTC_ISR1,#INITF,Wait_Init_mode — вот это?
Эсли бит INITF регистра RTC_ISR1 сброшен(false), переходим на метку Wait_Init_mode. То есть, ждем пока этот бит установится, что в данном случае означает вход в режим инициализации.
0
Я-то догадаюсь. Но подобные примеры, тем не менее, стоит приводить на чем-нить более стандартном, чем ассемблер.
0
Для контроллера нет ничего более стандартного, чем его родной ассемблер. Кроме того, написал я асме, поэтому и привел на асме
0
Ассемблер контроллеро-специфичен, к тому же, в нынешних реалиях С его активно вытесняет как основной язык для встроенной разработки. Тем более на STM8, где много памяти и (говорят) несколько нечеловеческий ассемблер, оптимизированный под компиляцию в него С. И в целом, С знает большее число людей, чем ассемблер конкретного ядра.
И кстати, я даже не видел ни одной статьи по структуре ядра STM8 и его ассемблеру. Ну и как в таких условиях читать статьи с кодом на асме?
0
Ну тогда правильно будет написать на «абстрактном алгоритмическом языке», потому как и Си не всем понятен.
Код написан вполне понятно, с комментариями, с говорящими названиями. кроме того дока по асму доступна от производителя, что какая команд делает можно и там прочитать (если уж русские комментарии не устраивают).
Вообщем мой вердикт — притензии по поводу применения асма не обоснованные. Пожелание по поводу Си высказали, и пожалуй хватит.
0
Ну это и есть пожелание, только оно традиционно развернулось в приличных размеров обсуждение. Сорри.
0
Да ладно, Vga , должны же быть примеры кода под СТМ8 и на асме. Автору плюс за асм и за желание познать ядро СТМ8, лично мне было интересно посмотреть код
+1
Думаю, в будущем надо будет выкладывать код и на асме, и на си
0
Довольно трудоемкое занятие. Я недавно решил подготовить несколько статеек. 2 версии Си кода ещё можно сделать, но вот от асм версии всё-же отказался.
В прочем это я, а то Вы :)
0
Собственно, сегодня наконец-то установил компилер от ренесаса, поэтому могу код на асме перегнать на сишку и испробовать
0
Фу, пардон, я не в адеквате, от Raisonance компилятор
0
Кстати, если вы пишете на си, подскажите: если я зарегил этот компилер с компа на работе, для домашнего мне придется все заново делать (дома инета нет)?
0
Предлагаю завязать с обсуждением преимуществ асма и си, а то где-то я это уже видел ;)
+2
:)
0
Нда, писать видимо больше нечего
0
Да нет, это я о своем улыбнулся. Не хочу холиварить.
0
Да я о том, что все замолчали
0
Лично я жду ответа.
0
Опечатку исправил: mov RTC_APRER,#$F7 mov RTC_APRER,#$7F
0
Между прочем, никто так и не спросил, как завести на этом контроллере аларм. Если интересно, отпишитесь, я пока этим не занимался, но светит.
0
а не пробовал вывести частоту 1Гц (512Гц) на выход?
в STM8L152С6, по Datasheet RTC_CALIB может выводиться на PD3 или на PD6, но где переключение между ними я так и не нашел, пробовал инициализировать стандартными библиотечными функциями — сигнала нет ни на PD6, ни на PD3
0
а не пробовал вывести частоту 1Гц (512Гц) на выход RTC_CALIB
у меня на STM8L152R6 не получается, я и на форуме писал, но никто похоже не пробовал
про цифровую калибровку RTC тоже никто не упоминает :(
0
Не, не пробовал. Цифровая калибровка вроде в medium density отсутствует, так что я даже не обращал внимания
0
да вроде отсутствует, извини за назойливость (не заметил твоего ответа)
0
Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.