RTC HAL stm32
![](http://istarik.ru/uploads/images/00/00/01/2019/02/26/d51a3a.png)
Речь пойдёт о программировании RTC (встроенных часов) в микроконтроллере stm32.
Описание сделано для F103 и F303, но так как у них много общих функций, то читать нужно всё.
Первым делом нужно указать источник тактирования для часов. Указываем внешний кварцевый резонатор, он есть на многих платах…
![](http://istarik.ru/uploads/images/00/00/01/2018/10/12/1964ab.png)
В CubeMX выбираем
![](http://istarik.ru/uploads/images/00/00/01/2019/02/20/17c38a.jpg)
В мультиплексоре RTC Clock Mux нужно указать источник LSE…
![](http://istarik.ru/uploads/images/00/00/01/2018/10/14/9141e8.png)
Если внешнего кварца нет, тогда в мультиплексоре укажите LSI, а Low Speed External (LSE) ⇨ Disable.
Переходим в раздел
Для F103
![](http://istarik.ru/uploads/images/00/00/01/2019/02/20/c31653.jpg)
Со временем и календарём всё понятно. Формат 24-х часовой.
Для F303
![](http://istarik.ru/uploads/images/00/00/01/2019/02/20/d7d1d3.jpg)
Здесь два предделителя для настройки частоты —
Если у Вас LSI 40kHz, тогда во втором предделителе укажите 311. Если частота другая, тогда смотрите ниже.
Настройка предделителей для разных источников тактирования…
![](http://istarik.ru/uploads/images/00/00/01/2019/02/20/3c38f8.jpg)
У нас тактируется от LSE = 32.768кГц, тогда исходя из формулы получается следующее: 128 * 256 = 32768 / 32.768кГц = 1Гц (один тик в секунду). Если уменьшить или увеличить какое-нибудь значение, то часы пойдут быстрее или медленнее.
Пишем код. В функции
/* USER CODE BEGIN PV */
RTC_TimeTypeDef sTime = {0};
RTC_DateTypeDef DateToUpdate = {0};
char trans_str[64] = {0,};
/* USER CODE END PV */
И заодно объявим массив для вывода данных в UART.
У F303 структура даты называется sDate.
В бесконечном цикле будем читать дату и время:
/* USER CODE BEGIN WHILE */
while (1)
{
HAL_RTC_GetTime(&hrtc, &sTime, RTC_FORMAT_BIN); // RTC_FORMAT_BIN , RTC_FORMAT_BCD
snprintf(trans_str, 63, "Time %d:%d:%d\n", sTime.Hours, sTime.Minutes, sTime.Seconds);
HAL_UART_Transmit(&huart1, (uint8_t*)trans_str, strlen(trans_str), 1000);
HAL_RTC_GetDate(&hrtc, &DateToUpdate, RTC_FORMAT_BIN);
snprintf(trans_str, 63, "Date %d-%d-20%d\n", DateToUpdate.Date, DateToUpdate.Month, DateToUpdate.Year);
HAL_UART_Transmit(&huart1, (uint8_t*)trans_str, strlen(trans_str), 1000);
HAL_Delay(1000);
...
![](http://istarik.ru/uploads/images/00/00/01/2019/02/20/843ee2.png)
Если на пин
/**Initialize RTC and set the Time and Date */
sTime.Hours = 10;
sTime.Minutes = 34;
sTime.Seconds = 0;
sTime.DayLightSaving = RTC_DAYLIGHTSAVING_NONE;
sTime.StoreOperation = RTC_STOREOPERATION_RESET;
//if (HAL_RTC_SetTime(&hrtc, &sTime, RTC_FORMAT_BIN) != HAL_OK)
//{
// Error_Handler();
//}
DateToUpdate.WeekDay = RTC_WEEKDAY_WEDNESDAY;
DateToUpdate.Month = RTC_MONTH_FEBRUARY;
DateToUpdate.Date = 20;
DateToUpdate.Year = 19;
//if (HAL_RTC_SetDate(&hrtc, &DateToUpdate, RTC_FORMAT_BIN) != HAL_OK)
//{
// Error_Handler();
//}
Эти же функции можно использовать где-нибудь в программе для изменения времени/даты на лету.
Теперь можно прошить ещё раз и понажимать ресет. Данные должны сохраняться.
У микроконтроллера F103, дата не сохраняется. Это связано с тем, что F103 всего один 32-х битный регистр, см. спойлер…
спойлер
Вот так выглядит схема RTC в F103…
![](//istarik.ru/uploads/images/00/00/01/2020/01/10/be6a51.jpg)
От батарейки работает только регистр со временем и будильником, ну и ещё предделитель. То есть дату сохранить нельзя.
Но, дату сохранить нельзя только если пользоваться HAL, если же написать свой костыль, тогда в RTC_CNT можно сохранять дату/время в UNIX-формате, то есть количество секунд прошедшее с 1970 года. А потом средствами СИ вытаскивать из этого числа дату и время.
![](http://istarik.ru/uploads/images/00/00/01/2020/01/10/be6a51.jpg)
От батарейки работает только регистр со временем и будильником, ну и ещё предделитель. То есть дату сохранить нельзя.
Но, дату сохранить нельзя только если пользоваться HAL, если же написать свой костыль, тогда в RTC_CNT можно сохранять дату/время в UNIX-формате, то есть количество секунд прошедшее с 1970 года. А потом средствами СИ вытаскивать из этого числа дату и время.
У более «жирных» камней сохраняется и дата и время.
Если используется LSI, то данные сохранятся, но время идти не будет.
Если у вас микроконтроллер F4xx или F7xx, и вы хотите считывать только время (без даты), то в любом случае нужно после функции
Будильник (Alarm) для F103
Настраиваем…
![](http://istarik.ru/uploads/images/00/00/01/2019/02/20/0ca07d.jpg)
Будильник сработает через пять секунд после старта.
Можно сгенерировать проект, прошить и посмотреть как мигнёт светодиод.
После того как попробуете эти режимы верните всё как на картинке.
Включите прерывание от будильника…
![](http://istarik.ru/uploads/images/00/00/01/2019/02/21/4bf884.jpg)
Будильник соединён с линией EXTI17 – RTC Alert event.
Добавьте колбек будильника:
/* USER CODE BEGIN 0 */
void HAL_RTC_AlarmAEventCallback(RTC_HandleTypeDef *hrtc)
{
snprintf(trans_str, 63, "ALARM\n");
HAL_UART_Transmit(&huart1, (uint8_t*)trans_str, strlen(trans_str), 1000);
}
Прошивайте и смотрите результат.
Чтобы посмотреть настройки будильника из программы, нужно вызвать функцию
пример
Структуру будильника объявим как глобальную:
Для программной установки будильника нужно воспользоваться функциейHAL_RTC_SetAlarm_IT() , она есть в функции инициализации — static void MX_RTC_Init(void) .
/* USER CODE BEGIN PV */
RTC_TimeTypeDef sTime = {0};
RTC_DateTypeDef DateToUpdate = {0};
RTC_AlarmTypeDef sAlarm = {0}; // структура будильника
char trans_str[64] = {0,};
/* USER CODE END PV */
/* USER CODE BEGIN WHILE */
while (1)
{
HAL_RTC_GetTime(&hrtc, &sTime, RTC_FORMAT_BIN); // RTC_FORMAT_BIN , RTC_FORMAT_BCD
snprintf(trans_str, 63, "Time %d:%d:%d\n", sTime.Hours, sTime.Minutes, sTime.Seconds);
HAL_UART_Transmit(&huart1, (uint8_t*)trans_str, strlen(trans_str), 1000);
HAL_RTC_GetDate(&hrtc, &DateToUpdate, RTC_FORMAT_BIN);
snprintf(trans_str, 63, "Date %d-%d-20%d\n", DateToUpdate.Date, DateToUpdate.Month, DateToUpdate.Year);
HAL_UART_Transmit(&huart1, (uint8_t*)trans_str, strlen(trans_str), 1000);
HAL_RTC_GetAlarm(&hrtc, &sAlarm, RTC_ALARM_A, RTC_FORMAT_BIN);
snprintf(trans_str, 63, "Alarm %d:%d:%d\n", sAlarm.AlarmTime.Hours, sAlarm.AlarmTime.Minutes, sAlarm.AlarmTime.Seconds);
HAL_UART_Transmit(&huart1, (uint8_t*)trans_str, strlen(trans_str), 1000);
HAL_Delay(1000);
...
Для программной установки будильника нужно воспользоваться функцией
Помимо прерывания от будильника, есть ещё прерывание, которое может вызываться раз в секунду.
Включите глобальное прерывание…
![](http://istarik.ru/uploads/images/00/00/01/2019/02/21/7b6b9b.jpg)
Добавьте ещё один колбек:
/* USER CODE BEGIN 0 */
void HAL_RTCEx_RTCEventCallback(RTC_HandleTypeDef *hrtc)
{
snprintf(trans_str, 63, "One sec\n");
HAL_UART_Transmit(&huart1, (uint8_t*)trans_str, strlen(trans_str), 1000);
}
Перед бесконечным циклом добавьте функцию:
/* USER CODE BEGIN 2 */
HAL_RTCEx_SetSecond_IT(&hrtc);
/* USER CODE END 2 */
Прошейте и смотрите.
Как использовать этот функционал — например можно сделать так: в колбеке будильника запускаем это прерывание, после чего оно вызовется 10 раз и выключится. В прерывании можно делать что угодно, например подавать импульс на какой-нибудь пин с подключённой пищалкой.
пример
/* USER CODE BEGIN PV */
RTC_TimeTypeDef sTime = {0};
RTC_DateTypeDef DateToUpdate = {0};
RTC_AlarmTypeDef sAlarm = {0};
char trans_str[64] = {0,};
volatile uint8_t count = 0; // добавить счётчик
/* USER CODE END PV */
/* USER CODE BEGIN 0 */
void HAL_RTCEx_RTCEventCallback(RTC_HandleTypeDef *hrtc)
{
// тут подаём импульс на какой-нибудь пин
count++;
if(count > 9) HAL_RTCEx_DeactivateSecond(hrtc); // отключаем ежесекундное прерывание
snprintf(trans_str, 63, "One sec\n");
HAL_UART_Transmit(&huart1, (uint8_t*)trans_str, strlen(trans_str), 1000);
}
void HAL_RTC_AlarmAEventCallback(RTC_HandleTypeDef *hrtc)
{
snprintf(trans_str, 63, "ALARM\n");
HAL_UART_Transmit(&huart1, (uint8_t*)trans_str, strlen(trans_str), 1000);
HAL_RTCEx_SetSecond_IT(hrtc); // запускаем ежесекундное прерывание
}
/* USER CODE END 0 */
/* USER CODE BEGIN 2 */
//HAL_RTCEx_SetSecond_IT(&hrtc);
/* USER CODE END 2 */
Если установить
![](http://istarik.ru/uploads/images/00/00/01/2019/02/21/b90573.jpg)
… то режимы
Tamper для F103 и F303
Активируйте Tamper…
![](http://istarik.ru/uploads/images/00/00/01/2019/02/21/4efc1c.jpg)
В RTC OUT указывайте что хотите. Calendar можно включить, а можно и не включать.
До этого мы использовали tamper-пин для вывода сигнала, а сейчас он будет выполнять обратную функцию.
У F103 есть десять 16-ти битных регистров для хранения пользовательских данных (backup registers). Если подключена батарейка, то данные в этих регистрах не обнуляются ни при нажатии Reset, ни при выходе из спящего режима, ни при отключении основного питания.
Если в эти регистры записать какие-то данные, то их можно будет стереть подав на tamper-пин кратковременный импульс.
Какой именно сигнал послужит триггером, настраивается в пункте
Укажите
Внутренняя подтяжка такая слабенькая, что срабатывает от прикосновения пальца, поэтому желательно подтянуть пин к «плюсу» резистором (10КОм).
Запишем в первые два регистра данные:
/* USER CODE BEGIN 2 */
HAL_RTCEx_BKUPWrite(&hrtc, RTC_BKP_DR1, 1234); // в первый регистр запишем число 1234
HAL_RTCEx_BKUPWrite(&hrtc, RTC_BKP_DR2, 5678); // во второй регистр запишем число 5678
/* USER CODE END 2 */
В бесконечном цикле читаем эти данные:
/* USER CODE BEGIN WHILE */
while (1)
{
uint16_t reg_1 = HAL_RTCEx_BKUPRead(&hrtc, RTC_BKP_DR1);
uint16_t reg_2 = HAL_RTCEx_BKUPRead(&hrtc, RTC_BKP_DR2);
snprintf(trans_str, 63, "Reg_1 %d Reg_2 %d\n", reg_1, reg_2);
HAL_UART_Transmit(&huart1, (uint8_t*)trans_str, strlen(trans_str), 1000);
HAL_Delay(1000);
...
Прошейте эту программу и коротните пин на «землю» — данные обнулятся.
Теперь если нажать Reset, то по идее данные должны будут записаться заново, но этого не случится. Дело в том, что после подачи сигнала запись в эти регистры будет запрещена. Чтобы восстановить возможность записи нужно полностью обесточить плату (батарейку тоже нужно отключить).
Помимо обнуления регистров этот сигнал может вызывать прерывание…
![](http://istarik.ru/uploads/images/00/00/01/2019/02/21/a7c600.jpg)
В программе нужно добавить только колбек:
/* USER CODE BEGIN 0 */
void HAL_RTCEx_Tamper1EventCallback(RTC_HandleTypeDef *hrtc)
{
snprintf(trans_str, 63, "Tamper\n");
HAL_UART_Transmit(&huart1, (uint8_t*)trans_str, strlen(trans_str), 1000);
}
Если включено прерывание, то при нажатии Reset регистры с данными
Для работы без прерываний можно воспользоваться функцией ожидания сигнала.
пример
Структуру тампера объявляем глобально:
В бесконечном цикле делаем так:
Опять же, при нажатии Reset регистры с данными будут перезаписываться.
/* USER CODE BEGIN PV */
RTC_TimeTypeDef sTime = {0};
RTC_DateTypeDef DateToUpdate = {0};
RTC_AlarmTypeDef sAlarm = {0};
RTC_TamperTypeDef sTamper = {0}; // структура тампера
char trans_str[64] = {0,};
/* USER CODE END PV */
В бесконечном цикле делаем так:
/* USER CODE BEGIN WHILE */
while (1)
{
static uint16_t count = 0; // просто счётчик для наглядности
uint16_t reg_1 = HAL_RTCEx_BKUPRead(&hrtc, RTC_BKP_DR1);
uint16_t reg_2 = HAL_RTCEx_BKUPRead(&hrtc, RTC_BKP_DR2);
snprintf(trans_str, 63, "Before Reg_1 %d Reg_2 %d\n", reg_1, reg_2);
HAL_UART_Transmit(&huart1, (uint8_t*)trans_str, strlen(trans_str), 1000);
snprintf(trans_str, 63, "Start %d Wait 10 sec...\n", count++);
HAL_UART_Transmit(&huart1, (uint8_t*)trans_str, strlen(trans_str), 1000);
HAL_RTCEx_SetTamper(&hrtc, &sTamper);
HAL_RTCEx_PollForTamper1Event(&hrtc, 10000); // ждём сигнала 10 сек.
reg_1 = HAL_RTCEx_BKUPRead(&hrtc, RTC_BKP_DR1);
reg_2 = HAL_RTCEx_BKUPRead(&hrtc, RTC_BKP_DR2);
snprintf(trans_str, 63, "After Reg_1 %d Reg_2 %d\n\n", reg_1, reg_2);
HAL_UART_Transmit(&huart1, (uint8_t*)trans_str, strlen(trans_str), 1000);
HAL_Delay(1000);
...
Опять же, при нажатии Reset регистры с данными будут перезаписываться.
У F303 15 пользовательских регистров и три tamper-пина.
Прерывания включаются так…
![](http://istarik.ru/uploads/images/00/00/01/2019/02/22/231661.jpg)
У каждого пина свой колбек:
void HAL_RTCEx_Tamper1EventCallback(RTC_HandleTypeDef *hrtc)
void HAL_RTCEx_Tamper2EventCallback(RTC_HandleTypeDef *hrtc)
void HAL_RTCEx_Tamper3EventCallback(RTC_HandleTypeDef *hrtc)
Всё остальное как у F103.
Я когда ковырялся с этим функционалом, время от времени возникало ощущение что что-то «глючит» (регистры то записываются, то не записываются, то обнуляются, то не обнуляются), но потом стало понятно что это всего лишь следствие неправильных действий. Это к тому, что нужно проявить терпение и разобраться.
Будильник (Alarm) для F303
У этого микроконтроллера два будильника А и В…
![](http://istarik.ru/uploads/images/00/00/01/2019/02/23/7df555.jpg)
У них есть два варианта настроек:
Сейчас укажите
Настройте всё как на картинке…
![](http://istarik.ru/uploads/images/00/00/01/2019/02/23/506864.jpg)
Время у нас установлено 10:34:00, а будильник сработает в 10:34:10.
Следующие пункты, это различные комбинации настроек времени/даты срабатывания будильника. Например пункт
Если активировать пункт
Если активировать пункт
Этих комбинаций достаточно много, поэтому надеюсь что вы разберётесь самостоятельно.
Alarm combinations
Активируйте прерывание от будильника…
![](http://istarik.ru/uploads/images/00/00/01/2019/02/23/da6647.jpg)
В код добавьте колбек:
/* USER CODE BEGIN 0 */
void HAL_RTC_AlarmAEventCallback(RTC_HandleTypeDef *hrtc)
{
snprintf(trans_str, 63, "Alarm_A\n");
HAL_UART_Transmit(&huart1, (uint8_t*)trans_str, strlen(trans_str), 1000);
}
Alarm B
У Alarm B свой колбек:
HAL_RTCEx_AlarmBEventCallback(RTC_HandleTypeDef *hrtc)
В бесконечном цикле будем выводить инфу:
/* USER CODE BEGIN WHILE */
while (1)
{
HAL_RTC_GetTime(&hrtc, &sTime, RTC_FORMAT_BIN); // RTC_FORMAT_BIN , RTC_FORMAT_BCD
snprintf(trans_str, 63, "Time %d:%d:%d\n", sTime.Hours, sTime.Minutes, sTime.Seconds);
//snprintf(trans_str, 63, "Time %d:%d:%d:%lu\n", sTime.Hours, sTime.Minutes, sTime.Seconds, sTime.SubSeconds);
HAL_UART_Transmit(&huart1, (uint8_t*)trans_str, strlen(trans_str), 1000);
HAL_RTC_GetDate(&hrtc, &DateToUpdate, RTC_FORMAT_BIN);
snprintf(trans_str, 63, "Date %d-%d-20%d\n", DateToUpdate.Date, DateToUpdate.Month, DateToUpdate.Year);
HAL_UART_Transmit(&huart1, (uint8_t*)trans_str, strlen(trans_str), 1000);
HAL_RTC_GetAlarm(&hrtc, &sAlarm, RTC_ALARM_A, RTC_FORMAT_BIN);
snprintf(trans_str, 63, "Alarm %d:%d:%d\n", sAlarm.AlarmTime.Hours, sAlarm.AlarmTime.Minutes, sAlarm.AlarmTime.Seconds);
HAL_UART_Transmit(&huart1, (uint8_t*)trans_str, strlen(trans_str), 1000);
HAL_Delay(1000);
...
Чтобы будильник подавал импульс на пин РС13, надо указать
![](http://istarik.ru/uploads/images/00/00/01/2019/02/23/66a3aa.jpg)
В настройках появятся два дополнительных пункта…
![](http://istarik.ru/uploads/images/00/00/01/2019/02/23/52da33.jpg)
Делайте как на картинке и не забудьте будильник настроить, он сбивается при изменении режима.
Подключите светодиод к пину РС13 и смотрите как он мигнёт во время срабатывания будильника.
WakeUp
WakeUp может выводить МК из спящего режима, вызывать прерывание и подавать сигнал на пин РС13.
![](http://istarik.ru/uploads/images/00/00/01/2019/02/24/18d8ef.jpg)
WakeUp это простой 16-ти битный (от 0 до 65535) счётчик. Тактирование можно настроить с помощью предделителей часового генератора.
Например если сделать так…
![](http://istarik.ru/uploads/images/00/00/01/2019/02/23/8fa4da.jpg)
Тогда счётчик будет увеличиваться со скоростью 2048 единиц в секунду и достигнет 10000 примерно через 5 секунд (32.768кГц / 16 = 2048, 10000 / 2048 = 4.88 сек). То есть WakeUp будет срабатывать каждые ~5 секунд.
Можно не заморачиваться с предделителями, а просто указать 1Hz…
![](http://istarik.ru/uploads/images/00/00/01/2019/02/23/7a41e9.jpg)
Счётчик будет увеличиваться со скоростью 1 единица в секунду и срабатывать через каждые 5 сек.
Таким образом можно настроить пробуждение МК на достаточно большой интервал. Например если указать 65000, то WakeUp будет срабатывать каждые 18 часов.
Активируйте прерывание…
![](http://istarik.ru/uploads/images/00/00/01/2019/02/23/7ddbf0.jpg)
Если включено прерывание, то на пин РС13 подаётся кратковременный импульс, а если отключено, то подаётся постоянный сигнал.
И добавьте соответствующий колбек:
/* USER CODE BEGIN 0 */
void HAL_RTCEx_WakeUpTimerEventCallback(RTC_HandleTypeDef *hrtc)
{
snprintf(trans_str, 63, "WakeUp\n");
HAL_UART_Transmit(&huart1, (uint8_t*)trans_str, strlen(trans_str), 1000);
}
Прошивайте и смотрите что получилось.
Посмотреть значение счётчика можно так:
uint32_t wu = HAL_RTCEx_GetWakeUpTimer(&hrtc);
snprintf(trans_str, 63, "WakeUp %lu\n\n", wu);
HAL_UART_Transmit(&huart1, (uint8_t*)trans_str, strlen(trans_str), 1000);
Отключить счётчик:
HAL_RTCEx_DeactivateWakeUpTimer(&hrtc);
TimeStamp
![](http://istarik.ru/uploads/images/00/00/01/2019/02/23/12a4bc.jpg)
Прикольная функция. Если на пин РС13 подать внешний импульс, тогда в специальные регистры будут записаны текущие время и дата. Настройка только одна и она ничем не отличается от того, что написано в главе «Tamper для F103 и F303». То есть нужно указать фронт сигнала и подтянуть пин.
В бесконечном цикле сделайте так:
/* USER CODE BEGIN WHILE */
while (1)
{
HAL_RTCEx_GetTimeStamp(&hrtc, &sTime, &DateToUpdate, RTC_FORMAT_BIN); // читаем Time/Date Stamp
snprintf(trans_str, 63, "TimeStamp %d:%d:%d\n", sTime.Hours, sTime.Minutes, sTime.Seconds);
HAL_UART_Transmit(&huart1, (uint8_t*)trans_str, strlen(trans_str), 1000);
snprintf(trans_str, 63, "DateStamp %d-%d-%d\n", DateToUpdate.Date, DateToUpdate.Month, DateToUpdate.Year);
HAL_UART_Transmit(&huart1, (uint8_t*)trans_str, strlen(trans_str), 1000);
HAL_RTC_GetTime(&hrtc, &sTime, RTC_FORMAT_BIN);
snprintf(trans_str, 63, "Time %d:%d:%d\n", sTime.Hours, sTime.Minutes, sTime.Seconds);
HAL_UART_Transmit(&huart1, (uint8_t*)trans_str, strlen(trans_str), 1000);
HAL_RTC_GetDate(&hrtc, &DateToUpdate, RTC_FORMAT_BIN);
snprintf(trans_str, 63, "Date %d-%d-%d\n\n", DateToUpdate.Date, DateToUpdate.Month, DateToUpdate.Year);
HAL_UART_Transmit(&huart1, (uint8_t*)trans_str, strlen(trans_str), 1000);
HAL_Delay(1000);
...
Прошейте МК и коротните РС13 на «землю».
Данные из регистров записываются в структуры времени и даты (чтоб не создавать дополнительные структуры).
Обратите внимание на то, что регистры обнуляются после чтения.
Прерывание то же что и у Tamper…
![](http://istarik.ru/uploads/images/00/00/01/2019/02/23/fe0285.jpg)
А колбек свой:
/* USER CODE BEGIN 0 */
void HAL_RTCEx_TimeStampEventCallback(RTC_HandleTypeDef *hrtc)
{
snprintf(trans_str, 63, "TimeStamp\n");
HAL_UART_Transmit(&huart1, (uint8_t*)trans_str, strlen(trans_str), 1000);
}
Calibration
В мануале про этот выход сказано так:
«Выход RTC_CALIB используется для генерации сигнала переменной частоты. В зависимости от пожелания пользователя этот сигнал может играть роль опорной частоты для внешнего устройства или его можно подключить к зуммеру для генерации звука.»
Есть два варианты частоты — 1Гц и 512Гц…
![](http://istarik.ru/uploads/images/00/00/01/2019/02/23/7045a8.jpg)
Запускается и останавливается этот сигнал функциями…
HAL_RTCEx_SetCalibrationOutPut(&hrtc, RTC_CALIBOUTPUT_1HZ); // или RTC_CALIBOUTPUT_512HZ
HAL_RTCEx_DeactivateCalibrationOutPut(&hrtc);
Можно помигать или попищать при срабатывании будильника.
Для калибровки часов этот выход нужно подключить к осциллографу и добиваться необходимой частоты двумя способами:
1. Манипулировать предделителями — грубая калибровка.
2. С помощью пропусков (маскировки) или добавления тактов — мягкая калибровка.
Осциллографа у меня нет поэтому я особо в этом не разбирался. За мягкую калибровку отвечает функция
Reference clock detection — на это пин можно подать опорную частоту (50 Гц) из розетки. Проводить эксперименты я не решился
![](https://istarik.ru/uploads/images/00/00/01/2019/02/23/0d47aa.png)
В мануале есть такая картика…
![](http://istarik.ru/uploads/images/00/00/01/2019/02/23/ca64b6.jpg)
В статье не описаны некоторые функции — посмотреть их можно в файлах stm32f3xx_hal_rtc.c и stm32f3xx_hal_rtc_ex.c.
На этом всё.
Всем спасибо
![](https://istarik.ru/uploads/images/00/00/01/2019/10/17/1db9cc.jpg)
мануал AN3371
Телеграм-чат istarik
Телеграм-чат STM32
![](http://istarik.ru/uploads/images/thnd.png)
- 0
- stD
73838
Поддержать автора
Комментарии (0)