STM32 - RTC

EEC·2025년 2월 24일

STM32

목록 보기
5/9

rev. 2502241046 : 첫 작성.


오늘은 RTC에 대해서 학습해보자.

STM32에서는 RTC를 내장해서 제공해주고 있다.

RTC는 처음 다뤄보니 RTC가 무엇인지부터 확인해보자.

RTC

RTC는 Real Time Clock의 약어이다.
이 장치의 목적은 Board 전원의 공급이 Off(혹은 sleep mode) 되더라도 시간을 지속적으로 확인할 수 있는데 의미가 있다.

예를 들어,
특정 시간에 어떤 이벤트를 발생시키거나, 데이터를 로깅하거나, 시스템에 전력을 공급하는 전력 관리 시스템이 필요한 경우에 응용될 수 있다.(wake up 기능 사용)

일반적으로, RTC는 세 가지 기능을 제공한다고 한다.
ⓐ 시간 및 날짜를 관리(설정 혹은 읽기)
ⓑ 알림 기능(특정 시간에 이벤트 트리거)
ⓒ 타이머 기능(일정 시간 간격으로 주기적인 작업 수행)

다만, 전원이 off된 상태에서도 RTC에는 전원이 공급되어야 하기 때문에, 별도의 배터리를 RTC에 연결해주어야 한다.

STM32의 하드웨어 관련 문서에 보면 RTC는 다른 장치와 다르게 VBAT핀에 연결된 것을 확인할 수 있다.

그럼 이제 STM32의 RTC 사용법에 대해 학습해보자.

RTC Parameters & registers

  • RTC에서 32.768kHz의 Clock을 써야 하는 이유
    시간 기반의 장치이기 때문에 정확한 1초 구현을 위해 해당 Clock을 사용

내 Board에는 32.768kHz의 Clock Source(LSE)가 없기 때문에 40kHz의 LSI밖에 사용할 수 없다.
따라서, 정확한 시간을 측정할 수 없으니 동작 위주의 테스트만 우선 해보자.

위 사진들은 RTC 기능 사용 시 선택할 수 있는 Option들 혹은 Parameter들이다.

우선 Calendar 기능은 시간 및 날짜 설정, 알람 기능 등의 기능을 제공해준다. RTC를 사용할 거라면 이 기능은 무조건 check해주면 된다.

그 다음 눈 여겨볼 건 Data Format이다.
선택 옵션은 두 가지가 있다.

Binary data format : 시간 및 날짜를 10진수 형태로 설정
(ex. 25년 2월 24일 11시 44분 -> 2502241144)
BCD data format : 시간 및 날짜를 16진수 형태로 설정
(ex. 25년 2월 24일 11시 44분 -> 0x2502241144)

일반적으로, Binary 형태를 많이 쓴다고 한다.
BCD는 RTC 관련 데이터가 고정적인 Memory 공간을 사용한다는 장점이 있다.

그 밑에는
auto predivider calculation 기능에 대해서 나와있는데, 주파수를 낮춰주는 회로라고 한다.(prescaler)
초는 1Hz 단위로 값이 카운트되어야 정확한데, 입력된 Clock Source를 1Hz로 초를 카운트해줄 수 있도록 자동으로 변환해준다는 얘기같다.
이러면 굳이 32.768kHz를 사용하지 않아도 된다는 얘기 같은데, 정확한건 테스트 해보자.

실습

실습은 Uart 통신으로 1초마다 날짜와 시간을 출력해주는 프로그램을 만들어보자.

// app.c
#include "app.h"

RTC_TimeTypeDef sTime = {0};
RTC_DateTypeDef sDate = {0};

void app_init()
{
	// application init

	sTime.Hours = 19;
	sTime.Minutes = 58;
	sTime.Seconds = 00;
	HAL_RTC_SetTime(&hrtc, &sTime, RTC_FORMAT_BIN);

	sDate.WeekDay = RTC_WEEKDAY_MONDAY;
	sDate.Month = RTC_MONTH_FEBRUARY;
	sDate.Date = 24;
	sDate.Year = 25;
	HAL_RTC_SetDate(&hrtc, &sDate, RTC_FORMAT_BIN);
}

void app_main()
{
	app_init();

	// variable
	uint8_t tmp = 100;

	while(1)
	{
		// main loop
		HAL_RTC_GetTime(&hrtc, &sTime, RTC_FORMAT_BIN);
		HAL_RTC_GetDate(&hrtc, &sDate, RTC_FORMAT_BIN);

		if (sTime.Seconds != tmp) printf("%d년 %d월 %d일 %d시 %d분 %d초\n\r", sDate.Year, sDate.Month, sDate.Date, sTime.Hours, sTime.Minutes, sTime.Seconds);
		tmp = sTime.Seconds;
	}
}

HAL API를 사용한 구현방법은 위와 같다.

우선,
ⓐ Time, Date 타입 구조체를 선언해준다.
ⓑ 구조체의 각 변수들의 값을 세팅해준다.
ⓒ SetTime, SetDate 함수를 사용해 지정된 데이터 포맷으로 세팅해준 값을 저장한다.
ⓓ GetTime, GetDate 함수를 사용해 클럭을 이용해 변경되는 시간들을 불러온다.

* 주의할 점
시간을 불러올 때 항상 GetTime과 GetDate는 SET로 사용해야하며,
GetTime 함수를 먼저 호출해야 이상이 없다.

ⓔ 초의 값이 변할 때 마다 출력해준다.

profile
느리지만 확실하게

0개의 댓글