This program demonstrates the RTC timestamp feature of the STM32F4 family of MCUs. The timestamp is activated by one of two external pins (PA0 or PC13 on the STM32F446). Since the PC13 pin is connected to the user button on the Nucleo board, we use it in this demonstration to activate the timestamp. The timestamp feature can be used in either polling or interrupt mode. This demonstration utilizes the interrupt and callback. The ISR in this code simply flags a timestamp overflow by turning on the LED.
The code should be self explanatory. This code is compiled inside the Arduino IDE using the official STM 2.0 Core.
// RTC timestamp demo.
// 1. timestamp occurs when user button is pressed.
// 2. include a sketch level "build_opt.h" file with "-DHAL_RTC_MODULE_ONLY"
// LSI
#define RTC_ASYNCH_PREDIV 0x7F
#define RTC_SYNCH_PREDIV 0x00F9
// LSE
//#define RTC_ASYNCH_PREDIV 0x7F
//#define RTC_SYNCH_PREDIV 0x00FF
RTC_HandleTypeDef RtcHandle;
RTC_TimeTypeDef sTimeStamp;
RTC_DateTypeDef sDateStamp;
volatile bool stamp {false};
static void RTC_TimeStampConfig(void)
{
RTC_DateTypeDef sDate;
RTC_TimeTypeDef sTime;
// RTC TimeStamp generation: TimeStamp Rising Edge on PC13 Pin
HAL_RTCEx_SetTimeStamp_IT(&RtcHandle, RTC_TIMESTAMPEDGE_RISING, RTC_TIMESTAMPPIN_PC13);
// Set a date & time.
sTime.Hours = 0x1;
sTime.Minutes = 0x2;
sTime.Seconds = 0x3;
sTime.DayLightSaving = RTC_DAYLIGHTSAVING_NONE;
sTime.StoreOperation = RTC_STOREOPERATION_RESET;
if (HAL_RTC_SetTime(&RtcHandle, &sTime, RTC_FORMAT_BCD) != HAL_OK)
while (1);
sDate.WeekDay = RTC_WEEKDAY_MONDAY;
sDate.Month = RTC_MONTH_SEPTEMBER;
sDate.Date = 0x14;
sDate.Year = 0x0;
if (HAL_RTC_SetDate(&RtcHandle, &sDate, RTC_FORMAT_BCD) != HAL_OK)
while (1);
}
void RTC_Init(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct;
RCC_PeriphCLKInitTypeDef RCC_RTCPeriClkInit;
// 1. Turn on the LSI
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_LSI;
RCC_OscInitStruct.LSEState = RCC_LSI_ON;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
while (1);
// 2. Select LSI as RTCCLK
RCC_RTCPeriClkInit.PeriphClockSelection = RCC_PERIPHCLK_RTC;
RCC_RTCPeriClkInit.RTCClockSelection = RCC_RTCCLKSOURCE_LSI;
if (HAL_RCCEx_PeriphCLKConfig(&RCC_RTCPeriClkInit) != HAL_OK)
while (1);
__HAL_RCC_RTC_ENABLE();
// Configure the NVIC for RTC TimeStamp.
HAL_NVIC_SetPriority(TAMP_STAMP_IRQn, 0x0F, 0);
HAL_NVIC_EnableIRQ(TAMP_STAMP_IRQn);
// Configure RTC prescaler and RTC data registers
// - Hour Format = Format 12
// - Asynch Prediv = Value according to source clock
// - Synch Prediv = Value according to source clock
// - OutPut = Output Disable
// - OutPutPolarity = High Polarity
// - OutPutType = Open Drain
__HAL_RTC_RESET_HANDLE_STATE(&RtcHandle);
RtcHandle.Instance = RTC;
RtcHandle.Init.HourFormat = RTC_HOURFORMAT_12;
RtcHandle.Init.AsynchPrediv = RTC_ASYNCH_PREDIV;
RtcHandle.Init.SynchPrediv = RTC_SYNCH_PREDIV;
RtcHandle.Init.OutPut = RTC_OUTPUT_DISABLE;
RtcHandle.Init.OutPutPolarity = RTC_OUTPUT_POLARITY_HIGH;
RtcHandle.Init.OutPutType = RTC_OUTPUT_TYPE_OPENDRAIN;
__HAL_RTC_RESET_HANDLE_STATE(&RtcHandle);
if (HAL_RTC_Init(&RtcHandle) != HAL_OK)
while (1);
RTC_TimeStampConfig();
}
// EXTI line detection callback.
void buttonISR() { stamp = true; }
extern "C" void HAL_RTCEx_TimeStampEventCallback(RTC_HandleTypeDef *hrtc)
{
HAL_RTCEx_GetTimeStamp(&RtcHandle, &sTimeStamp, &sDateStamp, RTC_FORMAT_BIN);
}
// This function handles RTC tamper and timestamp interrupts through EXTI line 21.
extern "C" void TAMP_STAMP_IRQHandler(void)
{
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_RESET);
if (RTC->ISR & RTC_FLAG_TSOVF)
{
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_SET);
CLEAR_BIT(RTC->ISR, RTC_FLAG_TSOVF);
}
HAL_RTCEx_TamperTimeStampIRQHandler(&RtcHandle);
}
void setup()
{
Serial.begin(9600);
while(!Serial);
RTC_Init();
pinMode(LED_BUILTIN, OUTPUT);
attachInterrupt(digitalPinToInterrupt(PC13), buttonISR, RISING);
Serial.println("RTC Timestamp Demo");
}
void loop()
{
RTC_TimeTypeDef sTime;
RTC_DateTypeDef sDate;
char s[16] = { 0 };
HAL_RTC_GetTime(&RtcHandle, &sTime, RTC_FORMAT_BIN);
HAL_RTC_GetDate(&RtcHandle, &sDate, RTC_FORMAT_BIN);
sprintf(s, "%02d:%02d", sTime.Minutes, sTime.Seconds);
Serial.print(s);
if (stamp)
{
sprintf(s, " [%02d:%02d]", sTimeStamp.Minutes, sTimeStamp.Seconds);
Serial.println(s);
stamp = false;
}
else
Serial.println();
HAL_Delay(1000);
}